fix(FN-5627): suppress ntfy notifications for transient merge failures the engine auto-recovers
Even with FN-5627's merger TOCTOU fix + transient-failure self-healing sweep + safety-fallback auto-prerebase landed, the merger can still hit transient failure classes (lease handoff races, brief same-SHA non-FF advances) for tasks whose branches are particularly out-of-sync. The self-healing sweep auto-recovers them within bounded budget \u2014 but each individual failure cycle was firing a ntfy alarm before the recovery cleared the failed state, producing user-facing alarm spam for tasks that were never actually stuck. Two layers of fix: 1. NotificationService.handleTaskUpdated now classifies task.error via the new shared classifyTransientMergeError helper before scheduling the deferred failure notification. Transient classes (lease-handoff-target-not-queued, spurious-concurrent-advance-same-sha) get logged as suppressed and never schedule a ntfy timer. 2. Defense-in-depth: fireDeferredFailureNotification re-classifies the error at dispatch time, so a failure scheduled before the suppression landed on a newer cycle still suppresses if the error matches a transient class. The classifier itself moved from self-healing.ts to a new logger-free transient-merge-error-classifier.ts module so consumers in NotificationService don't pull createLogger through the import chain and break test mocks of ../logger.js (per project-memory rule about new modules using createLogger). self-healing.ts re-exports the symbol for backward compatibility. Log prefix for the recovery actions also changed from '[FN-5627] Auto-recovering...' to 'Auto-recovered:' so that NotificationService.maybeSuppressTransientFailedNotification's existing /^Auto-recovered:/ log-prefix check cancels any already-scheduled failure notification when the sweep runs mid-grace-window. Tests (3 new): - transient lease-handoff-target-not-queued failure NOT notified - transient spurious-concurrent-advance-same-sha failure NOT notified - genuine different-SHAs concurrent-advance still notifies (control) Engine suite: 6166 tests pass. Fusion-Task-Id: FN-5627
This commit is contained in:
@@ -1544,9 +1544,12 @@ export class ProjectEngine {
|
||||
runtimeLog.warn(
|
||||
`Auto-merge: ${taskId} fast-path REFUSED — auto-recovering (attempt ${nextRetries}/${ProjectEngine.MAX_AUTO_MERGE_RETRIES}): ${reachability.reason}: ${reachability.diagnostic}`,
|
||||
);
|
||||
// Prefix MUST be "Auto-recovered:" so NotificationService's
|
||||
// maybeSuppressTransientFailedNotification cancels the pending
|
||||
// ntfy fired off the underlying task:failed event.
|
||||
await store.logEntry(
|
||||
taskId,
|
||||
`[FN-5627] Auto-merge fast-path refused — cleared poisoned mergeDetails (commit ${shortSha} not reachable from ${integrationBranchForGate}, ${reachability.reason}). Re-enqueueing for fresh merge attempt ${nextRetries}/${ProjectEngine.MAX_AUTO_MERGE_RETRIES}.`,
|
||||
`Auto-recovered: fast-path refused — cleared poisoned mergeDetails (commit ${shortSha} not reachable from ${integrationBranchForGate}, ${reachability.reason}). Re-enqueueing for fresh merge attempt ${nextRetries}/${ProjectEngine.MAX_AUTO_MERGE_RETRIES} [FN-5627].`,
|
||||
);
|
||||
await store.updateTask(taskId, {
|
||||
mergeDetails: cleanedMergeDetails,
|
||||
|
||||
Reference in New Issue
Block a user