huskies: merge 1203 bug Gateway status gives no response — 1187 made it proxy-only with no local resolution or error surfacing

This commit is contained in:
Huskies Agent
2026-07-17 23:23:52 +00:00
parent fd83ff2f53
commit 75c4a8de33
3 changed files with 315 additions and 9 deletions
+125
View File
@@ -125,6 +125,51 @@ pub fn format_overview_compact(items_by_project: &BTreeMap<String, Value>) -> St
format!("**Overview: Active Work**\n\n{}", sections.join("\n\n"))
}
/// Find the registered project whose pipeline contains a story with the
/// given numeric ID prefix, searching `active`, `backlog`, and `archived`
/// alike so gateway `status <n>` resolves regardless of which project is
/// currently "active" (story 1203).
///
/// `items_by_project` is the output of `fetch_all_project_pipeline_items`.
/// Projects whose entry carries an `error` key (unreachable, no URL) are
/// skipped rather than matched. Returns the owning project's name, or `None`
/// if no registered, reachable project has a matching story.
pub fn find_project_containing_story(
items_by_project: &BTreeMap<String, Value>,
num_str: &str,
) -> Option<String> {
for (name, status) in items_by_project {
if status.get("error").is_some() {
continue;
}
for key in ["active", "backlog", "archived"] {
let Some(items) = status.get(key).and_then(|a| a.as_array()) else {
continue;
};
let found = items.iter().any(|item| {
item.get("story_id")
.and_then(|s| s.as_str())
.map(|story_id| story_number_prefix(story_id) == num_str)
.unwrap_or(false)
});
if found {
return Some(name.clone());
}
}
}
None
}
/// Extract the leading numeric prefix from a `story_id` like `"42_story_x"`,
/// or `""` if the ID has no purely-digit prefix before the first `_`.
fn story_number_prefix(story_id: &str) -> &str {
story_id
.split('_')
.next()
.filter(|s| !s.is_empty() && s.chars().all(|c| c.is_ascii_digit()))
.unwrap_or("")
}
// ── Tests ────────────────────────────────────────────────────────────────────
#[cfg(test)]
@@ -267,4 +312,84 @@ mod tests {
// alpha's section should come before beta's (BTreeMap sorted order).
assert!(output.find("alpha").unwrap() < output.find("beta").unwrap());
}
// ── find_project_containing_story ──────────────────────────────────────
#[test]
fn find_story_matches_active_array() {
let mut items = BTreeMap::new();
items.insert(
"huskies".to_string(),
json!({ "active": [{ "story_id": "42_story_x", "name": "X", "stage": "current" }], "backlog": [], "archived": [] }),
);
assert_eq!(
find_project_containing_story(&items, "42"),
Some("huskies".to_string())
);
}
#[test]
fn find_story_matches_backlog_array() {
let mut items = BTreeMap::new();
items.insert(
"huskies".to_string(),
json!({ "active": [], "backlog": [{ "story_id": "77_story_y", "name": "Y" }], "archived": [] }),
);
assert_eq!(
find_project_containing_story(&items, "77"),
Some("huskies".to_string())
);
}
#[test]
fn find_story_matches_archived_array() {
let mut items = BTreeMap::new();
items.insert(
"huskies".to_string(),
json!({ "active": [], "backlog": [], "archived": [{ "story_id": "13_story_z", "name": "Z" }] }),
);
assert_eq!(
find_project_containing_story(&items, "13"),
Some("huskies".to_string())
);
}
#[test]
fn find_story_returns_none_when_not_present_anywhere() {
let mut items = BTreeMap::new();
items.insert(
"huskies".to_string(),
json!({ "active": [{ "story_id": "1_story_a", "name": "A" }], "backlog": [], "archived": [] }),
);
assert_eq!(find_project_containing_story(&items, "999"), None);
}
#[test]
fn find_story_skips_unreachable_projects() {
let mut items = BTreeMap::new();
items.insert(
"broken".to_string(),
json!({ "error": "connection refused" }),
);
items.insert(
"huskies".to_string(),
json!({ "active": [{ "story_id": "5_story_b", "name": "B" }], "backlog": [], "archived": [] }),
);
assert_eq!(
find_project_containing_story(&items, "5"),
Some("huskies".to_string())
);
}
/// A project literally named after the digits (e.g. "42") must not
/// spuriously match — only `story_id` prefixes are compared.
#[test]
fn find_story_does_not_match_on_project_name() {
let mut items = BTreeMap::new();
items.insert(
"42".to_string(),
json!({ "active": [{ "story_id": "1_story_a", "name": "A" }], "backlog": [], "archived": [] }),
);
assert_eq!(find_project_containing_story(&items, "42"), None);
}
}