docs: RELEASES.md entry for 8.3.2 (honest counters)
This commit is contained in:
parent
2e2ba9c9aa
commit
0932ecde37
1 changed files with 30 additions and 0 deletions
30
RELEASES.md
30
RELEASES.md
|
|
@ -10,6 +10,36 @@ Full auto-generated changelog: `CHANGELOG.md` · Releases: https://github.com/so
|
|||
|
||||
---
|
||||
|
||||
## v8.3.2 — 2026-07-14 (honest counters — the recount + removal-without-re-reading)
|
||||
|
||||
Completes 8.3.1's delete-hygiene story at the counter layer, from a production proof chain reported
|
||||
by a downstream deployment: persisted entity totals were permanently **inflated** — deletes whose
|
||||
count decrement was silently skipped — and because paginated `totalCount` serves
|
||||
`Math.max(persistedTotal, scanned)`, the inflated number always won and **no disk cleanup could ever
|
||||
lower it**.
|
||||
|
||||
- **A removal's count decrement no longer requires re-reading the record being removed.** The
|
||||
decrement was sourced from re-reading the entity's metadata inside the delete; if that read
|
||||
returned `null` (a replace race, or a ghost left by a pre-8.3.1 partial delete) the decrement was
|
||||
silently skipped while the paired add had counted — minting drift on every write→delete→re-create
|
||||
cycle. The caller's pre-delete read now rides through the whole delete path
|
||||
(`remove()`/`removeMany()` → the delete operation → `deleteNoun`/`deleteVerb` →
|
||||
`deleteNounMetadata`/`deleteVerbMetadata`, both sides symmetric): a null internal read falls back
|
||||
to the known prior record instead of skipping. The `StorageAdapter` signatures gain an optional
|
||||
`priorMetadata` parameter (additive; existing adapters unaffected).
|
||||
|
||||
- **`repairIndex()` is the sanctioned counter recount — unconditional, and it actually persists.**
|
||||
`rebuildTypeCounts()` previously rebuilt only the type-statistics arrays and computed the total
|
||||
*just to log it* — the persisted scalar (`counts.json`) survived every "rebuild" untouched, so an
|
||||
already-inflated brain could never be corrected. One canonical walk now rebuilds **every** counter
|
||||
rollup — scalar totals, per-type maps, and type statistics — and persists them, and `repairIndex()`
|
||||
runs it unconditionally (not only when orphan directories are found: counters can be inflated over
|
||||
perfectly clean shelves). Brains with delete history should run `brain.repairIndex()` once after
|
||||
upgrading; the correction survives reopen.
|
||||
|
||||
No API breaks (optional-parameter additions only). Regression tests cover the drift cycle, the
|
||||
null-read decrement fallback, and the persisted recount across reopen.
|
||||
|
||||
## v8.3.1 — 2026-07-14 (full-removal deletes + family-scoped migration gate)
|
||||
|
||||
Two production-reported fixes in the write/index spine, plus an operator repair path. No API changes;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue