feat(cli): add adjudicate --apply-same guarded batch merge (#137)#175
Merged
Conversation
Gives `adjudicate` a batch path to action: `--apply-same` fuses every eligible SAME 2-member duplicate group in one pass, closing the advisory -> action loop that previously required one manual `merge` per pair. - Eligibility is exactly `verdict == SAME` and a 2-member group; N>2 groups and DIFFERENT/UNCERTAIN verdicts are skipped (mirroring `--apply`). - The batch prints a full aggregate preview of every merge it will perform, then requires a typed-count confirmation: `--confirm-count <N>` must equal the previewed count exactly (scriptable, mirrors `purge --confirm-phrase`); on a TTY the count is prompted; a non-TTY run without the flag refuses with zero writes. Any empty/wrong/non-numeric value aborts byte-identically. - An empty report (no eligible groups) short-circuits to "nothing to apply" (exit 0), so a scripted run never fails spuriously. - Merges execute sequentially, each landing in the `merged_from` ledger so `unmerge` round-trips. A mid-batch failure stops but keeps prior commits and reports how many were applied before the failure. Apply-time re-resolution skips a member already absorbed earlier in the batch. - Refactor: the per-pair prepare/preview/commit body is extracted into `_prepare_one_merge`/`_format_merge_preview_line`/`_commit_one_merge`, shared by both the interactive `--apply` walk and the batch, so the destructive write ordering is defined once. `--apply-same` is mutually exclusive with `--apply` and `--json`. Reviewed via the full 4R set (risk/resilience/reliability/readability); risk review found no data-loss or unauthorized-merge path. Exceeds the 800-line review budget (size:exception) — 62% of the diff is the 20-scenario test matrix for this destructive path. Closes #137.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Final slice of #137 — the guarded batch.
adjudicate --apply-samefuses every eligible SAME 2-member duplicate group in one pass, closing the advisory→action loop that previously required one manualopenkos mergeper pair. Closes #137 (parts--json#161 and interactive--apply#165 already shipped).The deferred guardrail (issue #138) was resolved by #147 — but that fix was prompt-only, so the only machine-checkable gate remains
verdict == SAME+ 2-member size. The batch's safety net is therefore an explicit aggregate preview + typed-count confirmation, not a confidence threshold.Behavior
verdict == SAMEand a 2-member group; N>2 groups and DIFFERENT/UNCERTAIN are skipped (mirrors--apply).--confirm-count <N>to equal the previewed count exactly (scriptable, mirrors the shippedpurge --confirm-phrase); a TTY prompts for the count; a non-TTY run without the flag refuses with zero writes. Empty/wrong/non-numeric aborts byte-identically.merged_fromledger (unmergeround-trips). A mid-batch failure stops, keeps prior commits, and reports how many were applied. Apply-time re-resolution skips a member already absorbed earlier in the batch._prepare_one_merge/_format_merge_preview_line/_commit_one_merge, shared by both--applyand the batch so the destructive write ordering lives in one place.--applyand--json.Verification
uv run pytest: 2130 passed, exit 0 · ruff clean · mypy clean--applysuite green.Strict TDD throughout (RED confirmed before each GREEN, including the three review fixes).
Review budget
Exceeds the 800-line budget →
size:exception. ~922 changed lines of code, 62% of it the 20-scenario test matrix for this destructive path; production surface is ~400 lines. Splitting off the Phase 1 refactor would not bring the feature PR under budget (the test matrix is inherent).Closes #137.