Skip to content

diff: EOF-append to flat YAML list yields zero role:"changed" fragments (change signal lost) + whole-file fragmentation #103

Description

@nikolay-e

Observed

On a diff whose sole change is three lines appended at EOF of a large flat
YAML list file, diffctx . --diff HEAD~1 emits a context output that:

  1. Carries zero role: "changed" fragments. Not a single fragment in the
    output is labeled as the change — grep -c 'role:' output.yaml0. The
    "what changed" signal is entirely lost even though the diff is non-empty and
    valid.
  2. Does not surface the changed lines at all. The change adds new lines
    786–788 (@@ -785,3 +785,6 @@); the highest line range anywhere in the
    output is 785-785. The appended lines never appear as their own fragment.
  3. Explodes the whole ~790-line file into ~118 tiny definition fragments
    (lines: "4-6", "14-14", "17-17", … "785-785"), i.e. nearly the
    entire unchanged file is dumped as context.
  4. Also pulls in 2 unrelated files that the diff never touched.

Total: fragment_count: 120, ~5.9k tokens, for a 3-line append.

Expected

  • The appended lines (786–788) surfaced as a role: "changed" fragment — the
    change must always be represented and labeled.
  • Context scoped to the changed region + tight related context, not a
    whole-file fragmentation of a flat data-list file.

Repro

Public repo, deterministic:

git clone https://github.com/elastic/elasticsearch
cd elasticsearch
git checkout 4fc110bec          # "Mute ... MultiClusterSpecIT ... #153046"
diffctx . --diff HEAD~1 -f yaml > out.yaml
git diff HEAD~1 --stat          # ground truth: muted-tests.yml | 3 +++
grep -c 'role:' out.yaml        # → 0  (expected: >= 1 role: "changed")
grep -oE 'lines: "[0-9]+' out.yaml | grep -oE '[0-9]+' | sort -n | tail -1
                                # → 785 (the changed 786-788 never surface)
grep -cE '^  - path:' out.yaml  # → 120 fragments for a 3-line append

The changed file is muted-tests.yml, a flat top-level YAML list
(- class: … / method: … / issue: … entries) ~790 lines long.

Analysis

Two distinct symptoms, likely two root causes:

  • (A) Lost change signal — the EOF-append hunk maps to new lines 786–788,
    but no rendered fragment is in core_ids, so role: "changed" is never set.
    Either the changed-fragment for an at-EOF append in a non-code list file is
    never created, or it is dropped/absorbed during selection/merge. This is a
    correctness bug — worse than over-selection — since the actual answer to
    "what changed" is absent. Verified the field is emitted normally on other
    repos (e.g. numpy HEAD~1 yields 5 role: "changed" fragments), so this is
    a real omission, not a formatting artifact.
  • (B) Whole-file fragmentation — a flat YAML list is split into ~118
    per-entry definition fragments and most of the file is selected as context.
    This over-selection facet overlaps diffctx over-selection: PPR/edge relevance filter pulls in unrelated files (whole-tree over-dump + co-located k8s manifests) #65 (whole-tree over-dump); tracking (A)
    here because the missing role: "changed" is a separate, sharper failure.

Env

  • diffctx 1.10.2 (pipx-installed binary)
  • macOS; ran perl -e 'alarm 200; exec @ARGV' diffctx . --diff HEAD~1 (no
    hang — completed in well under the cap)

Related: #65 (over-selection). This issue is primarily about (A).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions