huskies: merge 945

This commit is contained in:
dave
2026-05-13 06:05:01 +00:00
parent 3a8894ea8f
commit 9ce5a8df0c
53 changed files with 497 additions and 654 deletions
-2
View File
@@ -71,7 +71,6 @@ mod tests {
stage,
depends_on: Vec::new(),
retry_count: 0,
frozen: false,
}
}
@@ -82,7 +81,6 @@ mod tests {
stage,
depends_on: deps.iter().map(|n| StoryId(n.to_string())).collect(),
retry_count: 0,
frozen: false,
}
}
-2
View File
@@ -13,7 +13,6 @@ fn make_item(id: &str, name: &str, stage: Stage) -> PipelineItem {
stage,
depends_on: Vec::new(),
retry_count: 0,
frozen: false,
}
}
@@ -25,7 +24,6 @@ fn make_item_with_deps(id: &str, name: &str, stage: Stage, deps: Vec<u32>) -> Pi
stage,
depends_on: deps.iter().map(|n| StoryId(n.to_string())).collect(),
retry_count: 0,
frozen: false,
}
}
+2 -1
View File
@@ -88,7 +88,8 @@ fn build_triage_dump(
// ---- CRDT metadata ----
if let Some(ref w) = crdt_item {
let mut fields: Vec<String> = Vec::new();
if w.blocked() {
// Story 945: `Stage::Blocked` is the source of truth.
if w.stage().is_blocked() {
fields.push("**blocked:** true".to_string());
}
if let Some(agent) = w.agent() {
+23 -12
View File
@@ -58,7 +58,8 @@ fn unblock_by_story_id(story_id: &str) -> String {
.and_then(|i| i.name().map(str::to_string))
.unwrap_or_else(|| story_id.to_string());
// Canonical "is this story blocked?" comes from the typed pipeline state.
// 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()
@@ -67,10 +68,8 @@ fn unblock_by_story_id(story_id: &str) -> String {
typed_item.as_ref().map(|i| &i.stage),
Some(crate::pipeline_state::Stage::MergeFailure { .. })
);
// CRDT register fallback for items not yet projected into typed state.
let crdt_blocked = crdt_item.as_ref().is_some_and(|i| i.blocked());
if !typed_blocked && !crdt_blocked {
if !typed_blocked {
return format!("**{story_name}** ({story_id}) is not blocked. Nothing to unblock.");
}
@@ -211,7 +210,6 @@ mod tests {
Some("Stuck Story"),
None,
Some(5),
Some(true),
None,
None,
None,
@@ -238,9 +236,11 @@ mod tests {
0,
"retry_count should be reset to 0 in CRDT after unblock"
);
// Story 945: `Stage::Blocked` was the source of truth; after unblock
// the stage must have transitioned out of `Blocked`.
assert!(
!item.blocked(),
"blocked flag should be cleared in CRDT after unblock"
!item.stage().is_blocked(),
"stage must no longer be Blocked after unblock"
);
}
@@ -279,7 +279,6 @@ mod tests {
Some("Stuck Story"),
None,
Some(5),
Some(true),
None,
None,
None,
@@ -305,9 +304,11 @@ mod tests {
0,
"retry_count must be reset to 0 in CRDT after unblock"
);
// Story 945: `Stage::Blocked` was the source of truth; after unblock
// the stage must have transitioned out of `Blocked`.
assert!(
!item.blocked(),
"blocked flag must be cleared in CRDT after unblock"
!item.stage().is_blocked(),
"stage must no longer be Blocked after unblock"
);
}
@@ -321,8 +322,18 @@ mod tests {
"# Story\n",
Some("In QA"),
);
crate::crdt_state::set_blocked("9901_story_in_qa", true);
crate::crdt_state::set_retry_count("9901_story_in_qa", 3);
// Story 945: blocked is now `Stage::Blocked` — seed via CRDT stage.
crate::crdt_state::write_item_str(
"9901_story_in_qa",
"blocked",
Some("In QA"),
None,
Some(3),
None,
None,
None,
None,
);
let output = unblock_cmd_with_root(tmp.path(), "9901").unwrap();
assert!(