feat: outer cap on commit-recovery respawns catches flapping agents
The progress-aware no-progress cap (3 consecutive byte-identical diffs) doesn't catch the degenerate pattern where the agent keeps making DIFFERENT file edits each session but never commits — every respawn resets the no-progress counter, infinite loop, budget burns. Adds ContentKey::CommitRecoveryTotalAttempts: an absolute counter that increments on every commit-recovery respawn regardless of progress. TOTAL_ATTEMPTS_CAP = 8; when hit, block with reason 'agent flapped — N respawns without ever committing'. Two caps now bound the recovery loop: - NO_PROGRESS_CAP (3): catches stuck-agent (same diff repeatedly) - TOTAL_ATTEMPTS_CAP (8): catches flapping-agent (different diffs, no commits) Easy to tune the constant lower if we see runaway in practice. All 2936 tests pass.
This commit is contained in:
@@ -34,6 +34,12 @@ pub enum ContentKey<'a> {
|
||||
/// between consecutive session-boundary-clean exits. Same byte length on
|
||||
/// two consecutive attempts → no progress → increment CommitRecoveryPending.
|
||||
CommitRecoveryDiffFingerprint(&'a str),
|
||||
/// Absolute count of commit-recovery respawns issued for a story since the
|
||||
/// last successful commit. Increments every respawn regardless of whether
|
||||
/// the diff fingerprint changed. Outer cap that catches the "agent flaps
|
||||
/// between different file edits each session but never commits" pattern
|
||||
/// where the progress-aware counter would never trigger.
|
||||
CommitRecoveryTotalAttempts(&'a str),
|
||||
/// Flag indicating a merge gate fixup coder session is in progress.
|
||||
///
|
||||
/// Set when the merge gate fails with a self-evident-fix class of failure
|
||||
@@ -68,6 +74,9 @@ impl<'a> ContentKey<'a> {
|
||||
ContentKey::CommitRecoveryDiffFingerprint(id) => {
|
||||
format!("{id}:commit_recovery_diff_fingerprint")
|
||||
}
|
||||
ContentKey::CommitRecoveryTotalAttempts(id) => {
|
||||
format!("{id}:commit_recovery_total_attempts")
|
||||
}
|
||||
ContentKey::MergeFixupPending(id) => format!("{id}:merge_fixup_pending"),
|
||||
ContentKey::MergeFailureKind(id) => format!("{id}:merge_failure_kind"),
|
||||
ContentKey::MergeSuccess(id) => format!("{id}:merge_success"),
|
||||
|
||||
Reference in New Issue
Block a user