huskies: merge 987

This commit is contained in:
dave
2026-05-13 16:30:31 +00:00
parent 430079ecbc
commit c3c9db3d8b
13 changed files with 662 additions and 311 deletions
@@ -64,9 +64,9 @@ async fn squash_merge_md_only_changes_fails() {
// The squash merge will commit the .huskies/ file, but should fail because
// there are no code changes outside .huskies/.
assert!(
!result.success,
"merge with only .huskies/ changes must fail: {}",
result.output
!matches!(result, super::MergeResult::Success { .. }),
"merge with only .huskies/ changes must fail: {:?}",
result
);
// Cleanup should still happen.
@@ -146,12 +146,10 @@ async fn squash_merge_additive_conflict_both_additions_preserved() {
let result = run_squash_merge(repo, "feature/story-238_additive", "238_additive").unwrap();
// Deterministic merge does NOT auto-resolve conflicts — AC3 requires failure.
assert!(result.had_conflicts, "additive conflict should be detected");
assert!(
!result.conflicts_resolved,
"deterministic merge must NOT auto-resolve conflicts"
matches!(result, super::MergeResult::Conflict { .. }),
"additive conflict should produce Conflict variant; got: {result:?}"
);
assert!(!result.success, "conflict must cause merge failure");
// Master must not have been modified (merge aborted).
let content = fs::read_to_string(repo.join("module.rs")).unwrap();
@@ -254,18 +252,13 @@ async fn squash_merge_conflict_resolved_but_gates_fail_reported_as_failure() {
// Squash-merge: conflict detected → aborted immediately (no gate run).
let result = run_squash_merge(repo, "feature/story-238_gates_fail", "238_gates_fail").unwrap();
assert!(result.had_conflicts, "conflict must be detected");
assert!(
!result.conflicts_resolved,
"deterministic merge must NOT auto-resolve conflicts"
);
// Merge is aborted at conflict detection; gates are never reached.
assert!(
!result.success,
"conflicting merge must be reported as failed"
matches!(result, super::MergeResult::Conflict { .. }),
"conflicting merge must produce Conflict variant; got: {result:?}"
);
assert!(
!result.output.is_empty(),
!result.output().is_empty(),
"output must contain conflict details"
);
@@ -329,9 +322,9 @@ async fn squash_merge_cleans_up_stale_workspace() {
let result = run_squash_merge(repo, "feature/story-stale_test", "stale_test").unwrap();
assert!(
result.success,
"merge should succeed after cleaning up stale workspace: {}",
result.output
matches!(result, super::MergeResult::Success { .. }),
"merge should succeed after cleaning up stale workspace: {:?}",
result
);
assert!(
!stale_ws.exists(),
@@ -398,15 +391,15 @@ fn squash_merge_runs_component_setup_from_project_toml() {
// The output must mention component setup, proving the new code path ran.
assert!(
result.output.contains("component setup"),
result.output().contains("component setup"),
"merge output must mention component setup when project.toml has components, got:\n{}",
result.output
result.output()
);
// The sentinel command must appear in the output.
assert!(
result.output.contains("sentinel"),
result.output().contains("sentinel"),
"merge output must name the component, got:\n{}",
result.output
result.output()
);
}
@@ -461,13 +454,13 @@ fn squash_merge_succeeds_without_components_in_project_toml() {
// No pnpm or frontend references should appear in the output.
assert!(
!result.output.contains("pnpm"),
!result.output().contains("pnpm"),
"output must not mention pnpm, got:\n{}",
result.output
result.output()
);
assert!(
!result.output.contains("frontend/"),
!result.output().contains("frontend/"),
"output must not mention frontend/, got:\n{}",
result.output
result.output()
);
}