CODE-050: weave JOIN of identical-blob reps doubles the tip text

Now
OPEN
Sev
HIGH
Rep
///bee
Ask
gritzko
Rev
///bee#8cb69a0
See
BEE-005

Input

Context

index/weave.js:276:KB (with index/dag.js:103:~c repsOf) joins the reps a merge stands on. When two reps carry the SAME blob — the same fix made on both branches, a cherry-pick, a re-applied revert — the contentless JOIN keeps both insertions live: fixture cross yields a 118-byte view for a 113-byte blob, line 6 reads line 06 SAME SAME;, and bee diff <base> <PQ> prints +line 06 SAME SAME;, content that exists in no commit. Every diff and provenance view over such a merge is wrong. Found in the 2026-09-18 review.

Goals

Repro: two branches applying one identical edit, merged. Dedupe reps by blob hashlet before the JOIN, and verify the produced view against the tip's own blob, falling back to the fold-the-tip-bytes branch at index/weave.js:282:KB.

WIP

Design decisions

  1. The JOIN is not deduped but REPLACED wherever a rep already IS the tip: weaveDiff matches each rep's REV-BLOB against the tip's own blob hashlet and stands the view on that rep. That verifies the view against the tip's blob in hashlet space — a folded layer produces its own blob back — so no produce and no extra ODB read is paid per path.
  2. A tip that HAS a blob no rep carries skips the join and folds its own bytes as its layer (the weave.js:282 branch), now over the reps' closure rather than the seed, so shared tokens keep their blame.
  3. A blobless side (a delete) keeps the old JOIN: there is then no blob to match a rep against. Such a tip standing on two reps still loses its empty fold to the join — pre-existing, left alone.
  4. The same JOIN doubled a -s ours merge too (the dropped side's line rendered as an insert); the blob match fixes that leg as well, and the repro pins the identical-edit one.

TODOs

Outcome