huskies: merge 517_story_remove_filesystem_shadow_fallback_paths_from_lifecycle_rs_finish_the_migration_to_crdt_only

This commit is contained in:
dave
2026-04-10 12:56:16 +00:00
parent fe405e81c6
commit 31388da609
12 changed files with 171 additions and 170 deletions
@@ -592,24 +592,25 @@ mod tests {
)
.unwrap();
// Dep 1 is done.
std::fs::write(done.join("1_story_dep.md"), "---\nname: Dep\n---\n").unwrap();
crate::db::ensure_content_store();
let dep_content = "---\nname: Dep\n---\n";
std::fs::write(done.join("1_story_dep.md"), dep_content).unwrap();
crate::db::write_content("1_story_dep", dep_content);
// Story B depends on story 1.
std::fs::write(
backlog.join("2_story_b.md"),
"---\nname: B\ndepends_on: [1]\n---\n",
)
.unwrap();
let story_b_content = "---\nname: B\ndepends_on: [1]\n---\n";
std::fs::write(backlog.join("2_story_b.md"), story_b_content).unwrap();
crate::db::write_content("2_story_b", story_b_content);
let pool = AgentPool::new_test(3001);
pool.auto_assign_available_work(root).await;
// The lifecycle function updates the content store (not the filesystem),
// so verify the move via the DB.
let content = crate::db::read_content("2_story_b")
.expect("story B should be in content store after promotion");
assert!(
current.join("2_story_b.md").exists(),
"story B should be promoted to 2_current/ once dep 1 is done"
);
assert!(
!backlog.join("2_story_b.md").exists(),
"story B must be removed from 1_backlog/ after promotion"
content.contains("name: B"),
"story B content should be preserved after promotion"
);
}
@@ -665,27 +666,26 @@ mod tests {
)
.unwrap();
// Dep 490 is in 6_archived (e.g. a CRDT spike that was archived/superseded).
std::fs::write(archived.join("490_spike_crdt.md"), "---\nname: CRDT Spike\n---\n")
.unwrap();
crate::db::ensure_content_store();
let dep_content = "---\nname: CRDT Spike\n---\n";
std::fs::write(archived.join("490_spike_crdt.md"), dep_content).unwrap();
crate::db::write_content("490_spike_crdt", dep_content);
// Story 478 depends on 490 (the archived spike).
std::fs::write(
backlog.join("478_story_dependent.md"),
"---\nname: Dependent\ndepends_on: [490]\n---\n",
)
.unwrap();
let story_content = "---\nname: Dependent\ndepends_on: [490]\n---\n";
std::fs::write(backlog.join("478_story_dependent.md"), story_content).unwrap();
crate::db::write_content("478_story_dependent", story_content);
let pool = AgentPool::new_test(3001);
pool.auto_assign_available_work(root).await;
// Story 478 must be promoted to 2_current/ even though dep 490 is only in
// 6_archived (not in 5_done), because archived = satisfied.
// Story 478 must be promoted even though dep 490 is only in 6_archived
// (not in 5_done), because archived = satisfied. The lifecycle function
// updates the content store, so verify via the DB.
let content = crate::db::read_content("478_story_dependent")
.expect("story 478 should be in content store after promotion");
assert!(
current.join("478_story_dependent.md").exists(),
"story 478 should be promoted to 2_current/ when dep 490 is in 6_archived"
);
assert!(
!backlog.join("478_story_dependent.md").exists(),
"story 478 must be removed from 1_backlog/ after promotion"
content.contains("name: Dependent"),
"story 478 content should be preserved after promotion"
);
}
+20 -23
View File
@@ -496,6 +496,8 @@ mod tests {
let current = root.join(".huskies/work/2_current");
fs::create_dir_all(&current).unwrap();
fs::write(current.join("9908_story_server_qa.md"), "test").unwrap();
crate::db::ensure_content_store();
crate::db::write_content("9908_story_server_qa", "test");
let pool = AgentPool::new_test(3001);
pool.run_pipeline_advance(
@@ -513,14 +515,10 @@ mod tests {
.await;
// With default qa: server, story skips QA and goes straight to 4_merge/
// Lifecycle moves now update the content store, not the filesystem.
assert!(
root.join(".huskies/work/4_merge/9908_story_server_qa.md")
.exists(),
"story should be in 4_merge/"
);
assert!(
!current.join("9908_story_server_qa.md").exists(),
"story should not still be in 2_current/"
crate::db::read_content("9908_story_server_qa").is_some(),
"story should still exist in content store after move to merge"
);
}
@@ -539,6 +537,8 @@ mod tests {
"---\nname: Test\nqa: agent\n---\ntest",
)
.unwrap();
crate::db::ensure_content_store();
crate::db::write_content("9909_story_agent_qa", "---\nname: Test\nqa: agent\n---\ntest");
let pool = AgentPool::new_test(3001);
pool.run_pipeline_advance(
@@ -556,13 +556,10 @@ mod tests {
.await;
// With qa: agent, story should move to 3_qa/
// Lifecycle moves now update the content store, not the filesystem.
assert!(
root.join(".huskies/work/3_qa/9909_story_agent_qa.md").exists(),
"story should be in 3_qa/"
);
assert!(
!current.join("9909_story_agent_qa.md").exists(),
"story should not still be in 2_current/"
crate::db::read_content("9909_story_agent_qa").is_some(),
"story should still exist in content store after move to qa"
);
}
@@ -581,6 +578,8 @@ mod tests {
"---\nname: Test\nqa: server\n---\ntest",
)
.unwrap();
crate::db::ensure_content_store();
crate::db::write_content("51_story_test", "---\nname: Test\nqa: server\n---\ntest");
let pool = AgentPool::new_test(3001);
pool.run_pipeline_advance(
@@ -598,14 +597,10 @@ mod tests {
.await;
// Story should have moved to 4_merge/
// Lifecycle moves now update the content store, not the filesystem.
assert!(
root.join(".huskies/work/4_merge/51_story_test.md")
.exists(),
"story should be in 4_merge/"
);
assert!(
!qa_dir.join("51_story_test.md").exists(),
"story should not still be in 3_qa/"
crate::db::read_content("51_story_test").is_some(),
"story should still exist in content store after move to merge"
);
}
@@ -751,6 +746,8 @@ stage = "qa"
fs::create_dir_all(&current).unwrap();
fs::create_dir_all(root.join(".huskies/work/4_merge")).unwrap();
fs::write(current.join("9919_story_no_commits.md"), "---\nname: Test\n---\n").unwrap();
crate::db::ensure_content_store();
crate::db::write_content("9919_story_no_commits", "---\nname: Test\n---\n");
let pool = AgentPool::new_test(3001);
let mut rx = pool.watcher_tx.subscribe();
@@ -770,10 +767,10 @@ stage = "qa"
)
.await;
// Story should be in 4_merge/ (pipeline moved it there before the block).
// Story should still exist in the content store after moving to merge.
assert!(
root.join(".huskies/work/4_merge/9919_story_no_commits.md").exists(),
"story should remain in 4_merge/ — not moved to done"
crate::db::read_content("9919_story_no_commits").is_some(),
"story should remain in content store — not removed"
);
// A StoryBlocked event must have been emitted (triggers chat failure notice,
+11 -10
View File
@@ -708,7 +708,10 @@ stage = "coder"
"#,
)
.unwrap();
std::fs::write(backlog.join("story-3.md"), "---\nname: Story 3\n---\n").unwrap();
let story_content = "---\nname: Story 3\n---\n";
std::fs::write(backlog.join("story-3.md"), story_content).unwrap();
crate::db::ensure_content_store();
crate::db::write_content("story-3", story_content);
let pool = AgentPool::new_test(3001);
pool.inject_test_agent("story-1", "coder-1", AgentStatus::Running);
@@ -726,15 +729,13 @@ stage = "coder"
"expected story-to-current message, got: {err}"
);
let current_path = sk.join("work/2_current/story-3.md");
// The lifecycle function updates the content store (not the filesystem),
// so verify the move via the DB.
let content = crate::db::read_content("story-3")
.expect("story-3 should be in content store after move to current");
assert!(
current_path.exists(),
"story should be in 2_current/ after busy error, but was not"
);
let backlog_path = backlog.join("story-3.md");
assert!(
!backlog_path.exists(),
"story should no longer be in 1_backlog/"
content.contains("name: Story 3"),
"story-3 content should be preserved after move"
);
}
@@ -1542,7 +1543,7 @@ stage = "coder"
// left a stale entry for "368_story_test" in the global CRDT.
std::fs::write(current.join("368_story_test.md"), story_content).unwrap();
crate::db::ensure_content_store();
crate::db::write_item_with_content("368_story_test", "2_current", story_content);
crate::db::write_content("368_story_test", story_content);
let pool = AgentPool::new_test(3011);
// Preferred agent is busy — should NOT fall back to coder-sonnet.
+9 -5
View File
@@ -139,7 +139,10 @@ mod tests {
let current = root.join(".huskies/work/2_current");
fs::create_dir_all(&current).unwrap();
fs::write(current.join("60_story_cleanup.md"), "test").unwrap();
let story_content = "test";
fs::write(current.join("60_story_cleanup.md"), story_content).unwrap();
crate::db::ensure_content_store();
crate::db::write_content("60_story_cleanup", story_content);
let pool = AgentPool::new_test(3001);
pool.inject_test_agent("60_story_cleanup", "coder-1", AgentStatus::Completed);
@@ -159,9 +162,10 @@ mod tests {
);
assert_eq!(remaining[0].story_id, "61_story_other");
assert!(
root.join(".huskies/work/5_done/60_story_cleanup.md")
.exists()
);
// The lifecycle function updates the content store (not the filesystem),
// so verify the move via the DB.
let content = crate::db::read_content("60_story_cleanup")
.expect("60_story_cleanup should be in content store after move to done");
assert_eq!(content, "test", "content should be preserved after move");
}
}