huskies: merge 1009

This commit is contained in:
dave
2026-05-13 22:55:05 +00:00
parent a5cd3a2152
commit 4e007bb770
56 changed files with 453 additions and 384 deletions
+35 -27
View File
@@ -149,10 +149,10 @@ pub fn transition(state: Stage, event: PipelineEvent) -> Result<Stage, Transitio
(Upcoming, Triage) => Ok(Backlog),
// ── Forward path ────────────────────────────────────────────────
(Backlog, DepsMet) => Ok(Coding),
(Coding, GatesStarted) => Ok(Qa),
(Backlog, DepsMet) => Ok(Coding { claim: None }),
(Coding { .. }, GatesStarted) => Ok(Qa),
(
Coding,
Coding { .. },
QaSkipped {
feature_branch,
commits_ahead,
@@ -160,6 +160,7 @@ pub fn transition(state: Stage, event: PipelineEvent) -> Result<Stage, Transitio
) => Ok(Merge {
feature_branch,
commits_ahead,
claim: None,
}),
(
Qa,
@@ -170,8 +171,9 @@ pub fn transition(state: Stage, event: PipelineEvent) -> Result<Stage, Transitio
) => Ok(Merge {
feature_branch,
commits_ahead,
claim: None,
}),
(Qa, GatesFailed { .. }) => Ok(Coding),
(Qa, GatesFailed { .. }) => Ok(Coding { claim: None }),
(Merge { .. }, MergeSucceeded { merge_commit }) => Ok(Done {
merged_at: now,
merge_commit,
@@ -193,7 +195,7 @@ pub fn transition(state: Stage, event: PipelineEvent) -> Result<Stage, Transitio
// ── Block: any active → Blocked ──────────────────────────────
(Backlog, Block { reason })
| (Coding, Block { reason })
| (Coding { .. }, Block { reason })
| (Qa, Block { reason })
| (Merge { .. }, Block { reason }) => Ok(Blocked { reason }),
@@ -201,18 +203,20 @@ pub fn transition(state: Stage, event: PipelineEvent) -> Result<Stage, Transitio
// story to `Stage::ReviewHold { resume_to, reason }`, preserving the
// current stage as the resume target so a reviewer can clear the
// hold and continue.
(s @ (Backlog | Coding | Qa | Merge { .. }), PipelineEvent::ReviewHold { reason }) => {
Ok(Stage::ReviewHold {
resume_to: Box::new(s),
reason,
})
}
(
s @ (Backlog | Coding { .. } | Qa | Merge { .. }),
PipelineEvent::ReviewHold { reason },
) => Ok(Stage::ReviewHold {
resume_to: Box::new(s),
reason,
}),
// ── MergeFailed: Merge → MergeFailure (recoverable intermediate) ──
(
Merge {
feature_branch,
commits_ahead,
..
},
MergeFailed { kind },
) => Ok(MergeFailure {
@@ -246,14 +250,14 @@ pub fn transition(state: Stage, event: PipelineEvent) -> Result<Stage, Transitio
// ── Abandon / supersede from any active or done stage ───────────
(Upcoming, Abandon)
| (Backlog, Abandon)
| (Coding, Abandon)
| (Coding { .. }, Abandon)
| (Qa, Abandon)
| (Merge { .. }, Abandon)
| (Done { .. }, Abandon) => Ok(Abandoned { ts: now }),
(Upcoming, Supersede { by })
| (Backlog, Supersede { by })
| (Coding, Supersede { by })
| (Coding { .. }, Supersede { by })
| (Qa, Supersede { by })
| (Merge { .. }, Supersede { by })
| (Done { .. }, Supersede { by }) => Ok(Superseded {
@@ -263,7 +267,7 @@ pub fn transition(state: Stage, event: PipelineEvent) -> Result<Stage, Transitio
// ── Reject from any active stage or QA ──────────────────────────
(Backlog, Reject { reason })
| (Coding, Reject { reason })
| (Coding { .. }, Reject { reason })
| (Qa, Reject { reason })
| (Merge { .. }, Reject { reason }) => Ok(Rejected { ts: now, reason }),
@@ -272,21 +276,24 @@ pub fn transition(state: Stage, event: PipelineEvent) -> Result<Stage, Transitio
// the backlog while waiting on dependent fixes, without losing it to
// Archived. Unlike `Unblock` (Blocked → Coding), this does not
// re-enter the active flow.
(Coding, Demote) | (Qa, Demote) | (Merge { .. }, Demote) | (Blocked { .. }, Demote) => {
Ok(Backlog)
}
(Coding { .. }, Demote)
| (Qa, Demote)
| (Merge { .. }, Demote)
| (Blocked { .. }, Demote) => Ok(Backlog),
// ── Close: direct completion from any active stage ─────────────
(Backlog, Close) | (Coding, Close) | (Qa, Close) | (Merge { .. }, Close) => Ok(Done {
merged_at: now,
merge_commit: GitSha("closed".to_string()),
}),
(Backlog, Close) | (Coding { .. }, Close) | (Qa, Close) | (Merge { .. }, Close) => {
Ok(Done {
merged_at: now,
merge_commit: GitSha("closed".to_string()),
})
}
// ── Freeze: any non-terminal stage → Frozen { resume_to } ──────
(
s @ (Upcoming
| Backlog
| Coding
| Coding { .. }
| Qa
| Merge { .. }
| Blocked { .. }
@@ -305,7 +312,7 @@ pub fn transition(state: Stage, event: PipelineEvent) -> Result<Stage, Transitio
(Stage::ReviewHold { resume_to, .. }, ReviewHoldCleared) => Ok(*resume_to),
// ── FixupRequested: MergeFailure → Coding (coder fixup) ────────
(MergeFailure { .. }, FixupRequested) => Ok(Coding),
(MergeFailure { .. }, FixupRequested) => Ok(Coding { claim: None }),
// ── FixupRequested: MergeFailureFinal → Coding (operator override)
//
@@ -314,19 +321,19 @@ pub fn transition(state: Stage, event: PipelineEvent) -> Result<Stage, Transitio
// the gate failure is fixable and send the story back for another
// coder attempt. The budget counter is a mergemaster bookkeeping
// detail, not a hard ceiling.
(MergeFailureFinal { .. }, FixupRequested) => Ok(Coding),
(MergeFailureFinal { .. }, FixupRequested) => Ok(Coding { claim: None }),
// ── ReQueuedForQa: MergeFailure → Qa (re-review) ────────────────
(MergeFailure { .. }, ReQueuedForQa) => Ok(Qa),
// ── MergeAborted: Merge → Coding (abort in-flight merge) ─────────
(Merge { .. }, MergeAborted) => Ok(Coding),
(Merge { .. }, MergeAborted) => Ok(Coding { claim: None }),
// ── HotfixRequested: Done → Coding (post-merge hotfix) ───────────
// Allows reopening a completed story so a coder can apply a hotfix.
// A fresh feature branch is forked from master when auto-assign spawns
// the coder.
(Done { .. }, HotfixRequested) => Ok(Coding),
(Done { .. }, HotfixRequested) => Ok(Coding { claim: None }),
// ── MergemasterAttempted: MergeFailure → MergeFailureFinal ─────
(MergeFailure { kind, .. }, MergemasterAttempted) => Ok(MergeFailureFinal { kind }),
@@ -337,7 +344,7 @@ pub fn transition(state: Stage, event: PipelineEvent) -> Result<Stage, Transitio
(Stage::ReviewHold { resume_to, .. }, Unblock) => Ok(*resume_to),
// ── Unblock: Blocked → Coding ─────────────────────────────────
(Blocked { .. }, Unblock) => Ok(Coding),
(Blocked { .. }, Unblock) => Ok(Coding { claim: None }),
// ── Unblock MergeFailure → Merge (re-attempt) ────────────────────
// `unblock_story` on a failed merge re-queues it for merge, restoring
@@ -353,6 +360,7 @@ pub fn transition(state: Stage, event: PipelineEvent) -> Result<Stage, Transitio
) => Ok(Merge {
feature_branch,
commits_ahead,
claim: None,
}),
// ── Demote MergeFailure → Backlog (manual parking) ───────────────