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
+24 -44
View File
@@ -21,7 +21,6 @@ pub struct CrdtItemDump {
pub name: Option<String>,
pub agent: Option<String>,
pub retry_count: Option<i64>,
pub blocked: Option<bool>,
pub depends_on: Option<Vec<u32>>,
pub claimed_by: Option<String>,
pub claimed_at: Option<f64>,
@@ -135,10 +134,6 @@ pub fn dump_crdt_state(story_id_filter: Option<&str>) -> CrdtStateDump {
JsonValue::Number(n) => Some(n as i64),
_ => None,
};
let blocked = match item_crdt.blocked.view() {
JsonValue::Bool(b) => Some(b),
_ => None,
};
let depends_on = match item_crdt.depends_on.view() {
JsonValue::String(s) if !s.is_empty() => serde_json::from_str::<Vec<u32>>(&s).ok(),
_ => None,
@@ -161,7 +156,6 @@ pub fn dump_crdt_state(story_id_filter: Option<&str>) -> CrdtStateDump {
name,
agent,
retry_count,
blocked,
depends_on,
claimed_by,
claimed_at,
@@ -321,10 +315,6 @@ pub(super) fn extract_item_view(item: &PipelineItemCrdt) -> Option<PipelineItemV
JsonValue::Number(n) => Some(n as i64),
_ => None,
};
let blocked = match item.blocked.view() {
JsonValue::Bool(b) => Some(b),
_ => None,
};
let depends_on = match item.depends_on.view() {
JsonValue::String(s) if !s.is_empty() => serde_json::from_str::<Vec<u32>>(&s).ok(),
_ => None,
@@ -348,16 +338,6 @@ pub(super) fn extract_item_view(item: &PipelineItemCrdt) -> Option<PipelineItemV
_ => None,
};
let mergemaster_attempted = match item.mergemaster_attempted.view() {
JsonValue::Bool(b) => Some(b),
_ => None,
};
let review_hold = match item.review_hold.view() {
JsonValue::Bool(b) => Some(b),
_ => None,
};
let item_type = match item.item_type.view() {
JsonValue::String(s) if !s.is_empty() => Some(s),
_ => None,
@@ -368,12 +348,12 @@ pub(super) fn extract_item_view(item: &PipelineItemCrdt) -> Option<PipelineItemV
_ => None,
};
let frozen = match item.frozen.view() {
JsonValue::Bool(b) => Some(b),
let resume_to = match item.resume_to.view() {
JsonValue::String(s) if !s.is_empty() => Some(s),
_ => None,
};
let stage = project_stage_for_view(&stage_str, &story_id, merged_at, blocked)?;
let stage = project_stage_for_view(&stage_str, &story_id, merged_at, resume_to.as_deref())?;
Some(PipelineItemView {
story_id,
@@ -381,17 +361,13 @@ pub(super) fn extract_item_view(item: &PipelineItemCrdt) -> Option<PipelineItemV
name,
agent,
retry_count,
blocked,
depends_on,
claimed_by,
claimed_at,
merged_at,
qa_mode,
mergemaster_attempted,
review_hold,
item_type,
epic,
frozen,
})
}
@@ -412,7 +388,7 @@ fn project_stage_for_view(
stage_str: &str,
story_id: &str,
merged_at: Option<f64>,
blocked: Option<bool>,
resume_to: Option<&str>,
) -> Option<crate::pipeline_state::Stage> {
use crate::pipeline_state::{ArchiveReason, BranchName, GitSha, Stage};
use chrono::{DateTime, Utc};
@@ -436,6 +412,12 @@ fn project_stage_for_view(
other => other,
};
// Story 945: resume target for `Frozen` / `ReviewHold` variants is stored
// in the sibling `resume_to` register. Fall back to `Coding` when the
// register is empty or holds an unrecognised value.
let resume_target =
|| -> Box<Stage> { Box::new(resume_to.and_then(Stage::from_dir).unwrap_or(Stage::Coding)) };
match clean {
"upcoming" => Some(Stage::Upcoming),
"backlog" => Some(Stage::Backlog),
@@ -451,6 +433,16 @@ fn project_stage_for_view(
"merge_failure" => Some(Stage::MergeFailure {
reason: String::new(),
}),
"merge_failure_final" => Some(Stage::MergeFailureFinal {
reason: String::new(),
}),
"frozen" => Some(Stage::Frozen {
resume_to: resume_target(),
}),
"review_hold" => Some(Stage::ReviewHold {
resume_to: resume_target(),
reason: String::new(),
}),
"done" => {
let merged_at = merged_at
.map(|ts| {
@@ -462,19 +454,10 @@ fn project_stage_for_view(
merge_commit: GitSha("legacy".to_string()),
})
}
"archived" => {
let reason = if blocked.unwrap_or(false) {
ArchiveReason::Blocked {
reason: "migrated from legacy blocked field".to_string(),
}
} else {
ArchiveReason::Completed
};
Some(Stage::Archived {
archived_at: Utc::now(),
reason,
})
}
"archived" => Some(Stage::Archived {
archived_at: Utc::now(),
reason: ArchiveReason::Completed,
}),
_ => None,
}
}
@@ -589,7 +572,6 @@ mod tests {
assert_eq!(view.name.as_deref(), Some("View Test"));
assert_eq!(view.agent.as_deref(), Some("coder-1"));
assert_eq!(view.retry_count, Some(2));
assert_eq!(view.blocked, Some(true));
assert_eq!(view.depends_on, Some(vec![10, 20]));
}
@@ -647,7 +629,6 @@ mod tests {
None,
None,
None,
None,
);
// The story is live on this node.
@@ -718,7 +699,6 @@ mod tests {
None,
None,
None,
None,
);
assert!(
read_item(story_id).is_none(),