Skip to content

TTSR paragraph-repeat detector misses near-repeat drift (exact hash match); needs normalized match gated by progress #1330

Description

@code-yeongyu

Summary

The TTSR paragraph-repeat detector landed in #1326 (packages/coding-agent/src/core/extensions/builtin/ttsr/detectors/collapse-paragraphs.ts) matches paragraphs by exact content: two hashes (FNV-1a style + djb2) plus the UTF-16 length (isSameParagraph), counted over a 64-entry ring, threshold 3, paragraphs >= 64 chars / 24 word chars.

Because the match is exact, a near-repeat loop escapes it: a model that re-narrates the same paragraph while only a counter, timestamp, or clause order drifts ("Now writing step 3...", "Now writing step 4...") produces distinct hashes, so the repeat count never reaches 3 and the stream runs until the user aborts. Interleaved repeats (A B A B A B) are already covered because the ring is windowed, not consecutive.

Constraint on the fix

Loosening the match alone (whitespace/number masking before hashing) re-creates the false positive this detector was tuned to avoid: a legitimate list traversal that prints "processing item N" for N = 1..k collapses to one hash and would be interrupted as a loop. So a normalized match needs a progress gate as a precondition, e.g. treat a candidate repeat as a real loop only when no tool call was emitted between the repeats (the incident stream had 0 tool calls over 38K chars) or when tool arguments/checkpoints did not advance. Both halves belong in one change.

Evidence

  • Incident and replay analysis: sionicai session 01a06648 (2026-09-03), 38,193-char single text part, 7-paragraph cycle repeated ~9x, 0 tool calls; the exact-cycle case is what fix(ttsr): interrupt within-message paragraph repetition #1326 now catches.
  • Source: collapse-paragraphs.ts isSameParagraph (hashA/hashB/utf16Length equality), PARAGRAPH_REPEAT_THRESHOLD = 3, PARAGRAPH_RING_CAPACITY = 64.

Surfaced while answering a community question in the Ultraworkers Discord (#chat-ko, 2026-09-03).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions