Node.equals compared only the id. It was written that way to dodge a
real trap — a data class compares ByteArray by identity, so the
generated equals calls two identical rows different — and dodging it broke
a whole feature.
Promoting a link keeps the node's id and changes its storage. So the new
row compared EQUAL to the one it replaced, the state object holding it
compared equal too, StateFlow conflated the update away, and Compose
never saw it. On screen the file vanished from Linked and did not appear
in the vault until the app was restarted. That reads as losing somebody's
file.
Every field is compared now, with contentEquals for the four byte
arrays — the identity trap handled rather than avoided.
This suite could not have caught it, and the new tests say why.
Everything here reads the vault, and the vault was right the whole time:
the index on disk had both rows, and a fresh load rendered both. The
failure was in what the vault handed a state holder that conflates on
equality. So the tests assert that property directly — a promoted row must
not equal its old self, an unchanged row read twice must, and every
mutable field must be visible in equality.
Found by watching it on an emulator. Confirmed by restoring the old
equals and watching both go red, then re-verified on device: the promoted
row now appears immediately with no restart, and its size corrects from
the provider's reported 4 kB to the real 14 kB plaintext length — which is
itself proof the row genuinely updated.
Also verified on device while here: a persistable read grant survives a
reboot, a full cold boot and an app update (persistable=0x1 persisted=0x1), promoting drops the bookmark from the index, and the
person's own file is left untouched where they put it.
`Node.equals` compared only the id. It was written that way to dodge a
real trap — a data class compares `ByteArray` by identity, so the
generated equals calls two identical rows different — and dodging it broke
a whole feature.
Promoting a link keeps the node's id and changes its `storage`. So the new
row compared EQUAL to the one it replaced, the state object holding it
compared equal too, `StateFlow` conflated the update away, and Compose
never saw it. On screen the file vanished from Linked and did not appear
in the vault until the app was restarted. That reads as losing somebody's
file.
Every field is compared now, with `contentEquals` for the four byte
arrays — the identity trap handled rather than avoided.
**This suite could not have caught it, and the new tests say why.**
Everything here reads the vault, and the vault was right the whole time:
the index on disk had both rows, and a fresh load rendered both. The
failure was in what the vault handed a state holder that conflates on
equality. So the tests assert that property directly — a promoted row must
not equal its old self, an unchanged row read twice must, and every
mutable field must be visible in equality.
Found by watching it on an emulator. Confirmed by restoring the old
equals and watching both go red, then re-verified on device: the promoted
row now appears immediately with no restart, and its size corrects from
the provider's reported 4 kB to the real 14 kB plaintext length — which is
itself proof the row genuinely updated.
Also verified on device while here: a persistable read grant survives a
reboot, a full cold boot and an app update (`persistable=0x1
persisted=0x1`), promoting drops the bookmark from the index, and the
person's own file is left untouched where they put it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Node.equalscompared only the id. It was written that way to dodge areal trap — a data class compares
ByteArrayby identity, so thegenerated equals calls two identical rows different — and dodging it broke
a whole feature.
Promoting a link keeps the node's id and changes its
storage. So the newrow compared EQUAL to the one it replaced, the state object holding it
compared equal too,
StateFlowconflated the update away, and Composenever saw it. On screen the file vanished from Linked and did not appear
in the vault until the app was restarted. That reads as losing somebody's
file.
Every field is compared now, with
contentEqualsfor the four bytearrays — the identity trap handled rather than avoided.
This suite could not have caught it, and the new tests say why.
Everything here reads the vault, and the vault was right the whole time:
the index on disk had both rows, and a fresh load rendered both. The
failure was in what the vault handed a state holder that conflates on
equality. So the tests assert that property directly — a promoted row must
not equal its old self, an unchanged row read twice must, and every
mutable field must be visible in equality.
Found by watching it on an emulator. Confirmed by restoring the old
equals and watching both go red, then re-verified on device: the promoted
row now appears immediately with no restart, and its size corrects from
the provider's reported 4 kB to the real 14 kB plaintext length — which is
itself proof the row genuinely updated.
Also verified on device while here: a persistable read grant survives a
reboot, a full cold boot and an app update (
persistable=0x1 persisted=0x1), promoting drops the bookmark from the index, and theperson's own file is left untouched where they put it.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
assigned to @paulhitt
mentioned in commit
c47533929echanged the description