story-kit: merge 173_bug_pipeline_board_lozenges_dont_update_on_agent_state_changes
This commit is contained in:
@@ -587,6 +587,7 @@ impl AgentPool {
|
||||
&sid,
|
||||
&aname,
|
||||
session_id,
|
||||
watcher_tx_clone.clone(),
|
||||
)
|
||||
.await;
|
||||
Self::notify_agent_state_changed(&watcher_tx_clone);
|
||||
@@ -2002,6 +2003,7 @@ async fn run_server_owned_completion(
|
||||
story_id: &str,
|
||||
agent_name: &str,
|
||||
session_id: Option<String>,
|
||||
watcher_tx: broadcast::Sender<WatcherEvent>,
|
||||
) {
|
||||
let key = composite_key(story_id, agent_name);
|
||||
|
||||
@@ -2094,7 +2096,7 @@ async fn run_server_owned_completion(
|
||||
|
||||
// Advance the pipeline state machine in a background task.
|
||||
// Uses a non-async helper to break the opaque type cycle.
|
||||
spawn_pipeline_advance(Arc::clone(agents), port, story_id, agent_name);
|
||||
spawn_pipeline_advance(Arc::clone(agents), port, story_id, agent_name, watcher_tx);
|
||||
}
|
||||
|
||||
/// Spawn pipeline advancement as a background task.
|
||||
@@ -2106,11 +2108,11 @@ fn spawn_pipeline_advance(
|
||||
port: u16,
|
||||
story_id: &str,
|
||||
agent_name: &str,
|
||||
watcher_tx: broadcast::Sender<WatcherEvent>,
|
||||
) {
|
||||
let sid = story_id.to_string();
|
||||
let aname = agent_name.to_string();
|
||||
tokio::spawn(async move {
|
||||
let (watcher_tx, _) = broadcast::channel(16);
|
||||
let pool = AgentPool {
|
||||
agents,
|
||||
port,
|
||||
@@ -3667,7 +3669,7 @@ mod tests {
|
||||
// Subscribe before calling so we can check if Done event was emitted.
|
||||
let mut rx = pool.subscribe("s10", "coder-1").unwrap();
|
||||
|
||||
run_server_owned_completion(&pool.agents, pool.port, "s10", "coder-1", Some("sess-1".to_string()))
|
||||
run_server_owned_completion(&pool.agents, pool.port, "s10", "coder-1", Some("sess-1".to_string()), pool.watcher_tx.clone())
|
||||
.await;
|
||||
|
||||
// Status should remain Completed (unchanged) — no gate re-run.
|
||||
@@ -3707,7 +3709,7 @@ mod tests {
|
||||
|
||||
let mut rx = pool.subscribe("s11", "coder-1").unwrap();
|
||||
|
||||
run_server_owned_completion(&pool.agents, pool.port, "s11", "coder-1", Some("sess-2".to_string()))
|
||||
run_server_owned_completion(&pool.agents, pool.port, "s11", "coder-1", Some("sess-2".to_string()), pool.watcher_tx.clone())
|
||||
.await;
|
||||
|
||||
// Completion report should exist (gates were run, though they may fail
|
||||
@@ -3760,7 +3762,7 @@ mod tests {
|
||||
repo.to_path_buf(),
|
||||
);
|
||||
|
||||
run_server_owned_completion(&pool.agents, pool.port, "s12", "coder-1", None)
|
||||
run_server_owned_completion(&pool.agents, pool.port, "s12", "coder-1", None, pool.watcher_tx.clone())
|
||||
.await;
|
||||
|
||||
let agents = pool.agents.lock().unwrap();
|
||||
@@ -3784,7 +3786,7 @@ mod tests {
|
||||
async fn server_owned_completion_nonexistent_agent_is_noop() {
|
||||
let pool = AgentPool::new_test(3001);
|
||||
// Should not panic or error — just silently return.
|
||||
run_server_owned_completion(&pool.agents, pool.port, "nonexistent", "bot", None)
|
||||
run_server_owned_completion(&pool.agents, pool.port, "nonexistent", "bot", None, pool.watcher_tx.clone())
|
||||
.await;
|
||||
}
|
||||
|
||||
@@ -6383,4 +6385,87 @@ theirs
|
||||
"child_killers should be cleared after kill_all_children"
|
||||
);
|
||||
}
|
||||
|
||||
// ── Bug 173: pipeline advance sends AgentStateChanged via real watcher_tx ─
|
||||
|
||||
#[tokio::test]
|
||||
async fn pipeline_advance_sends_agent_state_changed_to_watcher_tx() {
|
||||
use std::fs;
|
||||
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let root = tmp.path();
|
||||
|
||||
// Set up story in 2_current/
|
||||
let current = root.join(".story_kit/work/2_current");
|
||||
fs::create_dir_all(¤t).unwrap();
|
||||
fs::write(current.join("173_story_test.md"), "test").unwrap();
|
||||
// Ensure 3_qa/ exists for the move target
|
||||
fs::create_dir_all(root.join(".story_kit/work/3_qa")).unwrap();
|
||||
// Ensure 1_upcoming/ exists (start_agent calls move_story_to_current)
|
||||
fs::create_dir_all(root.join(".story_kit/work/1_upcoming")).unwrap();
|
||||
|
||||
// Write a project.toml with a qa agent so start_agent can resolve it.
|
||||
fs::create_dir_all(root.join(".story_kit")).unwrap();
|
||||
fs::write(
|
||||
root.join(".story_kit/project.toml"),
|
||||
r#"
|
||||
[[agent]]
|
||||
name = "coder-1"
|
||||
role = "Coder"
|
||||
command = "echo"
|
||||
args = ["noop"]
|
||||
prompt = "test"
|
||||
stage = "coder"
|
||||
|
||||
[[agent]]
|
||||
name = "qa"
|
||||
role = "QA"
|
||||
command = "echo"
|
||||
args = ["noop"]
|
||||
prompt = "test"
|
||||
stage = "qa"
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let pool = AgentPool::new_test(3001);
|
||||
pool.inject_test_agent_with_completion(
|
||||
"173_story_test",
|
||||
"coder-1",
|
||||
AgentStatus::Completed,
|
||||
root.to_path_buf(),
|
||||
CompletionReport {
|
||||
summary: "done".to_string(),
|
||||
gates_passed: true,
|
||||
gate_output: String::new(),
|
||||
},
|
||||
);
|
||||
|
||||
// Subscribe to the watcher channel BEFORE the pipeline advance.
|
||||
let mut rx = pool.watcher_tx.subscribe();
|
||||
|
||||
// Call pipeline advance directly. This will:
|
||||
// 1. Move the story to 3_qa/
|
||||
// 2. Start the QA agent (which calls notify_agent_state_changed)
|
||||
// Note: the actual agent process will fail (no real worktree), but the
|
||||
// agent insertion and notification happen before the background spawn.
|
||||
pool.run_pipeline_advance_for_completed_agent("173_story_test", "coder-1")
|
||||
.await;
|
||||
|
||||
// The pipeline advance should have sent AgentStateChanged events via
|
||||
// the pool's watcher_tx (not a dummy channel). Collect all events.
|
||||
let mut got_agent_state_changed = false;
|
||||
while let Ok(evt) = rx.try_recv() {
|
||||
if matches!(evt, WatcherEvent::AgentStateChanged) {
|
||||
got_agent_state_changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert!(
|
||||
got_agent_state_changed,
|
||||
"pipeline advance should send AgentStateChanged through the real watcher_tx \
|
||||
(bug 173: lozenges must update when agents are assigned during pipeline advance)"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user