fix: make rework comments reference-safe and bound correction plans

This commit is contained in:
2026-10-13 15:01:32 +00:00
parent a74fb747a5
commit 4e9c46bba2
4 changed files with 280 additions and 6 deletions
@@ -180,6 +180,88 @@ JSON/true flags or archived artifacts alone are not fresh provider readback.
- The adapter computes normalized inputs and passes them to the same verifier used
by `rework_comment.py verify`, rather than accepting caller success flags.
## Approved bounded correction of an existing publication
This is a narrow, separately approved exception to normal rework publication—not
a new create/reuse policy and not an implementation/review eligibility decision.
It applies only when explicit correction approval identifies the same exact,
verified impl-authored top-level PR comment ID, and the active Issue lease, exact
PR endpoint/metadata binding, complete pagination, unique correlation and absence
of duplicate correlation rows are all proven. Approval to correct does not make a
stale review admissible, satisfy the normal rework input gate, authorize product
edits, or claim normal workflow completion.
Before any external write, preserve the original baseline bytes and digest,
failed verification output/receipt, and source timeline event as immutable
historical evidence. Never replace, hide, repair in place, recapture over, or
reinterpret the original baseline or failed verify. A fresh readback snapshot is
a separate artifact explicitly labeled as a correction snapshot and bound to the
historical-baseline digest and the independently recorded correction authority.
It detects present state; it does not erase source drift, retroactively validate
the old workflow, or yield its original verified handoff.
The only candidate correction is a pure canonical `prepare-correction` plan.
The executable command prepares private JSON only; it does not PATCH and it
cannot emit a verified handoff/correction receipt:
```sh
python3 -B <HARNESS_ROOT>/harness/agents/impl/skills/gitea-issue-rework/scripts/rework_comment.py prepare-correction \
--previous-expected <ARCHIVED_FAILED_EXPECTED> \
--expected <NEW_RENDERED_EXPECTED> \
--comment-id <EXACT_EXISTING_COMMENT_ID> --actor-id <STABLE_IMPL_ID> \
--output <PRIVATE_CORRECTION_PLAN>
```
The output is `gitea-rework-correction-plan/v1`, with `approval_required=true`,
`prior_handoff_verified=false` and no native write/readback proof. The old and
new inputs and any existing plan are never overwritten.
The plan proves the legacy body has the exact three label-line format for Source Issue,
Pull Request and Source Review, changes those human-readable values to plain
decimal numbers, preserves all other human-readable semantics and every hidden
marker identifier/correlation input unchanged, then recomputes the marker-free
body `result-sha256` and canonical marker. It must prove there are no changed
findings, result/status, reviewed/final head, contract digest, PR body semantics,
marker identity or other semantic differences. The plan helper is a pure
preparation/validation function: it performs no native write and provides no
approval assurance. Any non-exact legacy format or additional body/marker change
is unsupported and must stop before mutation. Existing same-correlation,
different-body cases remain fail-closed under ordinary create/reuse; this
correction exception is not permission to create another comment or broaden
reuse.
Only the main impl workflow, with separate explicit correction approval and the
active Issue lease, may execute the single PATCH. Immediately before that PATCH,
perform fresh unchanged checks against the correction snapshot: exact target,
comment ID, unique correlation/no duplicates, author identity, current body,
Source Issue, PR, underlying PR-Issue, reviews, inline evidence, complete
collections and provider contract must still match, with the expected API status
and version token derived from the matching source response. If any material
state drifted, the API lacks a trustworthy status/version precondition, or
one-time conditional PATCH semantics cannot be established, stop as partial;
do not substitute POST, retry, delete, or restore source state.
After PATCH, read back the exact same comment ID and verify actor stable account
ID, immutable `created_at`, URL, full scoped collection count, exact corrected
body, recomputed result digest and unchanged marker identity/correlation. Prove
all old rows, reviews, inline evidence, Source Issue fields and entire metadata
(including `updated_at`), timeline, and cached counter are unchanged. Only this
comment's body/result hash/marker and a provider-verified comment `updated_at` or
revision may change, and only with the version/precondition proof. A PR or
underlying PR-Issue `updated_at` may change only when the exact timestamp is
explained by the provider's verified correction semantics. Any unexplained delta,
missing field, incomplete pagination or unsupported semantic is partial and
stops further action. Never delete comments, duplicate-POST, restore or rewrite
the Source Issue, perform a native review, or clean up source timeline history.
Archive the original failed baseline and failed verification as still incomplete.
Issue a distinct correction receipt, explicitly linked to the historical baseline
digest, approval authority, fresh correction snapshot, same comment ID and
verified post-PATCH readback. This receipt is not the original `gitea-rework-handoff`
receipt and cannot turn the original workflow into a verified completion. The
source-repair record reports only the bounded correction and its limitations;
no product edits or claim that an old/stale review is admissible.
## Limits and verification
The CLI enforces verified HTTPS, no redirects, GET-only requests, a one-megabyte