#33: harden author-coloring PUA sentinels against intra-emphasis markdown #53

Merged
benstull merged 1 commits from s33-sentinel-hardening into main 2026-06-13 15:42:05 +00:00
Owner

#33 (task, P3) — harden the F9/F10 author-coloring PUA sentinels against intra-emphasis markdown, via the token-aware approach recommended in the issue comment.

Fixes both characterized failure modes (session 0032):

  • CASE1 — a span boundary strictly inside a delimiter run (a**b**c, between the two *) split **, breaking markdown-it's pairing (stray <em></em>, raw **).
  • CASE3 — a boundary inside an emphasis run (**bold** covering **bo) rendered the emphasis but misnested span/element (<strong>bo</span>ld</strong>).

Fix (trackChangesModel.ts, pure)

  • injectSentinelsclamp any sentinel offset landing strictly inside a delimiter run (`* _ ~ ``) to the run's start, so a sentinel never splits a run (CASE1). Delimiters are invisible once rendered, so this only shifts the colored boundary across markup; drop spans that clamp to empty.
  • sentinelsToSpans — replace the naive global split/join with a token-aware walker over the rendered HTML: emit the cw-by-* span only around TEXT runs, closing it before any <tag> and reopening after, so a span is always well-nested within inline elements (one span segment per text run — CASE3). Tags copied verbatim with any stray sentinel stripped (no PUA leakage).

Pure / vscode-free / deterministic (INV-33). No regression — existing colorByAuthor/renderReview cases stay green; the common no-emphasis case is byte-identical.

Tests

222 unit + 74/5 host E2E green. New unit: CASE1 (emphasis intact, no stray <em></em>), CASE3 (<span class="cw-by-human">bo</span>ld</strong>, no misnest), CASE2 regression, no-PUA-leak.

Session 0047.

🤖 Generated with Claude Code

**#33 (task, P3)** — harden the F9/F10 author-coloring PUA sentinels against intra-emphasis markdown, via the token-aware approach recommended in the issue comment. Fixes both characterized failure modes (session 0032): - **CASE1** — a span boundary strictly inside a delimiter run (`a**b**c`, between the two `*`) split `**`, breaking markdown-it's pairing (stray `<em></em>`, raw `**`). - **CASE3** — a boundary inside an emphasis run (`**bold**` covering `**bo`) rendered the emphasis but **misnested** span/element (`<strong>bo</span>ld</strong>`). ## Fix (`trackChangesModel.ts`, pure) - **`injectSentinels`** — **clamp** any sentinel offset landing strictly inside a delimiter run (`* _ ~ \``) to the run's start, so a sentinel never splits a run (CASE1). Delimiters are invisible once rendered, so this only shifts the colored boundary across markup; drop spans that clamp to empty. - **`sentinelsToSpans`** — replace the naive global split/join with a **token-aware walker** over the rendered HTML: emit the `cw-by-*` span only around TEXT runs, closing it before any `<tag>` and reopening after, so a span is always well-nested within inline elements (one span segment per text run — CASE3). Tags copied verbatim with any stray sentinel stripped (no PUA leakage). Pure / vscode-free / deterministic (INV-33). No regression — existing `colorByAuthor`/`renderReview` cases stay green; the common no-emphasis case is byte-identical. ## Tests 222 unit + 74/5 host E2E green. New unit: CASE1 (emphasis intact, no stray `<em></em>`), CASE3 (`<span class="cw-by-human">bo</span>ld</strong>`, no misnest), CASE2 regression, no-PUA-leak. Session 0047. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
benstull added 1 commit 2026-06-13 15:41:55 +00:00
The F9/F10 author-coloring technique injects paired PUA sentinels into prose
source at span offsets, renders, then maps sentinels → cw-by-* spans. Two failure
modes when a span boundary met emphasis markup (characterized in session 0032):
- CASE1: a boundary strictly inside a delimiter run (a**b**c, between the two *)
  split `**`, breaking markdown-it's delimiter pairing (stray <em></em>, raw **).
- CASE3: a boundary inside an emphasis run (**bold** span covering **bo) rendered
  the emphasis but MISNESTED span/element (<strong>bo</span>ld</strong>).

Token-aware fix (both, per the issue #33 comment):
- injectSentinels: clamp any sentinel offset that lands strictly inside a
  delimiter run (* _ ~ `) to the run's start, so a sentinel never splits a run
  (CASE1). Delimiters are invisible once rendered, so this only shifts the colored
  boundary across markup. Drop spans that clamp to empty.
- sentinelsToSpans: replace the naive global split/join with a walker over the
  rendered HTML that emits the cw-by-* span only around TEXT runs — closing it
  before any <tag> and reopening after — so a span is always well-nested within
  inline elements (one span segment per text run, CASE3). Tags are copied
  verbatim with any stray sentinel stripped (no Private-Use-Area char leaks).

Pure, vscode-free, deterministic (INV-33). No regression: existing colorByAuthor /
renderReview cases stay green; the common no-emphasis case is byte-identical.

222 unit + 74/5 host E2E green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
benstull merged commit c67749a53c into main 2026-06-13 15:42:05 +00:00
Sign in to join this conversation.