Skip to content

fix: exclude error-paused sessions from Auto Run time tracking#731

Open
pedramamini wants to merge 3 commits intomainfrom
242-fix-autorun-time-counting-during-error-pause
Open

fix: exclude error-paused sessions from Auto Run time tracking#731
pedramamini wants to merge 3 commits intomainfrom
242-fix-autorun-time-counting-during-error-pause

Conversation

@pedramamini
Copy link
Copy Markdown
Collaborator

@pedramamini pedramamini commented Apr 5, 2026

Summary

  • Fixes incorrect Auto Run achievement time accumulation during error states
  • Error-paused sessions (errorPaused: true) were still counted in activeBatchSessionIds, causing time to accumulate even while sessions were paused waiting for error resolution
  • Filters out error-paused sessions in useAutoRunAchievements before computing time deltas, while preserving their inclusion in activeBatchSessionIds for UI purposes (sidebar indicators, peak usage stats)

Closes #242

Test plan

  • All 41 useAutoRunAchievements tests pass (38 existing + 3 new)
  • New tests cover: error-paused sessions excluded from time, mixed active/paused sessions, resume after error resolution
  • TypeScript type checks pass (npm run lint)
  • ESLint passes
  • Full test suite passes
  • Manual: Start Auto Run, trigger an error (e.g., SSH connection refused), verify achievement time stops accumulating while error dialog is shown
  • Manual: Retry after error, verify time resumes counting normally

Summary by CodeRabbit

Release Notes

  • Improvements

    • Error-paused batch sessions no longer accumulate auto-run achievement time.
    • Multi-phase auto-run documents are now organized in flat subdirectories instead of nested structures.
  • Documentation

    • Release notes formatting normalized for consistency.

- Standardized multi-phase auto-run docs into one flat, dated subdirectory 📁
- Explicitly banned nested project/feature folder structures for phase outputs 🚫
- Improved guidance for clean lexicographic sorting with zero-padded phases 🔢
- Made it easier to add entire effort folders to auto-run at once ➕
- Clarified organization rules so related phase documents stay tightly grouped 🧭
…cking (#242)

Error-paused Auto Run sessions (errorPaused: true) were still counted in
activeBatchSessionIds, causing achievement time to accumulate even while
the session was paused waiting for error resolution. This could result in
inflated total time and premature badge unlocks.

Filter out error-paused sessions in useAutoRunAchievements before using
them for time delta calculation, while preserving their inclusion in
activeBatchSessionIds for UI purposes (sidebar indicators, peak usage stats).
@pedramamini pedramamini added the bug Something isn't working label Apr 5, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 5, 2026

📝 Walkthrough

Walkthrough

This pull request fixes incorrect time accumulation during auto-run sessions that encounter errors. It modifies the achievement tracking hook to exclude errorPaused sessions from time calculations, adds test cases validating this behavior, updates the maestro system prompt for document organization rules, and reformats the releases markdown file.

Changes

Cohort / File(s) Summary
Markdown Reformatting
docs/releases.md
Normalized formatting from Windows-style CRLF/escaped line breaks to standard Markdown syntax across release notes sections. No content additions or removals.
Auto-Run Achievement Logic
src/renderer/hooks/batch/useAutoRunAchievements.ts
Modified hook to derive activeNonPausedSessionIds by filtering out sessions with errorPaused: true, and updated time delta calculation to use this filtered list instead of all active sessions. Prevents error-paused sessions from accumulating achievement time.
Achievement Hook Tests
src/__tests__/renderer/hooks/useAutoRunAchievements.test.ts
Added three new test cases validating that useAutoRunAchievements correctly excludes errorPaused sessions from: call triggers, time delta multiplier calculations, and time resumption after state transitions.
System Prompt Documentation
src/prompts/maestro-system-prompt.md
Updated multi-phase effort document placement rule to use flat subdirectory structure under {{AUTORUN_FOLDER}} instead of nested structure, and added explicit prohibition on nested subdirectories.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~18 minutes

Possibly related PRs

Poem

🐰 Time once counted when errors dare,
But now paused sessions get no care,
With filtering swift and tests so bright,
Auto-run badges shine just right!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main code change: filtering error-paused sessions from Auto Run time tracking to fix achievement time accumulation.
Linked Issues check ✅ Passed The PR directly implements the fix for issue #242: filtering error-paused sessions from time-delta calculations while preserving them in UI indicators and peak stats.
Out of Scope Changes check ✅ Passed Changes include the core fix plus related documentation updates (release notes, prompt docs) and comprehensive tests—all aligned with the stated objectives.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 242-fix-autorun-time-counting-during-error-pause

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 5, 2026

Greptile Summary

This PR correctly fixes Auto Run achievement time accumulation during error states by filtering errorPaused sessions from the time-tracking multiplier in useAutoRunAchievements. The production logic is sound — batchStore issues new object references on every state change (via batchReducer), so useMemo([activeBatchSessionIds, batchRunStates]) recomputes correctly in the real app. The separation between filtered time-tracking (activeNonPausedSessionIds) and unfiltered peak-stats tracking (activeBatchSessionIds) is intentional and correctly implemented.

  • Core fix (useAutoRunAchievements.ts): useMemo filter + useBatchStore subscription correctly excludes error-paused sessions from deltaMs while preserving them in sidebar indicators and peak-usage stats.
  • Test concern (useAutoRunAchievements.test.ts): The new "resumes counting when error is resolved" test uses in-place mutation of a const object (mockBatchRunStates), meaning useMemo never sees a reference change and never recomputes. The resume path is not actually verified by this test.
  • Style (useAutoRunAchievements.ts:100): The intentional .length-only useEffect dependency is functionally correct but lacks a comment explaining why, leaving it vulnerable to a well-intentioned "exhaustive-deps fix" that would reintroduce timer drift.
  • docs/releases.md and src/prompts/maestro-system-prompt.md contain whitespace/formatting changes only.

Confidence Score: 4/5

Safe to merge — production logic is correct; the only issue is a test that doesn't fully verify the resume-from-error path

Score of 4 reflects that the core hook change is well-implemented and the batchStore correctly issues new object references in production, ensuring useMemo recomputes. One point deducted because the 'resumes counting' test uses in-place mutation and does not actually validate the intended behavior, leaving a gap in test coverage for the resume path.

src/tests/renderer/hooks/useAutoRunAchievements.test.ts — the 'resumes counting' test needs let mockBatchRunStates with full reference replacement (not property mutation) to properly verify the error-resolution resume behavior

Important Files Changed

Filename Overview
src/renderer/hooks/batch/useAutoRunAchievements.ts Correctly filters error-paused sessions via useMemo before time delta; .length-only dep is intentional but undocumented
src/tests/renderer/hooks/useAutoRunAchievements.test.ts Two of three new tests are solid; 'resumes counting' test uses in-place object mutation that won't trigger useMemo recomputation, leaving the resume path uncovered
docs/releases.md Whitespace and formatting normalization only, no content changes
src/prompts/maestro-system-prompt.md Whitespace and formatting normalization only, no content changes

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[activeBatchSessionIds
batchRunStates] --> B[useMemo
filter errorPaused]
    B --> C{activeNonPausedSessionIds
.length === 0?}
    C -- Yes --> D[reset lastUpdateTime = 0
no interval]
    C -- No --> E[setInterval 60s]
    E --> F[deltaMs = elapsedMs
× non-paused count]
    F --> G[updateAutoRunProgress
deltaMs]
    G --> H{newBadgeLevel
!== null?}
    H -- Yes --> I[setStandingOvationData
badge]
    H -- No --> J[wait next tick]
    A2[activeBatchSessionIds
sessions] --> K[Peak Stats Effect
updateUsageStats]
    style D fill:#ffd,stroke:#cc0
    style I fill:#dfd,stroke:#080
Loading

Reviews (1): Last reviewed commit: "style: format docs/releases.md with pret..." | Re-trigger Greptile

Comment on lines +813 to +835
it('resumes counting when error is resolved', () => {
// Start with error-paused session
mockBatchRunStates['session-1'] = { isRunning: true, errorPaused: true };

const { rerender } = renderHook(
({ ids }) => useAutoRunAchievements({ activeBatchSessionIds: ids }),
{ initialProps: { ids: ['session-1'] } }
);

act(() => {
vi.advanceTimersByTime(60000);
});
expect(mockUpdateAutoRunProgress).not.toHaveBeenCalled();

// Resolve error
mockBatchRunStates['session-1'] = { isRunning: true, errorPaused: false };
rerender({ ids: ['session-1'] });

act(() => {
vi.advanceTimersByTime(60000);
});
expect(mockUpdateAutoRunProgress).toHaveBeenCalledTimes(1);
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Test does not verify resume behavior — in-place mutation invisible to useMemo

The test mutates mockBatchRunStates in-place at line 828:

mockBatchRunStates['session-1'] = { isRunning: true, errorPaused: false };
rerender({ ids: ['session-1'] });

mockBatchRunStates is declared as const (line 60), so the useBatchStore mock always delivers the same object reference to its selector. When a property is reassigned, the container reference stays identical.

React's useMemo compares deps with Object.is. Since batchRunStates (= mockBatchRunStates) is the same reference before and after the mutation, useMemo returns the cached [], the effect's dep (activeNonPausedSessionIds.length === 0) never changes, no interval is ever created, and mockUpdateAutoRunProgress is never called — making the toHaveBeenCalledTimes(1) assertion at line 834 a false positive (or vacuous pass).

The fix is to switch mockBatchRunStates to let so the entire reference can be replaced, which useMemo will detect:

// Line 60: change const → let
let mockBatchRunStates: Record<string, any> = {};

// In beforeEach — reassign instead of key-deleting:
mockBatchRunStates = {};

// In the test — replace the full reference:
mockBatchRunStates = { 'session-1': { isRunning: true, errorPaused: false } };
rerender({ ids: ['session-1'] });

Note: the beforeEach reset at lines 138–139 (Object.keys(mockBatchRunStates).forEach(key => delete ...)) must also become mockBatchRunStates = {} for consistency once let is used.

Comment on lines 97 to +100
return () => {
clearInterval(intervalId);
};
}, [activeBatchSessionIds.length]);
}, [activeNonPausedSessionIds.length]);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Intentional .length-only dep needs a comment to prevent future regressions

The effect body accesses activeNonPausedSessionIds at lines 59 and 78, but the dependency array only lists activeNonPausedSessionIds.length. This is deliberate — using the full array reference would restart the interval (and reset lastUpdateTime) whenever session composition changes even if the count stays the same, introducing timer drift. However:

  1. It would trigger react-hooks/exhaustive-deps without explanation.
  2. A future developer could "fix" it by adding the full array, reintroducing the very bug this PR avoids.

Add a comment documenting the intent:

Suggested change
return () => {
clearInterval(intervalId);
};
}, [activeBatchSessionIds.length]);
}, [activeNonPausedSessionIds.length]);
return () => {
clearInterval(intervalId);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
// Intentionally depend on .length only: the array reference changes on every
// composition change (even same-count), which would restart the interval and
// reset lastUpdateTime unnecessarily. Only the count affects the deltaMs multiplier.
}, [activeNonPausedSessionIds.length]);

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
docs/releases.md (1)

174-174: Optional: Correct "Github" capitalization.

Line 174 uses "Github" but the official spelling is "GitHub" (capital H). The static analysis tool correctly flagged this.

📝 Proposed fix
-🌳 Github Worktree support was added. Any agent bound to a Git repository has the option to enable worktrees, each of which show up as a sub-agent with their own write-lock and Auto Run capability. Now you can truly develop in parallel on the same project and issue PRs when you're ready, all from within Maestro. Huge improvement, major thanks to `@petersilberman`.
+🌳 GitHub Worktree support was added. Any agent bound to a Git repository has the option to enable worktrees, each of which show up as a sub-agent with their own write-lock and Auto Run capability. Now you can truly develop in parallel on the same project and issue PRs when you're ready, all from within Maestro. Huge improvement, major thanks to `@petersilberman`.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/releases.md` at line 174, Update the release-note sentence that
currently reads "🌳 Github Worktree support was added..." to use the correct
capitalization "GitHub"; locate the exact string in the releases entry (the
sentence starting with the tree emoji) and replace "Github" with "GitHub" so the
line becomes "🌳 GitHub Worktree support was added..." ensuring consistency with
official branding.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@docs/releases.md`:
- Line 174: Update the release-note sentence that currently reads "🌳 Github
Worktree support was added..." to use the correct capitalization "GitHub";
locate the exact string in the releases entry (the sentence starting with the
tree emoji) and replace "Github" with "GitHub" so the line becomes "🌳 GitHub
Worktree support was added..." ensuring consistency with official branding.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b0f23a68-eeb5-419d-8c17-dbf1f653eb8a

📥 Commits

Reviewing files that changed from the base of the PR and between 3e0e338 and 1f00cdf.

📒 Files selected for processing (4)
  • docs/releases.md
  • src/__tests__/renderer/hooks/useAutoRunAchievements.test.ts
  • src/prompts/maestro-system-prompt.md
  • src/renderer/hooks/batch/useAutoRunAchievements.ts

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

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect Total Time on Auto Run during errors

1 participant