Files
audita/docs/roadmap/correction-repair.md

293 lines
17 KiB
Markdown

# Correction Repair After Validation
**Updated:** 2026-11-11
**Status:** Implemented. See the [implementation plan](implementation.md)
and the [pipeline guide](../internal/pipeline.md).
## Objective
Give a rejected correction an opportunity to improve using specific validator
feedback, while preserving proposals that have already passed validation. Each
correction module supplies a repair prompt. Each validator supplies findings
within its own remit. Audita coordinates bounded revision conversations and
acceptance through the existing PromptKit runtime.
The unit of repair is an individual correction proposal. Multiple proposals
against one transcript segment remain separately identifiable. A model may revise
the selected proposal or explicitly withdraw it. Every revised proposal must pass
the full applicable validation chain before it becomes eligible for application.
This adds domain revision after rejection. It is distinct from PromptKit's
structural output repair and from obtaining an unavailable validator decision.
The latter remains separate [deferred work](future.md#domain-aware-response-recovery).
## Current Baseline
Reviewed application revision: `8946a82`. Recheck the owning components when
implementation begins, including any subsequent correctness-review fixes.
- The [pipeline](../internal/pipeline.md) partitions the transcript once and runs
ordered stages. Proposals can be generated concurrently; indexing and
application remain deterministic. Approved corrections are applied in proposal
order, with existing replacement and conflict checks.
- [Proposal generation](../internal/modules.md#proposal-generation-ownership)
returns a correction set, potentially with several proposals per segment.
Model-facing segment references are request-local and are mapped to transcript
identities. The four modules are glossary, homophones, spoken-word cleanup,
and grammar.
- The [validator runtime](../internal/validators.md) runs deterministic checks
before LLM-backed checks and filters rejected candidates before later
validators. Decisions already carry proposal identity, disposition, reason code,
and message. Unavailable decisions are distinguished from editorial rejection.
Validator chains are currently selected by module, not individually configured
by operators.
- The [LLM adapter](../internal/llm-runtime.md) uses PromptKit v0.21.0 prepared
execution with ConfigKit v1.2.0. It captures prepared-request data and final
response text. Proposal-generation results carry candidates, operation outcomes,
and artifact references, but do not retain a conversation for domain revision.
- [Embedded prompts](../internal/prompts.md) live in the `audita` collection and
support operator replacement through native underlays. Audita supplies response
schemas separately. Full interaction artifacts are optional debug output.
- Existing `llm.repair_attempts` controls structural repairs. It is not a budget
for the proposed domain revision loop. No such loop is implemented.
## Targeted End State
### Proposal Lifecycle
1. Generate the initial correction set using the stage's instruction, transcript
section, relevant glossary/protection data, and response schema.
2. Validate candidates, collecting findings from checks that can meaningfully
evaluate them. Checks that cannot run do not become invented rejection reasons.
3. Retain approved proposals for application. Give each rejected proposal a repair
branch containing its conversation and findings. Budget and eligibility rules
determine whether another request can run.
4. Request revision or withdrawal of that one proposal. An accepted withdrawal
ends the branch without an edit. A revised proposal returns to the complete
applicable validator chain; approvals of a previous version do not transfer.
5. Continue until approval, withdrawal, budget exhaustion, or a classified failure.
Preserve independently accepted work under the existing partial-success rules.
6. Apply accepted corrections in deterministic proposal order, retaining the
existing apply-time checks for stale spans, protection, and conflicts.
Withdrawal or exhaustion contributes no edit from that proposal. Other accepted
proposals against the same segment may still change its text. Retaining an
approval does not guarantee application when another edit makes it inapplicable.
This feature does not add a second repair loop for application-time conflicts.
Each revision remains associated with the original proposal and its processing
stage and section. Repair responses must identify the requested proposal; unrelated
edits do not become additional candidates. Revisions may correct the proposed
span or target reference within the original section context, as specified in
[the accepted target decision](#revising-the-span-or-target-reference).
Exact internal types and model-facing reference spelling are implementation
choices, not new globally unique identity requirements.
### Full Conversation and Independent Branches
The first repair request contains the complete initial rendered request messages,
with their original roles and order, followed by the complete assistant response
that supplied the decoded proposal set, then the targeted repair instruction.
Retain the original section and request inputs for this purpose; do not rebuild
the conversation from a transcript already changed by other corrections.
Every proposal branches independently from that same initial exchange. Later
attempts append that proposal's previous repair response and new feedback to its
own branch. Repairs of other proposals never become turns in that conversation.
Keep approved proposals outside the set being reconsidered. Branch scheduling
must not change proposal attribution or final application order.
Here, conversation history means the application-level message exchange. Preserve
the full response used for candidate decoding rather than serializing only the
failed proposal as if it were the model's original answer. Provider transport
attempts and PromptKit's internal structural-repair operations remain accounted
for separately. Do not manufacture hidden provider messages or reasoning.
Keep required conversation state in memory when repair is enabled, independently
of debug artifact saving. Its lifetime need only cover the associated work; this
does not introduce durable conversation storage or restart/resume support. Send
the full replay and feedback under the revision output contract, subject to the
selected provider's [request limits](#provider-request-limits).
### Module Repair Prompts and Response Contract
Each built-in correction module owns a corresponding repair definition in the
`audita` namespace, alongside its proposal definition. Use the existing embedded
filesystem and ConfigKit underlay mechanism so operators can replace repair
prompts without rebuilding Audita. Shared instruction fragments may be reused;
module-specific instructions stay with the module's prompt.
The repair instruction identifies the proposal, repeats its original and proposed
replacement text, presents the findings, and asks for a revision or withdrawal.
It explains that only this proposal is under review and states the response
contract for this turn. This must remain clear even though the initial prompt
requested a complete correction set. Later turns refer explicitly to the current
proposal version rather than relying on an ambiguous "last message" reference.
Use a structured response that distinguishes revision from withdrawal and carries
the requested proposal reference. A revision contains the correction data needed
by the existing validators. Empty replacement text remains a possible span
deletion; it must not double as a withdrawal signal. The response schema owns
shape validation. Audita owns correspondence and domain acceptance.
### Validator-Owned Feedback
Validators contribute their own actionable findings: validator identity, stable
reason code, an explanation, and relevant evidence or constraints where available.
Build on existing decision data rather than creating a parallel reason registry.
For example, a protection finding can identify the spelling affected, while an
editorial finding can explain the meaning change it detected.
The module repair template owns presentation of the collected findings.
Validators do not construct chat histories or own the correction response schema.
Order feedback by the applicable validator chain for understandable reports and
prompts. Model-backed validators should contribute their assessment through the
existing structured decision path.
Collect failures from all applicable checks that can meaningfully evaluate the
candidate. A malformed target may prevent contextual checks; a provider failure
means the assessment is unavailable, not that the edit violated a domain rule.
Apply the accepted
[eligibility and continuation policy](#feedback-eligibility-and-unavailable-validation).
Making validator chains operator-configurable is not required by this feature.
### Ownership and Library Integration
Audita owns proposal lineage, semantic feedback, branch state, revision budgets,
revalidation, and transcript application. PromptKit continues to own rendering,
profile/backend selection, transport retry, structural repair, and per-backend
admission. Configuration continues through ConfigKit's native resolution and
the existing root/stage scope conventions. Standard CommandKit inspection and
request commands expose the configured prompt assets through their normal APIs.
PromptKit already supports
[appending rendered assistant and corrective messages](https://forge.maximumdirect.net/base-layer/promptkit/src/commit/171fb11f4e967a1da3af57843c6467954b14ba09/docs/consumers/pkg-promptkit.md#append-already-rendered-messages).
Use its public preparation and execution APIs to render the module repair
definition and assemble the intended conversation from rendered messages. Use
its per-call schema selection for the revision contract.
Maintain the existing distinctions between recoverable model-operation failures,
fatal application/invariant failures, and cancellation. Domain revision attempts
are additional logical calls, each potentially containing PromptKit retries and
structural repairs; account for these separately. Share existing backend admission
and cancellation instead of adding a repair-specific global concurrency limiter.
Use the accepted [reporting scope](#ordinary-reports-and-attempt-history).
## Acceptance and Completion
Use controlled model responses and real loading/rendering at integration
boundaries. Cover the following behavior with proportionate tests:
- One approved and one rejected proposal from the same response: repair only
the rejected proposal, then apply the accepted results in deterministic order.
Include several proposals against one segment and an overlapping-edit case.
- Full initial messages and full response retained, correct roles and ordering,
explicit proposal selection, independent branches, and a second repair turn
containing only its own branch's history. Exercise debug enabled and disabled.
- Repair success, explicit withdrawal, budget exhaustion, the default of one
semantic attempt, additional configured attempts, and global or stage-level
zero disabling both repair and extra feedback collection. Distinguish
withdrawal from an empty-string deletion proposal.
- Validator-owned findings collected under the accepted continuation policy;
inapplicable or unavailable checks do not masquerade as editorial rejection.
Cover known rejection alongside an unavailable assessment, unavailable
assessment alone, and a no-effect proposal finishing without repair.
Revised candidates must pass all applicable checks, including checks that
approved their earlier versions.
- Wrong proposal references and unusable repair responses cannot introduce
unrelated edits or approval. Preserve ordinary identity reconciliation and
structural validation; no generic salvage of malformed JSON is implied.
- A revision can correct its source span or segment reference within the original
request's section, preserving proposal lineage and passing ordinary target
mapping and full validation.
- A provider error on a repair request, including a context-size rejection,
fails only that proposal after any applicable PromptKit retries. Other approved
work remains eligible for application. Cover structural-repair exhaustion and
cancellation under the existing failure boundaries. Account for semantic
attempts, structural repairs, and transport retries separately.
- Embedded module repair prompts and operator replacements work through the
shared engine. Root and stage settings follow the accepted scope and fallback
rules, including inheritance of the effective proposal profile after stage
settings are combined and explicit repair-profile overrides. Verify that
ordinary reporting records one compact outcome per repair branch and that
optional redacted debug output carries the detailed attempt history.
Run focused checks during development and assembled application validation at
completion under the [testing policy](../policy/testing.md). Representative
transcript comparisons can help tune prompts and defaults, but this roadmap
sets no numerical quality threshold or requirement for paid provider calls.
Completion requires the agreed loop and accepted policies, acceptance evidence,
and updated canonical documentation. Successful schema validation alone is not
evidence that a revised correction is acceptable.
## Accepted Decisions
### Semantic Repair Budget and Configuration Scope
Allow one additional semantic repair attempt per rejected proposal by default,
configurable at the root and per stage. Zero disables both the repair loop and
extra feedback collection. A revision that fails validation can continue when
the operator configures more attempts. Use a distinct setting from structural
`llm.repair_attempts`.
Retain existing per-call timeouts and parent cancellation, and document that
each semantic attempt may include transport retries and structural repairs.
This provides useful feedback-driven revision with a simple finite bound.
### Provider Request Limits
Submit the full repair conversation and let the selected provider enforce its
request limits. If a provider error prevents revision after any applicable
PromptKit retries, including when the conversation exceeds the provider's context
window, record the repair as unavailable and end that proposal's branch.
Continue processing other proposals. Audita's existing fatal application error
and cancellation behavior still applies.
### Repair Execution Profile
Inherit the effective proposal profile by default, with an optional root/per-stage
repair-profile override. Resolve fallback after stage
settings are combined, following the existing validation-profile pattern. This
keeps ordinary configuration small while allowing a different model for a
difficult revision. Backend capacity remains shared through PromptKit.
### Feedback Eligibility and Unavailable Validation
When repair is enabled, collect all meaningful deterministic failures, then run
the applicable semantic validators when the candidate has the usable target and
before/after data they need, even if another independent check rejected it. With
an effective repair budget of zero, later validators receive only the candidates
that advance under the current validation flow.
An actionable rejection may enter repair; no-effect proposals can finish without
repair because they contribute no edit. Build a small applicability map from
the actual checks rather than running validators on unusable inputs or encoding
universal dependencies between them.
Keep unavailable validation as a separate operation outcome. If a proposal also
has an actionable rejection, its repair may proceed using the known findings,
with unavailable assessments identified as such; any revision still needs a full
successful validation chain. An unavailable assessment by itself should retain
the current unavailable outcome, leaving decision-recovery calls to the deferred
feature. This produces useful feedback without treating infrastructure failure
as evidence against the proposed wording.
### Ordinary Reports and Attempt History
Use one compact repair-outcomes section in ordinary reporting. Give each repair
branch one entry with the original proposal reference, its attempt count, and
final disposition. Use the existing work-unit context for stage and chunk
identity. Make it clear whether an approved revision was applied. Record
operational errors and recoveries through the existing report framework and keep
the current exit-status policy.
Editorial rejection and voluntary withdrawal are correction outcomes. Keep
conversation text and per-attempt details in optional redacted debug artifacts.
### Revising the Span or Target Reference
Allow the revised proposal to correct its original-text span and segment
reference within the original request's section, while retaining its
proposal lineage. Apply the ordinary target mapping, replacement policy, and full
validation to the new candidate. This permits repair of an incorrect source span
or model-facing target reference, both of which can cause validation failures.
It adds no new transcript-wide targeting mechanism.