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)
|
## 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;
|
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