From f142f0ab3a912b1bb5019478715f152eb18f1a91 Mon Sep 17 00:00:00 2001 From: Yash Raj Pandey Date: Thu, 18 Jun 2026 11:50:54 -0400 Subject: [PATCH] fix(agent-edit): stop replace from orphaning a closing on wrapped authored spans expandRangeToIncludeFullyWrappedAuthoredSpan only expanded the edit range when it exactly equalled a span's content bounds. When anchor resolution strips authored spans it can return a range that includes the opening tag but stops at the content edge (e.g. [openStart, contentEnd]), so the exact-equality check missed and the trailing was left behind as an unbalanced tag (Hello earth!). Expand whenever the resolved range covers the full span content and lies within the span's outer bounds; a partial-content edit does not cover the full content, so it keeps its wrapper. Fixes the failing edit-ops case (now 17/17). --- server/proof-span-strip.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/server/proof-span-strip.ts b/server/proof-span-strip.ts index 8ed5e199..5055a627 100644 --- a/server/proof-span-strip.ts +++ b/server/proof-span-strip.ts @@ -429,7 +429,16 @@ export function expandRangeToIncludeFullyWrappedAuthoredSpan( let nextEnd = end; for (const span of listAuthoredProofSpanBounds(markdown)) { - if (nextStart === span.contentStart && nextEnd === span.contentEnd) { + // Expand when the resolved range covers the span's entire inner content and + // sits within the span's outer tag bounds. Anchor resolution that strips + // authored spans can return a range that reaches the opening tag on one + // side but stops at the content edge on the other (e.g. [openStart, + // contentEnd]); requiring exact content-bound equality left the unmatched + // tag behind as an orphaned . A partial-content edit does not cover + // the full content, so it is left untouched and keeps its wrapper. + const coversFullContent = nextStart <= span.contentStart && nextEnd >= span.contentEnd; + const withinSpanBounds = nextStart >= span.openStart && nextEnd <= span.closeEnd; + if (coversFullContent && withinSpanBounds) { nextStart = span.openStart; nextEnd = span.closeEnd; break;