huskies: merge 961

This commit is contained in:
dave
2026-05-13 11:27:21 +00:00
parent 78b1ecdc3c
commit 8b53e20ca9
38 changed files with 327 additions and 146 deletions
@@ -76,7 +76,7 @@ async fn mergemaster_blocks_and_sends_story_blocked_when_no_commits_ahead() {
// Story should still exist in the content store after moving to merge.
assert!(
crate::db::read_content("9919_story_no_commits").is_some(),
crate::db::read_content(crate::db::ContentKey::Story("9919_story_no_commits")).is_some(),
"story should remain in content store — not removed"
);
@@ -249,7 +249,7 @@ async fn stale_mergemaster_advance_for_done_story_is_noop() {
// Seed the story in 5_done via the DB, which also writes to the CRDT.
let story_id = "9929_story_zombie_merge";
let content = "---\nname: Zombie Merge Test\n---\n";
crate::db::write_content(story_id, content);
crate::db::write_content(crate::db::ContentKey::Story(story_id), content);
crate::db::write_item_with_content(
story_id,
"5_done",
@@ -387,7 +387,10 @@ async fn work_survived_advances_to_qa_instead_of_blocking() {
// Set up the story in the content store.
crate::db::ensure_content_store();
crate::db::write_content("9945_story_survived", "---\nname: Survived Test\n---\n");
crate::db::write_content(
crate::db::ContentKey::Story("9945_story_survived"),
"---\nname: Survived Test\n---\n",
);
crate::db::write_item_with_content(
"9945_story_survived",
"2_current",
@@ -397,7 +400,10 @@ async fn work_survived_advances_to_qa_instead_of_blocking() {
// Simulate a passing run_tests call during the agent's session (bug 668):
// the agent ran script/test, it passed, and the server captured the evidence.
crate::db::write_content("9945_story_survived:run_tests_ok", "1");
crate::db::write_content(
crate::db::ContentKey::RunTestsOk("9945_story_survived"),
"1",
);
let pool = AgentPool::new_test(3001);
@@ -421,7 +427,7 @@ async fn work_survived_advances_to_qa_instead_of_blocking() {
// Story should have advanced — content store should reflect the move.
// The work-survived check should have moved it to QA (or merge for
// server qa mode), NOT incremented retry_count.
let content = crate::db::read_content("9945_story_survived")
let content = crate::db::read_content(crate::db::ContentKey::Story("9945_story_survived"))
.expect("story should exist in content store");
assert!(
!content.contains("blocked"),
@@ -482,7 +488,10 @@ async fn no_committed_work_still_retries_and_blocks() {
// Set up the story with max_retries=1 so it blocks immediately.
crate::crdt_state::init_for_test();
crate::db::ensure_content_store();
crate::db::write_content("9946_story_nowork", "---\nname: No Work Test\n---\n");
crate::db::write_content(
crate::db::ContentKey::Story("9946_story_nowork"),
"---\nname: No Work Test\n---\n",
);
crate::db::write_item_with_content(
"9946_story_nowork",
"2_current",
@@ -609,7 +618,7 @@ async fn gates_failed_no_test_evidence_does_not_advance() {
// Set up the story with max_retries=1 so we can observe the retry/block.
crate::db::ensure_content_store();
crate::db::write_content(
"9947_story_no_evidence",
crate::db::ContentKey::Story("9947_story_no_evidence"),
"---\nname: No Evidence Test\n---\n",
);
crate::db::write_item_with_content(
@@ -620,7 +629,7 @@ async fn gates_failed_no_test_evidence_does_not_advance() {
);
// Explicitly ensure no test evidence exists for this story.
crate::db::delete_content("9947_story_no_evidence:run_tests_ok");
crate::db::delete_content(crate::db::ContentKey::RunTestsOk("9947_story_no_evidence"));
fs::create_dir_all(root.join(".huskies")).unwrap();
fs::write(
@@ -740,7 +749,7 @@ async fn gates_failed_with_test_evidence_and_committed_work_advances() {
crate::db::ensure_content_store();
crate::db::write_content(
"9948_story_with_evidence",
crate::db::ContentKey::Story("9948_story_with_evidence"),
"---\nname: With Evidence Test\n---\n",
);
crate::db::write_item_with_content(
@@ -752,7 +761,10 @@ async fn gates_failed_with_test_evidence_and_committed_work_advances() {
// Write the run_tests evidence — simulates the agent having called run_tests
// MCP and getting a passing result before it crashed.
crate::db::write_content("9948_story_with_evidence:run_tests_ok", "1");
crate::db::write_content(
crate::db::ContentKey::RunTestsOk("9948_story_with_evidence"),
"1",
);
let pool = AgentPool::new_test(3001);
@@ -774,7 +786,7 @@ async fn gates_failed_with_test_evidence_and_committed_work_advances() {
.await;
// Story should advance (not blocked, no retry_count).
let content = crate::db::read_content("9948_story_with_evidence")
let content = crate::db::read_content(crate::db::ContentKey::Story("9948_story_with_evidence"))
.expect("story must exist in content store");
assert!(
!content.contains("blocked"),
@@ -786,7 +798,10 @@ async fn gates_failed_with_test_evidence_and_committed_work_advances() {
);
// Evidence must be consumed (cleared) after use.
assert!(
crate::db::read_content("9948_story_with_evidence:run_tests_ok").is_none(),
crate::db::read_content(crate::db::ContentKey::RunTestsOk(
"9948_story_with_evidence"
))
.is_none(),
"run_tests evidence must be cleared after pipeline advance consumes it"
);
}
@@ -919,7 +934,9 @@ stage = "coder"
crate::db::ItemMeta::named("Recovery Test"),
);
// Ensure no stale recovery key exists.
crate::db::delete_content("9954_story_recovery:commit_recovery_pending");
crate::db::delete_content(crate::db::ContentKey::CommitRecoveryPending(
"9954_story_recovery",
));
let pool = AgentPool::new_test(3001);
@@ -966,7 +983,10 @@ stage = "coder"
// The recovery key must be set so a second failure triggers a block.
assert!(
crate::db::read_content("9954_story_recovery:commit_recovery_pending").is_some(),
crate::db::read_content(crate::db::ContentKey::CommitRecoveryPending(
"9954_story_recovery"
))
.is_some(),
"commit_recovery_pending key must be set after issuing recovery respawn"
);
}
@@ -1008,7 +1028,10 @@ stage = "coder"
// Simulate the recovery key already being set (first recovery respawn was
// issued previously).
crate::db::write_content("9955_story_recovery2:commit_recovery_pending", "1");
crate::db::write_content(
crate::db::ContentKey::CommitRecoveryPending("9955_story_recovery2"),
"1",
);
let pool = AgentPool::new_test(3001);
let mut rx = pool.watcher_tx.subscribe();
@@ -1052,7 +1075,10 @@ stage = "coder"
// The recovery key must be cleared after blocking.
assert!(
crate::db::read_content("9955_story_recovery2:commit_recovery_pending").is_none(),
crate::db::read_content(crate::db::ContentKey::CommitRecoveryPending(
"9955_story_recovery2"
))
.is_none(),
"commit_recovery_pending key must be cleared after blocking the story"
);
@@ -1128,7 +1154,10 @@ async fn coder_completion_with_test_evidence_and_zero_commits_does_not_advance()
// Simulate the agent having called run_tests with a passing result (bug-645
// evidence) — but the feature branch still has zero commits ahead of master.
crate::db::write_content("9953_story_zero_commits:run_tests_ok", "1");
crate::db::write_content(
crate::db::ContentKey::RunTestsOk("9953_story_zero_commits"),
"1",
);
// Write a project.toml with max_retries=1 so the story blocks immediately,
// giving us a clean assertion target (StoryBlocked event).
@@ -1193,7 +1222,8 @@ async fn coder_completion_with_test_evidence_and_zero_commits_does_not_advance()
// Test evidence must have been consumed (cleared) by the advance handler.
assert!(
crate::db::read_content("9953_story_zero_commits:run_tests_ok").is_none(),
crate::db::read_content(crate::db::ContentKey::RunTestsOk("9953_story_zero_commits"))
.is_none(),
"run_tests evidence must be cleared after pipeline advance consumes it"
);
}