huskies: merge 1086 story Pipeline+Status split — Step C: migrate auto-assign, subscribers, and lifecycle transitions to read Pipeline + Status
This commit is contained in:
@@ -6,10 +6,20 @@
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::pipeline_state::Stage;
|
||||
use crate::pipeline_state::{Pipeline, Stage, Status};
|
||||
use crate::slog;
|
||||
use crate::slog_warn;
|
||||
|
||||
/// Story 1086: matches the set of terminal stages used by the worktree-cleanup
|
||||
/// subscriber via the typed [`Status`] / [`Pipeline`] projections. Excludes
|
||||
/// `Status::Rejected` so rejected stories keep their worktree for human review.
|
||||
fn is_cleanup_terminal(stage: &Stage) -> bool {
|
||||
matches!(
|
||||
stage.status(),
|
||||
Status::Done | Status::Abandoned | Status::Superseded
|
||||
) || matches!(stage.pipeline(), Pipeline::Archived)
|
||||
}
|
||||
|
||||
/// Spawn a background task that creates a git worktree when a story enters `Stage::Coding`.
|
||||
///
|
||||
/// Subscribes to the pipeline transition broadcast channel. On each
|
||||
@@ -22,7 +32,14 @@ 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 { .. }) {
|
||||
// Story 1086: classify by Pipeline column. `Pipeline::Coding`
|
||||
// covers `Stage::Coding` and `Stage::Blocked` — but Blocked has
|
||||
// no worktree to create, so we still need the Stage::Coding
|
||||
// payload check. Use a layered match: pipeline first for fast
|
||||
// skip, then variant guard.
|
||||
if fired.after.pipeline() == Pipeline::Coding
|
||||
&& matches!(fired.after, Stage::Coding { .. })
|
||||
{
|
||||
on_coding_transition(&project_root, port, &fired.story_id.0).await;
|
||||
}
|
||||
}
|
||||
@@ -50,13 +67,7 @@ pub(crate) fn spawn_worktree_cleanup_subscriber(project_root: PathBuf) {
|
||||
loop {
|
||||
match rx.recv().await {
|
||||
Ok(fired) => {
|
||||
if matches!(
|
||||
fired.after,
|
||||
Stage::Done { .. }
|
||||
| Stage::Archived { .. }
|
||||
| Stage::Abandoned { .. }
|
||||
| Stage::Superseded { .. }
|
||||
) {
|
||||
if is_cleanup_terminal(&fired.after) {
|
||||
on_terminal_transition(&project_root, &fired.story_id.0).await;
|
||||
}
|
||||
}
|
||||
@@ -79,7 +90,11 @@ pub(crate) fn spawn_worktree_cleanup_subscriber(project_root: PathBuf) {
|
||||
/// so that Lagged events on the broadcast channel never leave Coding stories without worktrees.
|
||||
pub(crate) async fn reconcile_worktree_create(project_root: &Path, port: u16) {
|
||||
for item in crate::pipeline_state::read_all_typed() {
|
||||
if matches!(item.stage, crate::pipeline_state::Stage::Coding { .. }) {
|
||||
// Story 1086: filter by Pipeline column then narrow to the `Coding`
|
||||
// variant (Blocked is in `Pipeline::Coding` but has no worktree).
|
||||
if item.stage.pipeline() == Pipeline::Coding
|
||||
&& matches!(item.stage, crate::pipeline_state::Stage::Coding { .. })
|
||||
{
|
||||
on_coding_transition(project_root, port, &item.story_id.0).await;
|
||||
}
|
||||
}
|
||||
@@ -92,13 +107,7 @@ pub(crate) async fn reconcile_worktree_create(project_root: &Path, port: u16) {
|
||||
/// the broadcast channel never leave terminal stories with dangling worktrees.
|
||||
pub(crate) async fn reconcile_worktree_cleanup(project_root: &Path) {
|
||||
for item in crate::pipeline_state::read_all_typed() {
|
||||
if matches!(
|
||||
item.stage,
|
||||
crate::pipeline_state::Stage::Done { .. }
|
||||
| crate::pipeline_state::Stage::Archived { .. }
|
||||
| crate::pipeline_state::Stage::Abandoned { .. }
|
||||
| crate::pipeline_state::Stage::Superseded { .. }
|
||||
) {
|
||||
if is_cleanup_terminal(&item.stage) {
|
||||
on_terminal_transition(project_root, &item.story_id.0).await;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user