huskies: merge 988
This commit is contained in:
@@ -205,7 +205,7 @@ mod tests {
|
||||
.expect("read_typed should succeed")
|
||||
.expect("item should be present");
|
||||
assert!(
|
||||
item.is_frozen(),
|
||||
matches!(item.stage, crate::pipeline_state::Stage::Frozen { .. }),
|
||||
"stage should be Frozen after freeze: {:?}",
|
||||
item.stage
|
||||
);
|
||||
|
||||
@@ -218,7 +218,7 @@ fn render_item_line(
|
||||
Some(item.name.as_str())
|
||||
};
|
||||
// Use the typed CRDT stage as the sole source of truth (story 945).
|
||||
let frozen = item.stage.is_frozen();
|
||||
let frozen = matches!(item.stage, Stage::Frozen { .. });
|
||||
let base_label = super::story_short_label(story_id, name_opt);
|
||||
let display = if frozen {
|
||||
format!("\u{2744}\u{FE0F} {base_label}") // ❄️ prefix
|
||||
@@ -310,7 +310,16 @@ fn render_item_line(
|
||||
}
|
||||
}
|
||||
|
||||
let blocked = item.stage.is_blocked();
|
||||
let blocked = matches!(
|
||||
item.stage,
|
||||
Stage::Blocked { .. }
|
||||
| Stage::MergeFailure { .. }
|
||||
| Stage::MergeFailureFinal { .. }
|
||||
| Stage::Archived {
|
||||
reason: ArchiveReason::Blocked { .. },
|
||||
..
|
||||
}
|
||||
);
|
||||
// Blocked items with a recovery agent get differentiated indicators.
|
||||
if blocked {
|
||||
return match agent.map(|a| &a.status) {
|
||||
|
||||
@@ -362,12 +362,30 @@ fn stage_is_blocked_returns_true_for_archived_blocked() {
|
||||
reason: "too many retries".to_string(),
|
||||
},
|
||||
};
|
||||
assert!(stage.is_blocked());
|
||||
assert!(matches!(
|
||||
stage,
|
||||
Stage::Blocked { .. }
|
||||
| Stage::MergeFailure { .. }
|
||||
| Stage::MergeFailureFinal { .. }
|
||||
| Stage::Archived {
|
||||
reason: ArchiveReason::Blocked { .. },
|
||||
..
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stage_is_blocked_returns_false_for_coding() {
|
||||
assert!(!Stage::Coding.is_blocked());
|
||||
assert!(!matches!(
|
||||
Stage::Coding,
|
||||
Stage::Blocked { .. }
|
||||
| Stage::MergeFailure { .. }
|
||||
| Stage::MergeFailureFinal { .. }
|
||||
| Stage::Archived {
|
||||
reason: ArchiveReason::Blocked { .. },
|
||||
..
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -376,7 +394,16 @@ fn stage_is_blocked_returns_false_for_archived_completed() {
|
||||
archived_at: Utc::now(),
|
||||
reason: ArchiveReason::Completed,
|
||||
};
|
||||
assert!(!stage.is_blocked());
|
||||
assert!(!matches!(
|
||||
stage,
|
||||
Stage::Blocked { .. }
|
||||
| Stage::MergeFailure { .. }
|
||||
| Stage::MergeFailureFinal { .. }
|
||||
| Stage::Archived {
|
||||
reason: ArchiveReason::Blocked { .. },
|
||||
..
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
// -- status output shows idle dot for items with no active agent --------
|
||||
|
||||
@@ -86,7 +86,16 @@ fn build_triage_dump(
|
||||
if let Some(ref w) = crdt_item {
|
||||
let mut fields: Vec<String> = Vec::new();
|
||||
// Story 945: `Stage::Blocked` is the source of truth.
|
||||
if w.stage().is_blocked() {
|
||||
if matches!(
|
||||
w.stage(),
|
||||
crate::pipeline_state::Stage::Blocked { .. }
|
||||
| crate::pipeline_state::Stage::MergeFailure { .. }
|
||||
| crate::pipeline_state::Stage::MergeFailureFinal { .. }
|
||||
| crate::pipeline_state::Stage::Archived {
|
||||
reason: crate::pipeline_state::ArchiveReason::Blocked { .. },
|
||||
..
|
||||
}
|
||||
) {
|
||||
fields.push("**blocked:** true".to_string());
|
||||
}
|
||||
if let Some(agent) = w.agent() {
|
||||
|
||||
@@ -61,9 +61,18 @@ fn unblock_by_story_id(story_id: &str) -> String {
|
||||
// Story 945: `Stage::Blocked` / `Stage::MergeFailure` are the single
|
||||
// source of truth — the legacy `blocked` boolean flag is gone.
|
||||
let typed_item = crate::pipeline_state::read_typed(story_id).ok().flatten();
|
||||
let typed_blocked = typed_item
|
||||
.as_ref()
|
||||
.is_some_and(|item| item.stage.is_blocked());
|
||||
let typed_blocked = typed_item.as_ref().is_some_and(|item| {
|
||||
matches!(
|
||||
item.stage,
|
||||
crate::pipeline_state::Stage::Blocked { .. }
|
||||
| crate::pipeline_state::Stage::MergeFailure { .. }
|
||||
| crate::pipeline_state::Stage::MergeFailureFinal { .. }
|
||||
| crate::pipeline_state::Stage::Archived {
|
||||
reason: crate::pipeline_state::ArchiveReason::Blocked { .. },
|
||||
..
|
||||
}
|
||||
)
|
||||
});
|
||||
let typed_merge_failure = matches!(
|
||||
typed_item.as_ref().map(|i| &i.stage),
|
||||
Some(crate::pipeline_state::Stage::MergeFailure { .. })
|
||||
@@ -239,7 +248,16 @@ mod tests {
|
||||
// Story 945: `Stage::Blocked` was the source of truth; after unblock
|
||||
// the stage must have transitioned out of `Blocked`.
|
||||
assert!(
|
||||
!item.stage().is_blocked(),
|
||||
!matches!(
|
||||
item.stage(),
|
||||
crate::pipeline_state::Stage::Blocked { .. }
|
||||
| crate::pipeline_state::Stage::MergeFailure { .. }
|
||||
| crate::pipeline_state::Stage::MergeFailureFinal { .. }
|
||||
| crate::pipeline_state::Stage::Archived {
|
||||
reason: crate::pipeline_state::ArchiveReason::Blocked { .. },
|
||||
..
|
||||
}
|
||||
),
|
||||
"stage must no longer be Blocked after unblock"
|
||||
);
|
||||
}
|
||||
@@ -307,7 +325,16 @@ mod tests {
|
||||
// Story 945: `Stage::Blocked` was the source of truth; after unblock
|
||||
// the stage must have transitioned out of `Blocked`.
|
||||
assert!(
|
||||
!item.stage().is_blocked(),
|
||||
!matches!(
|
||||
item.stage(),
|
||||
crate::pipeline_state::Stage::Blocked { .. }
|
||||
| crate::pipeline_state::Stage::MergeFailure { .. }
|
||||
| crate::pipeline_state::Stage::MergeFailureFinal { .. }
|
||||
| crate::pipeline_state::Stage::Archived {
|
||||
reason: crate::pipeline_state::ArchiveReason::Blocked { .. },
|
||||
..
|
||||
}
|
||||
),
|
||||
"stage must no longer be Blocked after unblock"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user