2026-09-05 — One chunk, from two that disagreed

This came out of a cross-repository review of four applications, not from anything the kernel needed. The review looked for code worth sharing and found almost none: nearly every candidate turned out to be domain logic that belongs to whichever service owns the data. One function survived the test, and this session moves it here.

Why chunk and nothing else

Two applications each carried a private utils/chunk.ts. Both split an array into runs so a database batch stays under the platform's statement ceiling; both are pure; neither knows what its elements are. That last part is the test the other candidates failed — a company normaliser and a content-hash both looked shared and both encode a decision about a specific market's data.

The rule this package already states is the one that was applied: a helper belongs here when it names no vendor, no runtime and no HTTP framework. chunk names none of the three.

The two implementations disagreed, and only at the boundary

They agreed on everything except a size below one, which each had guarded against because a step of 0 does not terminate:

  • one clamped the step to 1, producing many single-element runs
  • the other returned the whole input as a single run

The second is the more tempting reading — "no meaningful limit, so no split" — and it is the wrong one. The only promise the function makes is that no run is longer than size. Returning everything in one run breaks that promise in the direction that hurts: the caller asked for a bounded batch because something downstream has a ceiling, and it now gets an unbounded one, which fails at the far end where the ceiling actually lives, in whatever terms that system uses.

List.chunk clamps. A misconfigured 0 becomes many small runs — slow, obvious, recoverable. So does anything else that is not a finite number of one or more, and NaN is the case that will really happen, since a batch size read from an environment variable arrives as Number(undefined) when the variable is missing.

A fractional size is truncated rather than passed through, because slice with a step of 2.5 cuts at drifting boundaries and produces runs of alternating length.

List, not a bare function

Both consumers exported a bare chunk. This package's utilities are classes of static methods — Text, Time, Signature — so it arrives as List.chunk, and the two call sites change shape when they adopt it. That is a rename in a consumer, not a behaviour change.

What this does not do

Nothing in the kernel calls List.chunk, and the module note in utils/ claimed everything there existed because the kernel needed it. That was already untrue of Signature, which no code in src/ calls either. The note now says what is actually true: these are published because they are pure and vendor-neutral, and a helper already written twice in two consumers is one those consumers should share rather than keep diverging copies of.

The consumers still carry their own copies. They cannot import this until 1.3.0 is published, and removing a working local helper before its replacement exists on the registry would break both builds for the sake of tidiness.

results matching ""

    No results matching ""