bench/results/deterministic-20260727T083941Z.md §2:
| operation |
survived / total |
| interactive-rebase |
20 / 20 |
| rebase-onto |
20 / 20 |
| cherry-pick |
20 / 20 |
| filter-branch |
20 / 20 |
| squash-merge |
0 / 20 |
Reproduced independently, outside the harness:
3 records on a feature branch
git merge --squash feat && git commit -m 'squash: bring in feat'
→ 0 records in HEAD, 0 in the entire history
Why this one matters more than the others
"Squash and merge" is a button in the GitHub UI and the default merge strategy at many organisations. Rebase and cherry-pick preserve records because they preserve messages one-to-one; squash collapses N messages into one that the merger writes, and the trailers go with the messages that no longer exist.
The notes mirror does not save it either — notes attach to a SHA, and squash produces a new one.
So the product's central claim — decision history is bound to git and survives normal workflows — is false for a workflow a large fraction of users have configured as their default. That is not a bug in a corner; it is a limitation that belongs on the README before anyone adopts the tool on that basis.
Directions, none obviously right
- Detect and refuse. A pre-merge hook that fails when squashing commits carrying records. Honest, and annoying enough that people will disable it.
- Fold the trailers. Concatenate records from the squashed commits into the squash message, with
Provenance: inherited <sha> — the vocabulary already has the word for this. Produces one commit carrying many records, which validate may not accept as-is.
- Document it and stop claiming survival. Cheapest, and possibly correct: a tool that binds records to commits cannot follow an operation that deletes the commits.
(2) is the only one that preserves the claim. Whether it should is a design decision, not an implementation detail — the resulting record set says one commit made decisions that were actually made across several, and that may be a worse lie than losing them.
Decide the direction before writing code. Whatever is chosen, §2's number goes in the README either way.
bench/results/deterministic-20260727T083941Z.md§2:Reproduced independently, outside the harness:
Why this one matters more than the others
"Squash and merge" is a button in the GitHub UI and the default merge strategy at many organisations. Rebase and cherry-pick preserve records because they preserve messages one-to-one; squash collapses N messages into one that the merger writes, and the trailers go with the messages that no longer exist.
The notes mirror does not save it either — notes attach to a SHA, and squash produces a new one.
So the product's central claim — decision history is bound to git and survives normal workflows — is false for a workflow a large fraction of users have configured as their default. That is not a bug in a corner; it is a limitation that belongs on the README before anyone adopts the tool on that basis.
Directions, none obviously right
Provenance: inherited <sha>— the vocabulary already has the word for this. Produces one commit carrying many records, whichvalidatemay not accept as-is.(2) is the only one that preserves the claim. Whether it should is a design decision, not an implementation detail — the resulting record set says one commit made decisions that were actually made across several, and that may be a worse lie than losing them.
Decide the direction before writing code. Whatever is chosen, §2's number goes in the README either way.