Skip to content

Add Reflection Cycle (Ralph's Loop) for iterative goal-driven sessions#92

Merged
PureWeen merged 20 commits intomainfrom
copilot/add-symbolic-loop-mechanism
Feb 17, 2026
Merged

Add Reflection Cycle (Ralph's Loop) for iterative goal-driven sessions#92
PureWeen merged 20 commits intomainfrom
copilot/add-symbolic-loop-mechanism

Conversation

Copy link
Contributor

Copilot AI commented Feb 13, 2026

Summary

Adds a Reflection Cycle (internally called "Ralph's Loop") — an iterative, goal-driven prompt mechanism that allows Copilot sessions to autonomously work toward a stated goal across multiple turns.

What's included

Core Model (ReflectionCycle.cs)

  • Tracks iteration count, max iterations, goal text, and stall detection
  • Uses [[REFLECTION_COMPLETE]] sentinel for structured completion detection
  • ConsecutiveStalls counter with configurable threshold for auto-stop
  • ShouldWarnOnStall and BuildFollowUpStatus helpers

Service Integration (CopilotService)

  • StartReflectionCycle() / StopReflectionForSession() API
  • Automatic follow-up prompt generation in CompleteResponse when cycle is active
  • FIFO queue ordering — user messages always take priority over reflection follow-ups
  • /reflect <goal> slash command support

UI (ExpandedSessionView, ChatMessageItem)

  • Purple "Reflecting" status pill with iteration counter (e.g., "Reflecting 3/30")
  • ChatMessageType.Reflection for compact purple badge messages
  • Stall warning messages after consecutive no-progress turns
  • Completion celebration message when goal is achieved

Tests (31 tests)

  • ReflectionCycleTests.cs — sentinel detection, stall logic, iteration limits, follow-up prompts
  • ChatMessageTests.cs — reflection message type factory methods

Performance work moved

Session switching performance optimizations have been moved to branch perf-session-switching for a separate PR.

Copilot AI changed the title [WIP] Add mechanism for symbolic loop implementation Add ReflectionCycle: iterative goal-driven prompt refinement mechanism Feb 13, 2026
Copilot AI requested a review from PureWeen February 13, 2026 05:31
@PureWeen PureWeen force-pushed the copilot/add-symbolic-loop-mechanism branch from 4ab977f to 86e2f8f Compare February 16, 2026 08:18
@PureWeen PureWeen changed the title Add ReflectionCycle: iterative goal-driven prompt refinement mechanism Add reflection cycle with UI: iterative goal-driven prompt refinement Feb 16, 2026
@PureWeen PureWeen force-pushed the copilot/add-symbolic-loop-mechanism branch 2 times, most recently from 6165cdc to 2d5d911 Compare February 16, 2026 22:36
@PureWeen PureWeen changed the title Add reflection cycle with UI: iterative goal-driven prompt refinement Add Reflection Cycle (Ralph's Loop) for iterative goal-driven sessions Feb 16, 2026
PureWeen added a commit that referenced this pull request Feb 17, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PureWeen PureWeen force-pushed the copilot/add-symbolic-loop-mechanism branch 3 times, most recently from 0e1e0cd to 7d0337d Compare February 17, 2026 15:32
Copilot AI and others added 15 commits February 17, 2026 10:05
…ment

Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
…state in Advance method

Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
…rompts

- Replace fragile Contains("Goal complete") with [[RALPH_COMPLETE]] sentinel
  detected via line-anchored regex (eliminates false positives in natural prose)
- Add stall detection via Jaccard similarity (>90% threshold) and exact hash
  matching over sliding window — stops after 2 consecutive stalls
- Improve follow-up prompt: requires progress assessment, discourages premature
  completion, uses "Ralph's Loop" branding
- Update event handler to log stall reason alongside goal-met/max-iterations
- Expand tests from 18 to 31: false-positive guards for old marker and natural
  prose, stall detection, sentinel positioning, prompt content validation
- User interruption already handled in EnqueueMessage (cancels active cycle)

Consulted 5 models (Opus, GPT-5, Gemini 3 Pro, Sonnet, GPT-5.1) for design.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ssages

- Add /reflect slash command: /reflect <goal> [--max N] starts a cycle,
  /reflect stop cancels it. Goal text is also sent as the initial prompt.
- Add status pill in session header: shows '🔄 Reflecting 2/5' with pulse
  animation while cycle is active, clickable to stop
- Add completion system messages in chat: ✅ goal met, ⚠️ stalled,
  ⏱️ max iterations reached — all include the goal text
- Rename all RALPH references to REFLECTION (sentinel, branding, docs)
- Wire OnStopReflection EventCallback through ExpandedSessionView
- Update /help to document the new command

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…arnings

- Add ChatMessageType.Reflection with purple compact rendering — auto
  follow-ups now show as '🔄 Iteration 2/5' instead of full prompt text
- Don't cancel cycle on user message — queued user messages run alongside
  the reflection loop, allowing mid-loop steering
- Add stall warning system message on first stall detection, before the
  2-stall threshold kills the cycle
- Add skipHistoryMessage to SendPromptAsync — reflection follow-ups go to
  the SDK but don't add a verbose user message to History
- Persist reflection/stall/completion messages to chat DB
- Expose ConsecutiveStalls and ShouldWarnOnStall on ReflectionCycle
- Add IsReflectionFollowUpPrompt helper for prompt type detection
- 3 new tests (334 total passing)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ntrol

- Rich /reflect help: typing /reflect with no args shows interactive guide
  with quick start examples, how-it-works, and all available commands
- Goal text in iteration messages: BuildFollowUpStatus JSON includes summary
  field with truncated goal ("🔄 Iteration 2/5 — Fix tests")
- Context usage warnings: yellow at 70%, red at 90% during active reflection
  cycle to prevent context exhaustion
- Rich completion summary: BuildCompletionSummary() shows emoji, goal, iteration
  count, duration, and outcome (including similarity % for stalls)
- Stall similarity %: CheckStall() now exposes LastSimilarity score, shown in
  warning messages ("91% similarity with previous response")
- Progress indicator on pill: reflection pill shows fill progress bar and
  truncated goal text, plus paused state indicator
- Pause/resume: /reflect pause and /reflect resume commands for inspecting
  progress without cancelling the cycle
- StartedAt/CompletedAt timestamps on ReflectionCycle for duration tracking
- IsPaused state prevents Advance() from incrementing while paused
- 14 new tests (45 total): pause/resume, similarity exposure, completion
  summary variants, duration tracking, long goal truncation
- Updated /help to document pause/resume commands

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… busy

- Send goal as initial prompt via SendPromptAsync when session is idle,
  or EnqueueMessage when session is already processing
- Add SkipReflectionEvaluationOnce flag on SessionState to prevent
  evaluating the pre-existing response against the reflection goal
- Show queued status message when cycle starts during active processing

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Task.Run + delay allowed the copilot agent to race and grab the session
before the queued reflection prompt could be sent. Now dispatches
immediately on the current synchronization context via fire-and-forget
SendPromptAsync, with ContinueWith re-queuing on failure.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…all reset

- Marshal ContinueWith re-queue callback to UI thread via InvokeOnUI
- Purge queued reflection follow-up prompts on StopReflectionCycle
- Escape session name in JS eval with EscapeForJs helper
- Dispatch immediately on resume when session is idle
- Add ResetStallDetection() and call on resume to avoid false stalls
- Use int.TryParse with clamping for --max to prevent OverflowException

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The tests hardcoded 'copilot' but on Windows the binary is 'copilot.exe'.
Added CopilotBinaryName helper and 'win-x64' to alternative RIDs fallback,
matching the logic already in CopilotService.GetBundledCliPath().

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Create a hidden evaluator session (gpt-4.1) on cycle start to judge
  worker responses independently instead of self-evaluation
- Evaluator receives goal + latest response, returns PASS/FAIL format
- Worker gets specific evaluator feedback as next iteration prompt
- Evaluator session is hidden from sidebar, auto-cleaned on cycle end
- Falls back to sentinel-based self-evaluation if evaluator unavailable
- Add AdvanceWithEvaluation() to ReflectionCycle model
- Add ParseEvaluatorResponse(), BuildEvaluatorPrompt(), BuildFollowUpFromEvaluator()
- Add IsHidden to AgentSessionInfo, filter from GetAllSessions()
- Add 19 new tests for evaluator parsing and cycle behavior (456 total)
- Make StartReflectionCycle async to await evaluator session creation

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
After async evaluator returns and enqueues a follow-up prompt, the
session is already idle (CompleteResponse finished). Explicitly dispatch
the queued message via Task.Run + sync context post when IsProcessing
is false. Also show evaluator PASS verdict in chat on cycle completion.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Filter hidden sessions from ReconcileOrganization to prevent them
  appearing in sidebar groups
- Filter hidden sessions from SaveActiveSessionsToDisk to prevent
  them being restored on app restart

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Evaluator prompt now demands flaws be found in early iterations and
only becomes lenient on the final iteration. This ensures the reflection
loop actually iterates instead of passing on the first attempt.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PureWeen PureWeen force-pushed the copilot/add-symbolic-loop-mechanism branch from fbda2ed to a06d256 Compare February 17, 2026 16:05
PureWeen and others added 4 commits February 17, 2026 10:21
Evaluator now explicitly instructed to find flaws and push for higher
quality in iterations 1-2, ensuring multi-iteration reflection loops.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1. Fix evaluator session leak on CloseSession — call StopReflectionCycle
   at start of CloseSessionAsync to clean up evaluator session
2. Fix PASS false positive — remove fuzzy Contains('PASS') fallback in
   ParseEvaluatorResponse, treat unknown format as FAIL
3. Fix race condition — capture cycle reference in evaluator closure,
   verify with ReferenceEquals before advancing to prevent wrong-cycle
   corruption after user restart
4. Fix unreachable paused pill — change pattern to { IsActive: true,
   IsPaused: false } so paused state is shown correctly
5. Fix resume skipHistoryMessage — add skipHistoryMessage: true to
   prevent reflection follow-up from appearing as user message

Add 13 new tests covering: false positive parsing (surpass, mid-sentence),
strict PASS parsing, cycle identity verification, paused state behavior,
evaluator prompt strictness levels, and evaluator feedback tracking.

565 tests total, all passing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add screenshot_*.png, *.bmp, *.tiff to .gitignore
- Add explicit warnings to copilot-instructions.md:
  NEVER commit screenshots/images/binaries
  NEVER use git add -A blindly — review staged files first
  Always check git status before committing

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PureWeen PureWeen marked this pull request as ready for review February 17, 2026 20:15
@PureWeen PureWeen merged commit dc61f5a into main Feb 17, 2026
@PureWeen PureWeen deleted the copilot/add-symbolic-loop-mechanism branch February 22, 2026 00:15
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.

2 participants