huskies: merge 945

This commit is contained in:
dave
2026-05-13 06:05:01 +00:00
parent 3a8894ea8f
commit 9ce5a8df0c
53 changed files with 497 additions and 654 deletions
@@ -21,15 +21,16 @@ pub(super) fn read_story_front_matter_agent(
.filter(|s| !s.is_empty())
}
/// Return `true` if the story has its `review_hold` CRDT register set.
/// Return `true` if the story is in `Stage::ReviewHold`.
///
/// Sub-story 932: `review_hold` is now a dedicated CRDT register on
/// `PipelineItemCrdt`, distinct from `Stage::Frozen`. The auto-assigner uses
/// this to keep human-QA items / spikes parked after gates pass until a
/// reviewer explicitly clears the hold (e.g. via `tool_approve_qa`).
/// Story 945: `Stage::ReviewHold { resume_to, reason }` is the single source
/// of truth — the legacy `review_hold: bool` CRDT register has been deleted.
/// The auto-assigner uses this to keep human-QA items / spikes parked after
/// gates pass until a reviewer explicitly clears the hold (e.g. via
/// `tool_approve_qa`).
pub(super) fn has_review_hold(_project_root: &Path, _stage_dir: &str, story_id: &str) -> bool {
crate::crdt_state::read_item(story_id)
.map(|w| w.review_hold())
.map(|w| w.stage().is_review_hold())
.unwrap_or(false)
}
@@ -80,18 +81,19 @@ pub(super) fn has_content_conflict_failure(
.unwrap_or(false)
}
/// Return `true` if the CRDT `mergemaster_attempted` register is set for this story.
/// Return `true` if the story is in `Stage::MergeFailureFinal`.
///
/// Story 945: `Stage::MergeFailureFinal` is the single source of truth —
/// the legacy `mergemaster_attempted: bool` CRDT register has been deleted.
/// Used to prevent the auto-assigner from repeatedly spawning mergemaster for
/// the same story after a failed mergemaster session. The CRDT register is the
/// only source consulted — the legacy YAML field is no longer checked.
/// the same story after a failed mergemaster session.
pub(super) fn has_mergemaster_attempted(
_project_root: &Path,
_stage_dir: &str,
story_id: &str,
) -> bool {
crate::crdt_state::read_item(story_id)
.map(|view| view.mergemaster_attempted())
.map(|view| view.stage().is_mergemaster_attempted())
.unwrap_or(false)
}
@@ -116,13 +118,15 @@ pub(super) fn check_archived_dependencies(
crate::crdt_state::check_archived_deps_crdt(story_id)
}
/// Return `true` if the story's `frozen` CRDT flag is set (story 934, stage 4).
/// Return `true` if the story is in `Stage::Frozen`.
///
/// `frozen` is orthogonal to [`Stage`]: a frozen story keeps its current stage
/// register but is skipped by the auto-assigner.
/// Story 945: `Stage::Frozen { resume_to }` is the single source of truth —
/// the legacy `frozen: bool` CRDT register has been deleted. Frozen stories
/// are skipped by the auto-assigner until `Unfreeze` returns them to
/// `resume_to`.
pub(super) fn is_story_frozen(_project_root: &Path, _stage_dir: &str, story_id: &str) -> bool {
crate::crdt_state::read_item(story_id)
.map(|view| view.frozen())
.map(|view| view.stage().is_frozen())
.unwrap_or(false)
}
@@ -139,9 +143,11 @@ mod tests {
crate::crdt_state::init_for_test();
crate::db::ensure_content_store();
let tmp = tempfile::tempdir().unwrap();
// Story 945: review_hold is now a typed Stage variant, seeded via
// the wire-form stage register directly.
crate::crdt_state::write_item_str(
"890_spike_held",
"3_qa",
"review_hold",
Some("Held Spike"),
None,
None,
@@ -149,9 +155,7 @@ mod tests {
None,
None,
None,
None,
);
crate::crdt_state::set_review_hold("890_spike_held", true);
assert!(has_review_hold(tmp.path(), "3_qa", "890_spike_held"));
}
@@ -170,7 +174,6 @@ mod tests {
None,
None,
None,
None,
);
assert!(!has_review_hold(tmp.path(), "3_qa", "890_spike_active_qa"));
}
@@ -258,7 +261,6 @@ mod tests {
Some("Blocked"),
None,
None,
None,
Some("[999]"),
None,
None,
@@ -285,7 +287,6 @@ mod tests {
None,
None,
None,
None,
);
crate::crdt_state::write_item_str(
"10_story_ok",
@@ -293,7 +294,6 @@ mod tests {
Some("Ok"),
None,
None,
None,
Some("[999]"),
None,
None,
@@ -320,7 +320,6 @@ mod tests {
None,
None,
None,
None,
);
assert!(!has_unmet_dependencies(
tmp.path(),
@@ -346,7 +345,6 @@ mod tests {
None,
None,
None,
None,
);
crate::crdt_state::write_item_str(
"503_story_dependent",
@@ -354,7 +352,6 @@ mod tests {
Some("Dependent"),
None,
None,
None,
Some("[500]"),
None,
None,
@@ -380,7 +377,6 @@ mod tests {
None,
None,
None,
None,
);
crate::crdt_state::write_item_str(
"503_story_waiting",
@@ -388,7 +384,6 @@ mod tests {
Some("Waiting"),
None,
None,
None,
Some("[490]"),
None,
None,