code-yeongyu / code-yeongyu/senpi
TTSR paragraph-repeat detector misses near-repeat drift (exact hash match); needs normalized match gated by progress
- Dominant language
- TypeScript
- Stars
- 429
- Forks
- 98
- Avg merge
- 5h 3m
- Merged PRs (30d)
- 526
Description
## 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 #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).
Contributor guide
Research direction
Start in packages/coding-agent/src/core/extensions/builtin/ttsr/detectors/collapse-paragraphs.ts, reading isSameParagraph and the 64-entry ring, threshold, and length limits. Trace how repeats relate to emitted tool calls or advancing checkpoints before deciding how the progress gate fits. Done means near-repeat drift is detected without interrupting legitimate progressing lists, while exact repeats and interleaved repeats retain their intended behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- ai
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100