hunkpick 0.5.1

Non-interactive git add -p alternative — pick and split unified-diff hunks by index, range, or content id
Documentation
# TODO

## Contents

- [Fixed]#fixed
- [Per-line cutting: remaining edges]#per-line-cutting-remaining-edges

## Fixed

### Legacy `@lo-hi` leading slice dropped trailing context (removed in 0.5.0)

Fixed by **removing** the `INDEX@lo-hi` added-line range selector entirely
(0.5.0). Its contiguous-slice implementation dropped the trailing context on a
leading/interior slice of a mid-file addition block, so `git apply` rejected the
piece (`patch does not apply`). A contiguous slice cannot both omit the trailing
additions and keep the context after them, so there was no in-place fix; the
per-line `@L<set>` cutter already keeps both leading and trailing context and
strictly subsumes `@lo-hi` (it can express any added-line range plus deletions,
interior slices, and replacements). See ADR 0009. A selector still using the
`@lo-hi` form is now a usage error (exit 2) that points the caller at `@L`.

## Per-line cutting: remaining edges

### Done

The generalized per-line selector `INDEX@L<set>` (`slice_changed_lines`) is
implemented. It selects an arbitrary subset of a sub-hunk's changed (`+`/`-`)
lines, numbered `1..N` in body order (deletions and additions share one
numbering, reported as `changed_lines` in `list --json`). Each unselected
deletion is kept as a context line — anchoring the piece so it applies without
`--unidiff-zero` — and each unselected addition is omitted, so every subset is
realisable as one applicable hunk with no boundary restriction. This subsumes
what a deletion-side `@d` cut would have offered: a deletion surrounded by
additions (`+x -y +z`) can be isolated, and a replacement's removals can be
separated from its insertions across `diff → stage → re-diff` rounds. Verified
end to end via `git apply`.

The primary consumer is a coding agent, which reads `changed_lines` from
`list --json` and constructs `@L` selectors programmatically.

The earlier "classify overlapping-selection errors as usage errors" item is also
resolved: `select` rejects overlapping selections of one sub-hunk (a whole plus a
range, or two overlapping ranges, or `@L` combined with another selection of the
same sub-hunk) as a usage error (exit 2) before the result reaches
`validate_internal`.

### Remaining

- **Multiple `@L` pieces of the same sub-hunk in one invocation.** Currently a
  usage error: separate pieces would carry mutually inconsistent new-side line
  numbers. Combining them in one emitted diff would need each piece's new-side
  anchor recomputed against the intermediate file the earlier pieces produce. The
  supported path today is the `diff → stage → re-diff` loop (one piece per round).
  Lift this only if a single-invocation multi-piece cut proves worth the anchor
  bookkeeping.

- **`@L` across several sub-hunks in one invocation when deletions become
  context.** Selecting additions (which turns that sub-hunk's deletions into
  context) grows its new-side span; combined with another sub-hunk in the same
  emit, the new-side ranges can overlap and `validate_internal` rejects it
  (`OverlappingHunks`, exit 70) rather than as a clean usage error. Safe (no bad
  patch emitted), but the diagnostic could be clearer, or the new-side anchors
  recomputed so the combination is valid. The re-diff loop avoids it.

- **Genuinely zero-context edges.** The convert-unselected-deletions-to-context
  rule removes most zero-context cases, but a context-less run (a whole-file
  replacement, a file creation/deletion) can still yield a piece git needs
  `--unidiff-zero` for. If such cases matter, add an explicit `--unidiff-zero`
  opt-in (git does not content-verify those hunks, so keep it off by default).

### Fundamental limits (out of scope)

- a single changed line is the atom — half a line cannot be staged;
- a unified diff does not record which deletion pairs with which addition, so a
  "semantically correct" split of a replacement is inherently ambiguous;
- some intermediate states are unbuildable — a property of any line-wise staging.