Refine the span deletion contract and implementation plan

This commit is contained in:
2026-09-25 02:44:38 +00:00
parent f219309617
commit 31979d4081
2 changed files with 130 additions and 59 deletions

View File

@@ -39,6 +39,9 @@ The source reviewed at `0b6cd98` contains a mismatch:
allows empty replacement text. The
[preview/application logic](../../internal/framework/proposals/preview.go)
supports literal span deletion when the resulting segment remains nonblank.
- Domain shape checks currently reject whitespace-only original spans, although
the response schema permits them and grammar prompts permit spacing cleanup.
This is another restriction to align with the target contract below.
- The validator named `non_empty_corrected_text` actually checks the resulting
segment, not the replacement string. Both this check and application prevent
a segment from becoming empty or whitespace-only. Application changes segment
@@ -53,8 +56,11 @@ of any particular historical incident without its payload and running version.
## Target Correction Contract
- `original_text` identifies an existing, nonblank literal span in the current
target segment. Preserve the existing matching and module replacement policies.
- `original_text` identifies an existing, nonempty literal span in the current
target segment. Whitespace-only spans are eligible; an empty string identifies
no source span and remains invalid. Matching and ambiguity checks still apply
under the module's replacement policy: `require_unique` for grammar, spoken-word,
and homophones; `replace_all` for glossary.
- `corrected_text` remains a required string. An empty string means delete the
identified span; it does not mean remove the segment record or skip validation.
Missing fields and non-string values remain structurally invalid.
@@ -71,8 +77,14 @@ of any particular historical incident without its payload and running version.
- Preserve literal replacement behavior. Prompts should select spans and
replacements that handle adjacent whitespace and punctuation appropriately;
this feature does not add automatic trimming or a second normalization pass.
Whitespace-only replacements are not categorically prohibited: their validity
depends on the resulting text and the ordinary module/domain checks.
Neither side of a correction is rejected solely for containing only whitespace.
For example, reducing a uniquely identified run of two spaces to one space may
be appropriate; validity still depends on the resulting text and domain checks.
Preserve the intended safeguards and outcomes, not every detail of the current
implementation. Validator ordering, internal structure, and payload construction
may change when needed to achieve this consistent contract. Existing behavior or
a passing test does not justify retaining a conflicting restriction.
Illustrative cases:
@@ -80,6 +92,7 @@ Illustrative cases:
| --- | --- | --- | --- |
| `uh hello` | `uh ` | empty string | Structurally valid; may produce `hello` after required validation. |
| `uh hello` | `uh hello` | `hello` | Remains a valid representation of the same cleanup, subject to validation. |
| `hello world` | two spaces | one space | Eligible spacing correction, subject to unique matching and required validation. |
| `uh` | `uh` | empty string | Structurally valid proposal, then filtered because the resulting segment would be blank. |
| `hello world` | `hello world` | spaces only | Filtered because the resulting segment would be blank. |
@@ -89,10 +102,12 @@ a successful no-change outcome.
## Prompt and Module Alignment
Proposal instructions should explicitly describe empty-string deletion and its
resulting-segment limit. Include a concise example where it helps the module's
task. Tell the model to omit a correction that would leave a blank segment rather
than fabricate replacement content or padding to satisfy a schema restriction.
Review relevant prompt definitions for consistency and edit only those needing
clarification. Where needed, explain empty-string deletion, whitespace-only spans,
and the resulting-segment limit with a concise, module-appropriate example. The
model should omit a correction that would leave a blank segment rather than invent
padding or replacement content. Consistent guidance is the goal; adding deletion
language to every prompt is not a requirement.
Retain each module's existing scope:
@@ -111,7 +126,8 @@ remains ordinary processing, not a defect that should be regenerated until appro
The resulting-segment validator's name and documented identity should describe
that responsibility accurately, rather than imply that the replacement string
itself must be nonempty. Preserve the existing blank-result failure reason and
validation order while making that deliberate identity change.
safeguard while making that deliberate identity change; current chain position
and preview implementation are not independent product requirements.
## Outcomes and Reporting
@@ -119,12 +135,22 @@ A legitimate deletion is an ordinary correction. Empty replacement alone must
produce neither structural repair nor a recovery classification. If another
problem required successful repair or filtering, retain that actual recovery.
A schema-valid proposal that would blank a segment is a defective proposal handled
through existing safe filtering. Preserve the `empty_resulting_segment` reason
A schema-valid proposal that would blank its stage-input segment is a defective
proposal handled through existing safe filtering. Preserve the
`empty_resulting_segment` reason
and consolidated `proposals_filtered` recovery behavior; other usable proposals
in the response continue through required validation. Ordinary editorial rejection
remains debug evidence rather than a model error or filtering recovery.
A stage can propose several edits to one segment in the same response. Each edit
is evaluated against the stage input, then approved edits are applied sequentially.
If a proposal was applicable to that input but an earlier accepted edit makes it
unsafe, skip it as an apply-time conflict. Do not count that conflict as a defective
proposal, model error, or filtering recovery. For example, in `"uh um"`, deleting
`"uh "` and deleting `"um"` each leaves text individually; after the first deletion,
the second must be skipped to prevent a blank result. Retain the skipped decision
in debug evidence. The existing runner already distinguishes this situation.
Debug evidence must accurately retain the empty replacement and the corresponding
validation/application outcome. Ordinary reports retain their existing counts and
purpose; no new report schema, incident category, or deletion-specific counter is
@@ -139,10 +165,14 @@ an error for the operation, as today.
transcript while preserving segment metadata and fixed chunk membership.
- A mixed response can apply an approved deletion and another approved correction;
an empty replacement does not invalidate the whole response.
- A proposal that would leave a blank segment is filtered independently, retains
the existing reason, and does not prevent unrelated valid candidates from
succeeding. Application still prevents a blank result if earlier edits change
what a later proposal would do.
- A proposal that would blank its stage-input segment is filtered independently,
retains the existing reason, and does not prevent unrelated valid candidates
from succeeding. A proposal made unsafe only by an earlier accepted edit is
skipped without adding an error or filtering recovery; a blank result is still
prevented and the conflict remains visible in debug evidence.
- A uniquely matching whitespace-only original span can reach validation and
application. Empty originals remain invalid, ambiguous matches remain subject
to module policy, and whitespace-only resulting segments remain disallowed.
- Protected-term and meaning-changing deletions remain subject to their normal
rejection rules. No candidate bypasses required validation.
- A deletion needing no recovery counts as an ordinary applied correction; actual