huskies: merge 888

This commit is contained in:
dave
2026-05-12 15:43:02 +00:00
parent d04facd24f
commit 3891de685c
3 changed files with 147 additions and 6 deletions
@@ -212,6 +212,102 @@ mod tests {
);
}
/// AC4 regression: set [1,2,3] → clear [] → replace [4,5] — CRDT reflects
/// each write, and replace never appends.
#[test]
fn tool_update_story_depends_on_set_clear_replace() {
let tmp = tempfile::tempdir().unwrap();
crate::crdt_state::init_for_test();
setup_story_for_update(
tmp.path(),
"888_deps_scr",
"---\nname: Deps SCR\n---\n\nNo sections.\n",
);
let ctx = test_ctx(tmp.path());
// Set to [1, 2, 3].
let r = tool_update_story(
&json!({"story_id": "888_deps_scr", "front_matter": {"depends_on": [1, 2, 3]}}),
&ctx,
);
assert!(r.is_ok(), "set [1,2,3] should succeed: {r:?}");
let view = crate::crdt_state::read_item("888_deps_scr").expect("CRDT must have story");
assert_eq!(
view.depends_on,
Some(vec![1, 2, 3]),
"CRDT should hold [1,2,3] after set"
);
// Clear to [].
let r = tool_update_story(
&json!({"story_id": "888_deps_scr", "front_matter": {"depends_on": []}}),
&ctx,
);
assert!(r.is_ok(), "clear [] should succeed: {r:?}");
let view = crate::crdt_state::read_item("888_deps_scr").expect("CRDT must have story");
assert_eq!(
view.depends_on, None,
"CRDT should be None after clearing to []"
);
// Replace with [4, 5] — must not append to previous [1,2,3].
let r = tool_update_story(
&json!({"story_id": "888_deps_scr", "front_matter": {"depends_on": [4, 5]}}),
&ctx,
);
assert!(r.is_ok(), "replace [4,5] should succeed: {r:?}");
let view = crate::crdt_state::read_item("888_deps_scr").expect("CRDT must have story");
assert_eq!(
view.depends_on,
Some(vec![4, 5]),
"CRDT should hold exactly [4,5] after replace (not [1,2,3,4,5])"
);
}
/// Regression: clearing depends_on must survive a subsequent update to another
/// field. Before the fix, write_story_content would restore the old YAML
/// depends_on value into the CRDT register, overwriting the clear.
#[test]
fn tool_update_story_clear_depends_on_survives_subsequent_update() {
let tmp = tempfile::tempdir().unwrap();
crate::crdt_state::init_for_test();
// Story created WITH depends_on in YAML so write_story_content would
// previously restore it.
setup_story_for_update(
tmp.path(),
"888_deps_persist",
"---\nname: Deps Persist\ndepends_on: [100, 200]\n---\n\nNo sections.\n",
);
let ctx = test_ctx(tmp.path());
// Seed CRDT with the YAML deps (simulates the initial write path).
crate::crdt_state::set_depends_on("888_deps_persist", &[100, 200]);
// Clear deps via update_story.
let r = tool_update_story(
&json!({"story_id": "888_deps_persist", "front_matter": {"depends_on": []}}),
&ctx,
);
assert!(r.is_ok(), "clear should succeed: {r:?}");
let view = crate::crdt_state::read_item("888_deps_persist").expect("CRDT must have story");
assert_eq!(view.depends_on, None, "CRDT should be None after clear");
// Now update a different field — this triggers write_story_content with
// the stale YAML (which still has depends_on: [100, 200]).
let r = tool_update_story(
&json!({"story_id": "888_deps_persist", "name": "Deps Persist Updated"}),
&ctx,
);
assert!(r.is_ok(), "subsequent name update should succeed: {r:?}");
// The CRDT must still be None — the YAML value must not have been restored.
let view = crate::crdt_state::read_item("888_deps_persist").expect("CRDT must have story");
assert_eq!(
view.depends_on, None,
"CRDT depends_on must remain None after unrelated update (write_story_content must not restore YAML value)"
);
}
#[test]
fn tool_update_story_depends_on_routes_to_crdt_not_yaml() {
let tmp = tempfile::tempdir().unwrap();