Expand description
Grouper<R> — kind-agnostic timeline grouping. Given a stream of
KernelEvents and a ParentResolver, emits a Vec<TimelineBlock> where
reply chains collapse into Twitter-style modules.
§Algorithm sketch
On each event insert:
- Ignore if already known.
- Resolve parent via the per-NIP
ParentResolver. - If parent is an
Eventalready in store AND occupies the leaf of an existing block, splice the new event onto that block (promoting Standalone → Module if needed) up topolicy.max_module_size. - Otherwise walk ancestors up to
policy.max_ancestor_hops, picking upEventids that are in the store and not yetseen.Address/Externalparents terminate the walk and become the module’srootpointer. - Wrap the chain in a
TimelineBlock;blocksis kept sorted by newest event timestamp, regardless of relay arrival order. - If the parent is unknown locally, buffer the child in
orphanskeyed by the missing parent id. Parent arrival replays children.
Adjacent-block collapse runs after every mutation: two Module blocks
sharing the same root pointer merge if policy.collapse_adjacent_same_ root is set and the merged length would fit max_module_size.
§Why no dynamic dependency injection
A view’s dependencies is a pure function of its spec. There is no API
to re-publish dependencies with pending_ancestor_ids learned at
runtime. ThreadView lives with the same constraint and relies on the
surrounding planner subscription (broad ("e", target) tag-ref) to
surface ancestors. Wrappers around this grouper inherit that contract;
pending_ancestor_ids is kept as internal diagnostic state.
§Module layout
The algorithm is split by phase across submodules; this file is the spine (state + construction + read accessors) that the phases share:
- [
lifecycle] — insert/remove/replace entry points, orphan replay, supersession bookkeeping. - [
placement] — splicing an event onto an existing block or walking ancestors to build a fresh chain. - [
ordering] — block recency ordering and delta-index resolution. - [
collapse] — adjacent same-root module merging.
Structs§
- Grouper
- Owning state for the algorithm. One instance per open view.
Enums§
- Group
Delta - Delta surface for the grouper. Wrappers map this into their own
view-module
Deltatype (typically a 1:1 forward).