Skip to content

fix(runs): advance the re-arm baseline so a resolved re-drive cannot orphan resolution commits#78

Open
Pawel-N-pl wants to merge 3 commits into
mainfrom
fix/resolve-baseline-advance
Open

fix(runs): advance the re-arm baseline so a resolved re-drive cannot orphan resolution commits#78
Pawel-N-pl wants to merge 3 commits into
mainfrom
fix/resolve-baseline-advance

Conversation

@Pawel-N-pl

@Pawel-N-pl Pawel-N-pl commented Jul 6, 2026

Copy link
Copy Markdown

What

rearm_escalation now advances baseline_commit to the project's current HEAD (and refreshes the untracked-files snapshot) instead of leaving it at the pre-attempt snapshot.

Why

A resolve session can legitimately commit work (e.g. the fixture the escalation asked for). The re-drive's reset-to-baseline still targeted the old baseline, so it parked that commit on an attempt-preserve/* ref and rebuilt against the unresolved tree, and the re-driven session hit the same gap and re-escalated verbatim. This complements other recent fixes for stale Auto Run Result handling and resume durability.

Rebased onto v0.8.1; the only conflict was a docstring/adjacent-lines overlap in rearm_escalation with an upstream addition to the same function, resolved by keeping both. Independent of the other pending PR (ledger-only proof-of-work fix); different files, either can land first.

How

  • At re-arm: set baseline_commit = verify.rev_parse_head(project), re-snapshot baseline_untracked.
  • Best-effort: a GitError leaves the old baseline in place.
  • Journal the adopted baseline.

Testing

Two new tests in tests/test_resolve.py (adopts HEAD + re-snapshots; stays stale outside a repo). Full suite: 1407 passed, 7 skipped; ruff clean.

Summary by CodeRabbit

  • Bug Fixes

    • Improved escalation re-drive handling so resumed work starts from the latest resolved state and preserves the current untracked file snapshot.
    • Added safer fallback behavior when repository metadata can’t be read, keeping the previous baseline intact.
    • Included baseline information in escalation-resolution records for better continuity.
  • Tests

    • Added coverage for baseline updates after resolution and for fallback behavior when git data is unavailable.

rearm_escalation flipped the story back to PENDING but left
baseline_commit at the escalated attempt's pre-attempt snapshot. When the
resolve session had committed authorized work on the project branch (e.g.
a baseline fixture the escalation was about), the redrive's
reset-to-baseline in engine._rollback_or_pause parked those commits on an
attempt-preserve ref and rebuilt against the unresolved tree — the
re-driven dev session immediately hit the very gap the human had just
resolved and re-escalated.

Advance baseline_commit to the project's HEAD and refresh the untracked
snapshot at re-arm time, so resolution work counts as the rebuild's
starting point rather than attempt debris. Best-effort: a git failure
keeps the old baseline. The story-escalation-resolved journal event now
records the adopted baseline.
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Pawel-N-pl, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 36 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 806197f0-4009-4d95-ad12-d67b0031c9e8

📥 Commits

Reviewing files that changed from the base of the PR and between 5620879 and ccc7cb7.

📒 Files selected for processing (2)
  • src/bmad_loop/runs.py
  • tests/test_resolve.py

Walkthrough

The rearm_escalation function now performs a best-effort git-based update of the task's baseline commit and untracked file snapshot before re-driving, catching GitError to preserve prior state on failure. The journal entry now includes this baseline value. New tests validate both success and failure paths.

Changes

Rearm escalation baseline update

Layer / File(s) Summary
Baseline advancement and journal entry
src/bmad_loop/runs.py
rearm_escalation updates task.baseline_commit and task.baseline_untracked via rev_parse_head/untracked_files, tolerating GitError, and includes baseline in the "story-escalation-resolved" journal entry.
Tests for baseline re-arm behavior
tests/test_resolve.py
New tests verify baseline commit advancement on successful HEAD move and preservation of the prior baseline when the directory is not a valid git repo.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant rearm_escalation
  participant GitRepo
  participant Journal

  Caller->>rearm_escalation: rearm_escalation(task)
  rearm_escalation->>GitRepo: rev_parse_head()
  GitRepo-->>rearm_escalation: HEAD commit or GitError
  rearm_escalation->>GitRepo: untracked_files()
  GitRepo-->>rearm_escalation: untracked file list or GitError
  rearm_escalation->>rearm_escalation: update baseline_commit / baseline_untracked
  rearm_escalation->>Journal: append("story-escalation-resolved", baseline)
Loading

Possibly related PRs

Poem

A rabbit hops to check the HEAD,
"Is the baseline fresh?" it said.
Untracked files, all snapped anew,
Journal entries logged on cue.
Hop, commit, and re-arm bright —
escalations resolved 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 summarizes the main change: advancing the re-arm baseline to preserve resolution commits during re-drive.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/resolve-baseline-advance

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.

@augmentcode

augmentcode Bot commented Jul 6, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: This PR fixes escalation re-drive behavior so a completed resolve session can’t be rolled back as “attempt debris.”

Changes:

  • Updates rearm_escalation to advance baseline_commit to the project’s current HEAD and refresh baseline_untracked.
  • Records the adopted baseline in the story-escalation-resolved journal entry.
  • Adds tests ensuring the baseline moves to resolved HEAD and that non-repo projects keep the prior baseline.

Technical Notes: Baseline advancement is best-effort (git failures retain the old baseline) to keep re-arm resilient.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Review completed. 2 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread src/bmad_loop/runs.py Outdated
# just loses this protection).
try:
repo = Path(state.project)
task.baseline_commit = verify.rev_parse_head(repo)

@augmentcode augmentcode Bot Jul 6, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

At task.baseline_commit = verify.rev_parse_head(repo): if rev_parse_head() succeeds but untracked_files() fails, the baseline commit will advance while baseline_untracked stays stale, which can make verify.safe_rollback() treat pre-existing untracked files as run-created and delete them.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Comment thread src/bmad_loop/runs.py Outdated
repo = Path(state.project)
task.baseline_commit = verify.rev_parse_head(repo)
task.baseline_untracked = sorted(verify.untracked_files(repo))
except verify.GitError:

@augmentcode augmentcode Bot Jul 6, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Catching only verify.GitError means other git-call failures (e.g. subprocess.TimeoutExpired/OSError from subprocess.run) would still raise and make rearm_escalation fail, despite the “best-effort” intent described above this block.

Severity: low

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/test_resolve.py (1)

178-207: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

LGTM! Good coverage of the success and non-repo tolerance paths.

Consider also adding a case where rev_parse_head succeeds but untracked_files fails, to cover the partial-update risk flagged in runs.py (baseline_commit advancing while baseline_untracked stays stale).

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/bmad_loop/runs.py`:
- Around line 550-566: The best-effort baseline refresh in runs.py can leave
task.baseline_commit and task.baseline_untracked out of sync if
verify.rev_parse_head succeeds but verify.untracked_files raises GitError.
Update the logic in the baseline refresh block so both git reads are completed
first and only then assign task.baseline_commit and task.baseline_untracked
together, keeping the pair consistent for attempt_dirty and safe_rollback. If
either git call fails, leave both existing baseline values unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d3012ab2-2cc7-45a4-85ac-4c0be7d47ed9

📥 Commits

Reviewing files that changed from the base of the PR and between b0cce05 and 5620879.

📒 Files selected for processing (2)
  • src/bmad_loop/runs.py
  • tests/test_resolve.py

Comment thread src/bmad_loop/runs.py
…on partial git failure

Both git reads in rearm_escalation's baseline refresh now land in locals
before either task field is assigned, and the except widens from GitError to
Exception (matching verify._prune_refs' best-effort contract for the whole
subprocess surface: a timeout or missing-binary OSError must not fail re-arm
either). Previously, rev_parse_head succeeding while untracked_files raised
would advance baseline_commit alone, leaving baseline_untracked stale and the
two fields describing different points in time - exactly the pairing
attempt_dirty/safe_rollback rely on to tell pre-existing untracked files from
run-created ones.

Addresses review feedback from PR #78 (CodeRabbit + Augment, converging on
the same finding).
…xcept

CI's trunk check (bandit) flagged the bare except/pass in rearm_escalation's
baseline refresh as B110 (try/except/pass). It is deliberately best-effort
(a git failure must not fail re-arm), matching the same pattern already used
elsewhere in the codebase (e.g. verify._prune_refs, Engine's teardown
handlers) - add the same noqa/nosec suppression with a short inline reason.

Verified locally with bandit (via uvx): 0 issues, 1 potential issue
specifically suppressed by the new nosec marker.
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