huskies: merge 593_bug_web_ui_work_item_detail_panel_returns_404_for_crdt_only_stories
This commit is contained in:
@@ -402,6 +402,34 @@ impl AgentsApi {
|
||||
}
|
||||
}
|
||||
|
||||
// Filesystem miss — fall back to CRDT-only path (story exists in the CRDT
|
||||
// but has no corresponding .md file on disk).
|
||||
if let Some(content) = crate::db::read_content(&story_id.0) {
|
||||
let item = crate::pipeline_state::read_typed(&story_id.0)
|
||||
.map_err(|e| bad_request(format!("Pipeline read error: {e}")))?;
|
||||
let stage = item
|
||||
.as_ref()
|
||||
.map(|i| match &i.stage {
|
||||
crate::pipeline_state::Stage::Backlog => "backlog",
|
||||
crate::pipeline_state::Stage::Coding => "current",
|
||||
crate::pipeline_state::Stage::Qa => "qa",
|
||||
crate::pipeline_state::Stage::Merge { .. } => "merge",
|
||||
crate::pipeline_state::Stage::Done { .. } => "done",
|
||||
crate::pipeline_state::Stage::Archived { .. } => "archived",
|
||||
})
|
||||
.unwrap_or("unknown")
|
||||
.to_string();
|
||||
let metadata = crate::io::story_metadata::parse_front_matter(&content).ok();
|
||||
let name = metadata.as_ref().and_then(|m| m.name.clone());
|
||||
let agent = metadata.and_then(|m| m.agent);
|
||||
return Ok(Json(WorkItemContentResponse {
|
||||
content,
|
||||
stage,
|
||||
name,
|
||||
agent,
|
||||
}));
|
||||
}
|
||||
|
||||
Err(not_found(format!("Work item not found: {}", story_id.0)))
|
||||
}
|
||||
|
||||
@@ -953,6 +981,50 @@ allowed_tools = ["Read", "Bash"]
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_work_item_content_falls_back_to_crdt_when_no_file() {
|
||||
let tmp = TempDir::new().unwrap();
|
||||
let root = tmp.path().to_path_buf();
|
||||
// Seed content + CRDT with no .md file on disk.
|
||||
crate::db::write_item_with_content(
|
||||
"44_story_crdt_only",
|
||||
"1_backlog",
|
||||
"---\nname: \"CRDT Only\"\n---\n\nCRDT content.",
|
||||
);
|
||||
let ctx = AppContext::new_test(root);
|
||||
let api = AgentsApi { ctx: Arc::new(ctx) };
|
||||
let result = api
|
||||
.get_work_item_content(Path("44_story_crdt_only".to_string()))
|
||||
.await
|
||||
.unwrap()
|
||||
.0;
|
||||
assert!(result.content.contains("CRDT content."));
|
||||
assert_eq!(result.stage, "backlog");
|
||||
assert_eq!(result.name, Some("CRDT Only".to_string()));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_work_item_content_crdt_fallback_with_current_stage() {
|
||||
let tmp = TempDir::new().unwrap();
|
||||
let root = tmp.path().to_path_buf();
|
||||
// Seed a CRDT-only story in the coding/current stage.
|
||||
crate::db::write_item_with_content(
|
||||
"45_story_crdt_current",
|
||||
"2_current",
|
||||
"---\nname: \"Current CRDT\"\n---\n\nIn progress.",
|
||||
);
|
||||
let ctx = AppContext::new_test(root);
|
||||
let api = AgentsApi { ctx: Arc::new(ctx) };
|
||||
let result = api
|
||||
.get_work_item_content(Path("45_story_crdt_current".to_string()))
|
||||
.await
|
||||
.unwrap()
|
||||
.0;
|
||||
assert!(result.content.contains("In progress."));
|
||||
assert_eq!(result.stage, "current");
|
||||
assert_eq!(result.name, Some("Current CRDT".to_string()));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_work_item_content_returns_error_when_no_project_root() {
|
||||
let tmp = TempDir::new().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user