huskies: merge 1009
This commit is contained in:
@@ -122,7 +122,7 @@ pub fn move_story_to_done(story_id: &str) -> Result<(), String> {
|
||||
merge_commit: GitSha("accepted".to_string()),
|
||||
},
|
||||
Stage::MergeFailure { .. } => PipelineEvent::Accepted,
|
||||
Stage::Coding | Stage::Qa | Stage::Backlog => PipelineEvent::Close,
|
||||
Stage::Coding { .. } | Stage::Qa | Stage::Backlog => PipelineEvent::Close,
|
||||
_ => {
|
||||
return Err(format!(
|
||||
"Work item '{story_id}' is in {} — cannot move to done.",
|
||||
@@ -160,7 +160,7 @@ pub fn move_story_to_merge(story_id: &str) -> Result<(), String> {
|
||||
let commits = NonZeroU32::new(1).expect("1 is non-zero");
|
||||
|
||||
let event = match &item.stage {
|
||||
Stage::Coding => PipelineEvent::QaSkipped {
|
||||
Stage::Coding { .. } => PipelineEvent::QaSkipped {
|
||||
feature_branch: branch,
|
||||
commits_ahead: commits,
|
||||
},
|
||||
@@ -383,8 +383,8 @@ fn map_stage_move_to_event(
|
||||
match (from, target) {
|
||||
(Stage::Upcoming, "backlog") => Ok(PipelineEvent::Triage),
|
||||
(Stage::Backlog, "current") => Ok(PipelineEvent::DepsMet),
|
||||
(Stage::Coding, "qa") => Ok(PipelineEvent::GatesStarted),
|
||||
(Stage::Coding, "merge") => Ok(PipelineEvent::QaSkipped {
|
||||
(Stage::Coding { .. }, "qa") => Ok(PipelineEvent::GatesStarted),
|
||||
(Stage::Coding { .. }, "merge") => Ok(PipelineEvent::QaSkipped {
|
||||
feature_branch: branch(),
|
||||
commits_ahead: nz1(),
|
||||
}),
|
||||
@@ -392,7 +392,7 @@ fn map_stage_move_to_event(
|
||||
feature_branch: branch(),
|
||||
commits_ahead: nz1(),
|
||||
}),
|
||||
(Stage::Coding, "backlog")
|
||||
(Stage::Coding { .. }, "backlog")
|
||||
| (Stage::Qa, "backlog")
|
||||
| (Stage::Merge { .. }, "backlog")
|
||||
| (Stage::Blocked { .. }, "backlog") => Ok(PipelineEvent::Demote),
|
||||
@@ -402,7 +402,7 @@ fn map_stage_move_to_event(
|
||||
(Stage::Merge { .. }, "done") => Ok(PipelineEvent::MergeSucceeded {
|
||||
merge_commit: GitSha("manual".to_string()),
|
||||
}),
|
||||
(Stage::Coding | Stage::Qa | Stage::Backlog, "done") => Ok(PipelineEvent::Close),
|
||||
(Stage::Coding { .. } | Stage::Qa | Stage::Backlog, "done") => Ok(PipelineEvent::Close),
|
||||
(Stage::Blocked { .. }, "current") => Ok(PipelineEvent::Unblock),
|
||||
// Story 919: MergeFailure + Unblock goes to Merge (re-attempt); manual
|
||||
// demotion to backlog uses Demote to park it without a retry.
|
||||
@@ -530,7 +530,7 @@ fn stage_to_name(s: &Stage) -> &'static str {
|
||||
match s {
|
||||
Stage::Upcoming => "upcoming",
|
||||
Stage::Backlog => "backlog",
|
||||
Stage::Coding => "current",
|
||||
Stage::Coding { .. } => "current",
|
||||
Stage::Blocked { .. } => "blocked",
|
||||
Stage::Qa => "qa",
|
||||
Stage::Merge { .. } => "merge",
|
||||
@@ -714,7 +714,7 @@ mod tests {
|
||||
"should return to coding after unblock"
|
||||
);
|
||||
assert!(
|
||||
matches!(item.stage, Stage::Coding),
|
||||
matches!(item.stage, Stage::Coding { .. }),
|
||||
"stage should be Stage::Coding after unblock"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ impl AgentPool {
|
||||
let merge_stage = Stage::Merge {
|
||||
feature_branch: BranchName(String::new()),
|
||||
commits_ahead: NonZeroU32::new(1).expect("1 is non-zero"),
|
||||
claim: None,
|
||||
};
|
||||
let merge_items = scan_stage_items(&merge_stage);
|
||||
for story_id in &merge_items {
|
||||
|
||||
@@ -160,6 +160,7 @@ mod tests {
|
||||
before: crate::pipeline_state::Stage::Merge {
|
||||
feature_branch: BranchName("feature/test".to_string()),
|
||||
commits_ahead: NonZeroU32::new(1).unwrap(),
|
||||
claim: None,
|
||||
},
|
||||
after: crate::pipeline_state::Stage::MergeFailure {
|
||||
kind: kind.clone(),
|
||||
|
||||
@@ -27,7 +27,7 @@ impl AgentPool {
|
||||
/// here as well.
|
||||
pub(super) async fn assign_pipeline_stages(&self, project_root: &Path, config: &ProjectConfig) {
|
||||
let stages: [(Stage, PipelineStage); 2] = [
|
||||
(Stage::Coding, PipelineStage::Coder),
|
||||
(Stage::Coding { claim: None }, PipelineStage::Coder),
|
||||
(Stage::Qa, PipelineStage::Qa),
|
||||
];
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ impl AgentPool {
|
||||
stage.dir_name()
|
||||
);
|
||||
|
||||
if matches!(stage, Stage::Coding) {
|
||||
if matches!(stage, Stage::Coding { .. }) {
|
||||
// Coder stage — determine qa mode to decide next step.
|
||||
let qa_mode = {
|
||||
let item_type = crate::agents::lifecycle::item_type_from_id(story_id);
|
||||
|
||||
@@ -220,7 +220,7 @@ mod tests {
|
||||
crate::db::ItemMeta::named("baz"),
|
||||
);
|
||||
|
||||
let items = scan_stage_items(&Stage::Coding);
|
||||
let items = scan_stage_items(&Stage::Coding { claim: None });
|
||||
// The global CRDT may contain items from other tests, so check
|
||||
// that our three items are present and appear in sorted order.
|
||||
assert!(
|
||||
|
||||
@@ -97,8 +97,6 @@ mod tests {
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
assert!(has_review_hold("890_spike_held"));
|
||||
}
|
||||
@@ -115,8 +113,6 @@ mod tests {
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
assert!(!has_review_hold("890_spike_active_qa"));
|
||||
}
|
||||
@@ -193,8 +189,6 @@ mod tests {
|
||||
None,
|
||||
Some("[999]"),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
assert!(has_unmet_dependencies("10_story_blocked"));
|
||||
}
|
||||
@@ -210,8 +204,6 @@ mod tests {
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
crate::crdt_state::write_item_str(
|
||||
"10_story_ok",
|
||||
@@ -221,8 +213,6 @@ mod tests {
|
||||
None,
|
||||
Some("[999]"),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
assert!(!has_unmet_dependencies("10_story_ok"));
|
||||
}
|
||||
@@ -238,8 +228,6 @@ mod tests {
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
assert!(!has_unmet_dependencies("5_story_free"));
|
||||
}
|
||||
@@ -258,8 +246,6 @@ mod tests {
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
crate::crdt_state::write_item_str(
|
||||
"503_story_dependent",
|
||||
@@ -269,8 +255,6 @@ mod tests {
|
||||
None,
|
||||
Some("[500]"),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let archived_deps = check_archived_dependencies("503_story_dependent");
|
||||
assert_eq!(archived_deps, vec![500]);
|
||||
@@ -288,8 +272,6 @@ mod tests {
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
crate::crdt_state::write_item_str(
|
||||
"503_story_waiting",
|
||||
@@ -299,8 +281,6 @@ mod tests {
|
||||
None,
|
||||
Some("[490]"),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let archived_deps = check_archived_dependencies("503_story_waiting");
|
||||
assert!(archived_deps.is_empty());
|
||||
|
||||
@@ -251,8 +251,6 @@ max_turns = 10
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
||||
// 12 turns in a single session exceeds the configured max of 10.
|
||||
@@ -381,8 +379,6 @@ max_turns = 10
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
||||
// Prior session with 5 turns (under limit alone).
|
||||
@@ -460,8 +456,6 @@ max_turns = 10
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
||||
// Session 1: exceeds limit → retry_count=1 in CRDT, NOT blocked.
|
||||
|
||||
@@ -294,8 +294,6 @@ stage = "coder"
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
||||
let pool = AgentPool::new_test(3011);
|
||||
|
||||
@@ -35,7 +35,7 @@ pub(super) fn validate_agent_stage(
|
||||
return Ok(());
|
||||
};
|
||||
let expected_stage = match story_stage {
|
||||
Stage::Coding => PipelineStage::Coder,
|
||||
Stage::Coding { .. } => PipelineStage::Coder,
|
||||
Stage::Qa => PipelineStage::Qa,
|
||||
Stage::Merge { .. } => PipelineStage::Mergemaster,
|
||||
_ => PipelineStage::Other,
|
||||
|
||||
@@ -30,7 +30,7 @@ pub(super) fn find_active_story_stage(
|
||||
if let Ok(Some(item)) = crate::pipeline_state::read_typed(story_id)
|
||||
&& matches!(
|
||||
item.stage,
|
||||
crate::pipeline_state::Stage::Coding
|
||||
crate::pipeline_state::Stage::Coding { .. }
|
||||
| crate::pipeline_state::Stage::Qa
|
||||
| crate::pipeline_state::Stage::Merge { .. }
|
||||
)
|
||||
@@ -56,7 +56,7 @@ mod tests {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
assert!(matches!(
|
||||
find_active_story_stage(tmp.path(), "10_story_test"),
|
||||
Some(crate::pipeline_state::Stage::Coding)
|
||||
Some(crate::pipeline_state::Stage::Coding { .. })
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ pub(crate) fn spawn_worktree_create_subscriber(project_root: PathBuf, port: u16)
|
||||
loop {
|
||||
match rx.recv().await {
|
||||
Ok(fired) => {
|
||||
if matches!(fired.after, Stage::Coding) {
|
||||
if matches!(fired.after, Stage::Coding { .. }) {
|
||||
on_coding_transition(&project_root, port, &fired.story_id.0).await;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user