huskies: merge 530_story_eliminate_filesystem_markdown_shadows_entirely_crdt_db_is_the_only_story_store
This commit is contained in:
@@ -92,7 +92,7 @@ pub async fn handle_assign(
|
||||
agents: &AgentPool,
|
||||
) -> String {
|
||||
// Find the story by numeric prefix: CRDT → content store → filesystem.
|
||||
let (story_id, _stage_dir, path, content) =
|
||||
let (story_id, _stage_dir, _path, content) =
|
||||
match crate::chat::lookup::find_story_by_number(project_root, story_number) {
|
||||
Some(found) => found,
|
||||
None => {
|
||||
@@ -102,21 +102,24 @@ pub async fn handle_assign(
|
||||
}
|
||||
};
|
||||
|
||||
let story_name = content
|
||||
.or_else(|| std::fs::read_to_string(&path).ok())
|
||||
.and_then(|contents| parse_front_matter(&contents).ok().and_then(|m| m.name))
|
||||
let current_content = content.or_else(|| crate::db::read_content(&story_id));
|
||||
|
||||
let story_name = current_content
|
||||
.as_ref()
|
||||
.and_then(|c| parse_front_matter(c).ok().and_then(|m| m.name))
|
||||
.unwrap_or_else(|| story_id.clone());
|
||||
|
||||
let agent_name = resolve_agent_name(model_str);
|
||||
|
||||
// Write `agent: <agent_name>` into the story's front matter.
|
||||
let write_result = std::fs::read_to_string(&path)
|
||||
.map_err(|e| format!("Failed to read story file: {e}"))
|
||||
.and_then(|contents| {
|
||||
// Write `agent: <agent_name>` into the story's front matter via content store.
|
||||
let write_result = match current_content {
|
||||
Some(contents) => {
|
||||
let updated = set_front_matter_field(&contents, "agent", &agent_name);
|
||||
std::fs::write(&path, &updated)
|
||||
.map_err(|e| format!("Failed to write story file: {e}"))
|
||||
});
|
||||
crate::db::write_item_with_content(&story_id, &_stage_dir, &updated);
|
||||
Ok(())
|
||||
}
|
||||
None => Err(format!("Story content not found for {story_id}")),
|
||||
};
|
||||
|
||||
if let Err(e) = write_result {
|
||||
return format!("Failed to assign model to **{story_name}**: {e}");
|
||||
@@ -304,15 +307,11 @@ mod tests {
|
||||
|
||||
// -- handle_assign (no running coder) ------------------------------------
|
||||
|
||||
use crate::chat::lookup::STAGES;
|
||||
use crate::chat::test_helpers::write_story_file;
|
||||
|
||||
#[tokio::test]
|
||||
async fn handle_assign_returns_not_found_for_unknown_number() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
for stage in STAGES {
|
||||
std::fs::create_dir_all(tmp.path().join(".huskies/work").join(stage)).unwrap();
|
||||
}
|
||||
let agents = std::sync::Arc::new(AgentPool::new_test(3000));
|
||||
let response = handle_assign("Timmy", "999", "opus", tmp.path(), &agents).await;
|
||||
assert!(
|
||||
@@ -327,12 +326,12 @@ mod tests {
|
||||
write_story_file(
|
||||
tmp.path(),
|
||||
"1_backlog",
|
||||
"42_story_test.md",
|
||||
"---\nname: Test Feature\n---\n\n# Story 42\n",
|
||||
"9972_story_test.md",
|
||||
"---\nname: Test Feature\n---\n\n# Story 9972\n",
|
||||
);
|
||||
|
||||
let agents = std::sync::Arc::new(AgentPool::new_test(3000));
|
||||
let response = handle_assign("Timmy", "42", "opus", tmp.path(), &agents).await;
|
||||
let response = handle_assign("Timmy", "9972", "opus", tmp.path(), &agents).await;
|
||||
|
||||
assert!(
|
||||
response.contains("coder-opus"),
|
||||
@@ -348,10 +347,8 @@ mod tests {
|
||||
"response should indicate assignment for future start: {response}"
|
||||
);
|
||||
|
||||
let contents = std::fs::read_to_string(
|
||||
tmp.path().join(".huskies/work/1_backlog/42_story_test.md"),
|
||||
)
|
||||
.unwrap();
|
||||
let contents = crate::db::read_content("9972_story_test")
|
||||
.expect("content store should have updated content");
|
||||
assert!(
|
||||
contents.contains("agent: coder-opus"),
|
||||
"front matter should contain agent field: {contents}"
|
||||
@@ -364,12 +361,12 @@ mod tests {
|
||||
write_story_file(
|
||||
tmp.path(),
|
||||
"1_backlog",
|
||||
"7_story_small.md",
|
||||
"9973_story_small.md",
|
||||
"---\nname: Small Story\n---\n",
|
||||
);
|
||||
|
||||
let agents = std::sync::Arc::new(AgentPool::new_test(3000));
|
||||
let response = handle_assign("Timmy", "7", "coder-opus", tmp.path(), &agents).await;
|
||||
let response = handle_assign("Timmy", "9973", "coder-opus", tmp.path(), &agents).await;
|
||||
|
||||
assert!(
|
||||
response.contains("coder-opus"),
|
||||
@@ -380,10 +377,8 @@ mod tests {
|
||||
"must not double-prefix: {response}"
|
||||
);
|
||||
|
||||
let contents = std::fs::read_to_string(
|
||||
tmp.path().join(".huskies/work/1_backlog/7_story_small.md"),
|
||||
)
|
||||
.unwrap();
|
||||
let contents = crate::db::read_content("9973_story_small")
|
||||
.expect("content store should have updated content");
|
||||
assert!(
|
||||
contents.contains("agent: coder-opus"),
|
||||
"must write coder-opus, not coder-coder-opus: {contents}"
|
||||
@@ -396,17 +391,15 @@ mod tests {
|
||||
write_story_file(
|
||||
tmp.path(),
|
||||
"1_backlog",
|
||||
"5_story_existing.md",
|
||||
"9974_story_existing.md",
|
||||
"---\nname: Existing\nagent: coder-sonnet\n---\n",
|
||||
);
|
||||
|
||||
let agents = std::sync::Arc::new(AgentPool::new_test(3000));
|
||||
handle_assign("Timmy", "5", "opus", tmp.path(), &agents).await;
|
||||
handle_assign("Timmy", "9974", "opus", tmp.path(), &agents).await;
|
||||
|
||||
let contents = std::fs::read_to_string(
|
||||
tmp.path().join(".huskies/work/1_backlog/5_story_existing.md"),
|
||||
)
|
||||
.unwrap();
|
||||
let contents = crate::db::read_content("9974_story_existing")
|
||||
.expect("content store should have updated content");
|
||||
assert!(
|
||||
contents.contains("agent: coder-opus"),
|
||||
"should overwrite old agent: {contents}"
|
||||
|
||||
Reference in New Issue
Block a user