You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: plan recovery system — graceful degradation, touchSet enforcement, and early conflict detection (#41)
* Merge graceful-retry
* Merge touchset-gate
* feat: activate needs_rebase job status for early conflict detection
Add trial merge check before jobs enter the merge train to detect
conflicts early. Jobs that would conflict are marked needs_rebase
and the plan pauses at an on_error checkpoint.
- Add checkMergeability() to merge-train.ts for trial merges
- Integrate trial merge in orchestrator reconcile loop
- Add retry arg to plan-approve for needs_rebase jobs
- Add ready_to_merge → needs_rebase transition in plan-types
- Add tests for all new functionality
Closes#36
* test: fix diagnostics in rebased test files
* fix: update plan job state before reconcile on completion
* test: mock createIntegrationBranch in plan-approve test for CI
error: mergeCheck.conflicts?.join(', ')??'merge conflict detected in trial merge',
519
+
});
520
+
job.status='needs_rebase';
521
+
522
+
this.showToast('Mission Control',`Job "${job.name}" has merge conflicts. Plan paused.`,'error');
523
+
this.notify(`❌ Job "${job.name}" would conflict with the integration branch.\n Files: ${mergeCheck.conflicts?.join(', ')??'unknown'}\nRebase the job branch and retry with mc_plan_approve(checkpoint: "on_error", retry: "${job.name}").`);
this.showToast('Mission Control',`Merge conflict in job "${nextJob.name}".`,'error');
548
-
this.notify(`❌ Merge conflict in job "${nextJob.name}". Files: ${mergeResult.files?.join(', ')??'unknown'}. Plan failed.`);
573
+
this.showToast('Mission Control',`Merge conflict in job "${nextJob.name}". Plan paused.`,'error');
574
+
this.notify(`❌ Merge conflict in job "${nextJob.name}". Files: ${mergeResult.files?.join(', ')??'unknown'}. Fix the branch and retry with mc_plan_approve(checkpoint: "on_error", retry: "${nextJob.name}").`);
575
+
awaitthis.setCheckpoint('on_error',plan);
576
+
return;
549
577
}else{
550
578
awaitupdatePlanJob(plan.id,nextJob.name,{
551
579
status: 'failed',
@@ -557,14 +585,10 @@ export class Orchestrator {
557
585
this.notify(`🧪 ${nextJob.name}: ${testSummary}`);
558
586
}
559
587
560
-
if(this.isSupervisor(plan)){
561
-
awaitthis.setCheckpoint('on_error',plan);
562
-
return;
563
-
}
564
-
565
-
plan.status='failed';
566
-
this.showToast('Mission Control',`Job "${nextJob.name}" failed during merge.`,'error');
567
-
this.notify(`❌ Job "${nextJob.name}" failed merge tests. Plan failed.`);
588
+
this.showToast('Mission Control',`Job "${nextJob.name}" failed merge tests. Plan paused.`,'error');
589
+
this.notify(`❌ Job "${nextJob.name}" failed merge tests. Fix the branch and retry with mc_plan_approve(checkpoint: "on_error", retry: "${nextJob.name}").`);
590
+
awaitthis.setCheckpoint('on_error',plan);
591
+
return;
568
592
}
569
593
}
570
594
@@ -763,22 +787,24 @@ If your work needs human review before it can proceed: mc_report(status: "needs_
thrownewError(`Job "${args.retry}" is not in a retryable state (current: ${job.status}). Only failed, conflict, or needs_rebase jobs can be retried.`);
thrownewError(`Job "${args.retry}" is not in a retryable state (current: ${job.status}). Only failed, conflict, or needs_rebase jobs can be retried.`);
0 commit comments