huskies: merge 1016

This commit is contained in:
dave
2026-05-13 23:51:07 +00:00
parent 5ed1438ab9
commit 29e800da21
10 changed files with 180 additions and 568 deletions
@@ -568,4 +568,72 @@ mod tests {
found {active_coder_count} active entries"
);
}
// ── AC4: startup event replay + pool reconstruction ──────────────────
/// AC4: Simulates a server restart by seeding the CRDT with a story in
/// Coding stage, calling `replay_current_pipeline_state` (the new startup
/// path), then `auto_assign_available_work`. Asserts the pool ends in the
/// expected state: exactly one agent assigned to the story.
#[tokio::test]
async fn startup_replay_followed_by_auto_assign_assigns_agent_once() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".huskies");
std::fs::create_dir_all(&sk).unwrap();
std::fs::write(
sk.join("project.toml"),
"[[agent]]\nname = \"coder-1\"\nstage = \"coder\"\n",
)
.unwrap();
crate::db::ensure_content_store();
let story_id = "9903_restart_replay";
crate::db::write_item_with_content(
story_id,
"2_current",
"---\nname: Restart Replay\n---\n",
crate::db::ItemMeta::named("Restart Replay"),
);
let pool = AgentPool::new_test(3001);
// Simulate startup: replay current state, then auto-assign.
crate::pipeline_state::replay_current_pipeline_state();
pool.auto_assign_available_work(tmp.path()).await;
let count_after_first = {
let agents = pool.agents.lock().unwrap();
agents
.iter()
.filter(|(key, a)| {
key.contains(story_id)
&& matches!(a.status, AgentStatus::Pending | AgentStatus::Running)
})
.count()
};
// AC3 (idempotency): replaying twice must not double-spawn agents.
crate::pipeline_state::replay_current_pipeline_state();
pool.auto_assign_available_work(tmp.path()).await;
let count_after_second = {
let agents = pool.agents.lock().unwrap();
agents
.iter()
.filter(|(key, a)| {
key.contains(story_id)
&& matches!(a.status, AgentStatus::Pending | AgentStatus::Running)
})
.count()
};
assert!(
count_after_first <= 1,
"after first replay+assign at most one agent must be assigned to {story_id}"
);
assert_eq!(
count_after_first, count_after_second,
"second replay must not spawn additional agents (idempotency)"
);
}
}