huskies: merge 872

This commit is contained in:
dave
2026-04-29 15:54:33 +00:00
parent 7505f7fdeb
commit 9bd3c10a09
10 changed files with 147 additions and 12 deletions
+1 -1
View File
@@ -53,7 +53,7 @@ pub use types::{
};
pub use write::{
bump_retry_count, migrate_names_from_slugs, migrate_story_ids_to_numeric, name_from_story_id,
set_agent, set_qa_mode, set_retry_count, write_item,
set_agent, set_depends_on, set_qa_mode, set_retry_count, write_item,
};
#[cfg(test)]
+83
View File
@@ -186,6 +186,32 @@ pub fn migrate_names_from_slugs() {
slog!("[crdt] Migrated names for {count} items from story ID slugs");
}
/// Set the typed `depends_on` CRDT register for a pipeline item.
///
/// Encodes `deps` as a compact JSON array string (e.g. `"[837]"`) and writes it
/// to the item's `depends_on` register. An empty slice clears the register to an
/// empty string, which means "no dependencies".
///
/// Returns `true` if the item was found and the op was applied, `false` otherwise.
pub fn set_depends_on(story_id: &str, deps: &[u32]) -> bool {
let Some(state_mutex) = get_crdt() else {
return false;
};
let Ok(mut state) = state_mutex.lock() else {
return false;
};
let Some(&idx) = state.index.get(story_id) else {
return false;
};
let value = if deps.is_empty() {
String::new()
} else {
serde_json::to_string(deps).unwrap_or_default()
};
apply_and_persist(&mut state, |s| s.crdt.doc.items[idx].depends_on.set(value));
true
}
/// Set the `agent` field for a pipeline item by its story ID.
///
/// `Some(name)` writes the agent name into the CRDT register.
@@ -715,6 +741,63 @@ mod tests {
migrate_names_from_slugs();
}
// ── set_depends_on regression tests ──────────────────────────────────────
#[test]
fn set_depends_on_round_trip_and_clear() {
use super::super::read::{check_unmet_deps_crdt, read_item};
init_for_test();
write_item(
"872_test_target",
"1_backlog",
Some("Target"),
None,
None,
None,
None,
None,
None,
None,
);
// Set depends_on to [837] and verify CRDT register holds the list.
let ok = set_depends_on("872_test_target", &[837]);
assert!(ok, "set_depends_on should return true for known item");
let view = read_item("872_test_target").unwrap();
assert_eq!(
view.depends_on,
Some(vec![837]),
"CRDT register should hold [837]"
);
// Clear by passing an empty slice.
let ok = set_depends_on("872_test_target", &[]);
assert!(ok, "set_depends_on([]) should return true");
let view = read_item("872_test_target").unwrap();
assert_eq!(
view.depends_on, None,
"clearing should leave register unset"
);
// Auto-assigner sees no unmet dependency after clearing.
let unmet = check_unmet_deps_crdt("872_test_target");
assert!(
unmet.is_empty(),
"after clearing deps, auto-assigner should see no unmet dependencies"
);
}
#[test]
fn set_depends_on_returns_false_for_unknown_story() {
init_for_test();
let ok = set_depends_on("nonexistent_story_872", &[1, 2, 3]);
assert!(
!ok,
"set_depends_on should return false for unknown story_id"
);
}
// ── set_agent tests ──────────────────────────────────────────────────────
#[test]