Skip to content

feat: add streaming loop detection with sentence sampling - #421

Merged
avoidwork merged 4 commits into
mainfrom
feat/streaming-loop-detection
Jun 22, 2026
Merged

feat: add streaming loop detection with sentence sampling#421
avoidwork merged 4 commits into
mainfrom
feat/streaming-loop-detection

Conversation

@avoidwork

@avoidwork avoidwork commented Jun 22, 2026

Copy link
Copy Markdown
Owner

Summary

Add a streaming loop detection mechanism that samples sentences from the active message as it streams in, detects repetition via a sliding window, and issues a silent "You're looping." nudge to break the cycle.

Motivation

The agent can get stuck in repetitive loops — re-checking status, re-running the same commands, or repeating the same phrasing across multiple responses. This wastes time, creates noise, and can lead to catastrophic decisions. A lightweight, streaming-aware detection mechanism catches loops early and gives the agent a chance to self-correct.

Implementation

New Components

Sentence Detector (src/agent/sentence-detector.js)

  • Buffers incoming streaming text chunks
  • Emits complete sentences when boundary characters (., !, ?) are detected
  • Handles partial chunks, multiple sentences per chunk, and edge cases (..., ?!, abbreviations)

Sliding Window Tracker (src/agent/sliding-window-tracker.js)

  • Maintains a 30-second sliding window of recent sentences with timestamps
  • Releases old sentences automatically
  • Tracks sentence frequency with normalization (trim whitespace, lowercase)

Loop Detector (src/agent/loop-detector.js)

  • Combines sentence detector + sliding window tracker into a pipeline
  • Triggers when any sentence appears >3 times within the window
  • Emits { type: 'loop_detected' } callback event

Integration Points

Streaming Pipeline (src/agent/react.js)

  • Loop detector instantiated per-stream in callReactAgentStreaming()
  • Text chunks processed through detector before emitting to callback
  • Detector reset on abort, completion, and error

TUI Handling (src/tui/app.js)

  • Added handler for loop_detected events
  • Displays "You're looping." as a silent nudge in the tool call display area
  • Non-disruptive — doesn't interrupt the stream

Testing

  • Unit tests for sentence detector (boundary detection, buffering, edge cases)
  • Unit tests for sliding window tracker (add, expire, frequency counting, normalization)
  • Unit tests for loop detector (threshold trigger, no false positives)
  • Integration tests for full pipeline (streaming chunks, loop detection, cleanup, concurrent streams)

Verification

  • All tests pass (1199 pass, 0 fail)
  • Lint passes (0 warnings, 0 errors)
  • Coverage maintained
  • Modules import without errors

Files Changed

  • src/agent/sentence-detector.js — New sentence boundary detection component
  • src/agent/sliding-window-tracker.js — New sliding window tracker
  • src/agent/loop-detector.js — New loop detection pipeline
  • src/agent/react.js — Integrated loop detector into streaming pipeline
  • src/tui/app.js — Added loop_detected event handler
  • tests/unit/agent/sentence-detector.test.js — Unit tests
  • tests/unit/agent/sliding-window-tracker.test.js — Unit tests
  • tests/unit/agent/loop-detector.test.js — Unit tests
  • tests/integration/streaming-loop-detection.test.js — Integration tests
  • openspec/changes/streaming-loop-detection/ — OpenSpec artifacts

@avoidwork avoidwork self-assigned this Jun 22, 2026
Add a streaming loop detection mechanism that samples sentences from
the active message as it streams in, detects repetition via a sliding
window, and issues a silent 'You're looping.' nudge to break the cycle.

New files:
- src/agent/sentence-detector.js: Sentence boundary detection component
- src/agent/sliding-window-tracker.js: Sliding window sentence tracking
- src/agent/loop-detector.js: Loop detection pipeline combining detector + tracker

Modified files:
- src/agent/react.js: Integrate loop detector into callReactAgentStreaming()
- src/tui/app.js: Handle loop_detected events as silent nudge

Tests:
- tests/unit/agent/sentence-detector.test.js
- tests/unit/agent/sliding-window-tracker.test.js
- tests/unit/agent/loop-detector.test.js
- tests/integration/streaming-loop-detection.test.js
@avoidwork avoidwork changed the title feat: add streaming loop detection for repetitive agent behavior feat: add streaming loop detection with sentence sampling Jun 22, 2026
@avoidwork

Copy link
Copy Markdown
Owner Author

Audit Results: Streaming Loop Detection

Coverage Audit

  • Goal 1 (Sentence Boundary Detector): Covered by spec "Sentence Boundary Detection" ✓
  • Goal 2 (Sliding Window Sentence Tracker): Covered by spec "Sliding Window Sentence Tracking" ✓
  • Goal 3 (Loop Detection & Nudge Injection): Covered by spec "Loop Detection Threshold" + "Silent Loop Nudge" ✓
  • Goal 4 (Integration with Streaming Pipeline): Covered by spec "Per-Stream Sampler State" + "Integration with Streaming Pipeline" ✓

Fidelity Audit

All specs faithfully represent the original intent of each goal. Key elements preserved:

  • 30-second sliding window ✓
  • 3 occurrence threshold ✓

  • Silent "You're looping." nudge following RECURSION_LIMIT_MESSAGE pattern ✓
  • Per-stream sampler state ✓
  • Integration into callReactAgentStreaming() on_chat_model_stream handler ✓

Completeness Audit

All key requirements and acceptance criteria are captured in specs with scenarios. Minor notes:

  • Edge cases (..., ?!, abbreviations) are covered in tasks 1.5 — acceptable deferral from spec
  • "Debounce rapid successive loops" open question from design is correctly deferred as future enhancement
  • All 4 goals have corresponding spec requirements with at least one scenario each

Consistency Audit

Tasks map correctly to spec requirements:

  • Sentence Boundary Detection → Tasks 1.1-1.6 ✓
  • Sliding Window Sentence Tracking → Tasks 2.1-2.5 ✓
  • Loop Detection Threshold → Tasks 3.1-3.4 ✓
  • Integration with Streaming Pipeline → Tasks 4.1-4.6 ✓
  • Silent Loop Nudge → Tasks 5.1-5.4 ✓
  • TUI handling → Tasks 6.1-6.4 ✓
  • Integration testing → Tasks 7.1-7.5 ✓
  • Verification → Tasks 8.1-8.4 ✓

Verdict

No errors found. Specs are comprehensive, faithful to goals, and tasks map correctly. Proceeding to Step 6.

@avoidwork
avoidwork merged commit 13e0cdb into main Jun 22, 2026
2 checks passed
@avoidwork
avoidwork deleted the feat/streaming-loop-detection branch June 22, 2026 22:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant