ValueSignature
The canonical byte string a scalar is identified by.
This is the single answer to "when are two values the same value", and it is shared rather than reimplemented for a reason that is worth stating plainly: the catalog counts distinct values with it to decide whether a path is worth an inverted index, and rabosh-index keys its term dictionary with it to build one. An estimator that disagreed with the index it recommended would not crash — it would recommend against indexing a column whose real cardinality is small, or build an index whose terms a query could never spell. That is the same argument that put the container read algorithms in one place in rabosh-index, and it applies harder here, because the failure is silent on both sides.
Canonical across widths. Every numeric width shares NUMERIC and goes through stripTrailingZeros().toPlainString(), so 1 written as an int8, 1.0 written as a double and 1.00 written as a decimal are one value. Scale is a property of how a value was written, not of what it is, and a query asking for 1 means all three.
This is a lookup order, not a value order. Signatures sort by tag and then by bytes, so NUMERIC || "10" sorts before NUMERIC || "9". That is exactly what a term dictionary needs — a total order to binary search — and exactly what a range predicate must not be answered with. An inverted index answers equality, IN and existence; ordered skipping is a shredded column's job.
The tags are permanent. Every HyperLogLog register ever written is a function of them, and so is every term in every posting file. Add, never renumber.