diff --git a/lib/merge.py b/lib/merge.py index af85d85..8a8139b 100644 --- a/lib/merge.py +++ b/lib/merge.py @@ -544,7 +544,8 @@ async def _merge_reweave_pr(branch: str) -> tuple[bool, str]: if not changed_files: return False, "no .md files changed" - # Create worktree from origin/main + # Pre-cleanup: remove stale worktree/branch from prior crash (SIGKILL, OOM, etc.) + await _git("worktree", "remove", "--force", worktree_path) await _git("branch", "-D", clean_branch) rc, out = await _git("worktree", "add", "-b", clean_branch, worktree_path, "origin/main") if rc != 0: @@ -582,29 +583,9 @@ async def _merge_reweave_pr(branch: str) -> tuple[bool, str]: # to cherry-pick. (Theseus: loud failure, not silent retry) return False, f"frontmatter parse failed on {fpath} — manual review needed" - # Superset assertion: branch's edge set must be a superset of main's. + # Superset assertion + merge in one pass. # Reweave only adds edges. If branch is missing an edge that main has, # the branch was based on stale main — union is safe (adds both). - for field in REWEAVE_EDGE_FIELDS: - main_list = main_fm.get(field, []) - branch_list = branch_fm.get(field, []) - if not isinstance(main_list, list): - main_list = [main_list] if main_list else [] - if not isinstance(branch_list, list): - branch_list = [branch_list] if branch_list else [] - - main_keys = {str(v).strip().lower() for v in main_list if v} - branch_keys = {str(v).strip().lower() for v in branch_list if v} - - missing = main_keys - branch_keys - if missing: - logger.warning( - "Reweave merge: %s field '%s' — branch missing edges from main: %s", - fpath, field, missing, - ) - skipped_non_superset.append(f"{fpath}:{field}") - - # Collect merged edge fields for string-level splicing merged_edges = {} for field in REWEAVE_EDGE_FIELDS: main_list = main_fm.get(field, []) @@ -613,6 +594,19 @@ async def _merge_reweave_pr(branch: str) -> tuple[bool, str]: main_list = [main_list] if main_list else [] if not isinstance(branch_list, list): branch_list = [branch_list] if branch_list else [] + + # Superset check + main_keys = {str(v).strip().lower() for v in main_list if v} + branch_keys = {str(v).strip().lower() for v in branch_list if v} + missing = main_keys - branch_keys + if missing: + logger.warning( + "Reweave merge: %s field '%s' — branch missing edges from main: %s", + fpath, field, missing, + ) + skipped_non_superset.append(f"{fpath}:{field}") + + # Collect merged edges for string-level splicing if main_list or branch_list: merged_edges[field] = _union_edge_lists(main_list, branch_list)