v0.3.2
Version aligned with the alpenglow ag-v0.3.2 tag this release was
validated against.
Added
- Stage 1 canonical-skip classifier (
aggregator::classify_skips):
walks parent pointers from observedFinalizedslots, assigns
everyvoted_skipslot toDirectFinalize/Ancestry/
Indeterminate. The headline operator-facing metric
canonical-skip %is derived from this classification. EventKind::TriggeringParentReadyparser variant for the
event_handler::add_missing_parent_readylog line; counter on
OverallStats(intentionally unsurfaced, reserved for future
per-window analysis).- Standstill range tracking:
OverallStats.standstill_rangesbuilt
fromStandstillExtending/StandstillEndedevents, including
EOS-orphan close. Newtimeout_crashed_leaders_outside_standstill
counter computed inanalyzefilters TCLs that fired inside a
standstill window (where the per-slot timeout is stretched and the
leader did not actually misbehave). SlotViewRow.consensus_invertedflag rendered as↶in the
Slots-tabconsensuscolumn for rows where the cluster's
Finalizedcert arrived before the local node'sBlockevent
(cluster outran local replay). Plain-is now reserved for
genuinely missing data.theme::TRUE_FB_ELEVATED_PCTthreshold constant.ProduceWindowcorruption guards (oversized span> 16,
inverted rangeend < start), counted in
OverallStats.malformed_produce_window.MirrorSparklinewidget on the time-series tab for the paired
vote-skip / canonical-skip mirror chart (one rises from the
bottom, the other hangs from the top, shared x-axis).
Changed
- Slot status labels:
SKIPrenamed toVSKIP(we Voted skip,
no canonical evidence).CSKIPunchanged. TheV/Cprefix
convention makes both labels self-describing — both refer to
our vote; the prefix indicates whether canonical evidence
exists. - Slots-tab filter hotkeys rotated:
[v]= VSKIP only,[c]= CSKIP only,
[s]= SLOW,[x]= clear all filters,
[b]freed.SlotFilters::vskip_onlyreplacesskipped_only
with narrowed semantic; the skip-family pair (vskip_only,
canonical_skip_only) now uses OR semantics — pressing both
shows the union. - Slots-tab
consensuscolumn now distinguishes three states:
positive value in ms (normal),↶(cluster outran local
replay),-(missing data). - Slots-tab
Latency bandsreference panel adds aconsensus
threshold row (≤ 300 ms · 300–600 ms · > 600 ms). - Slots-tab KPI strip: leader-slot share metric moved from the
buried right-panel footer ontoslot statsline 2 next to the
lifecycle percentiles.p95value is now health-coloured at the
KPI site, replacing the previous footer row. - Slots-tab legend: static column-value reference (status, vote,
consensus glyph) moved to the bottom of the panel below the
[x] clear all filtersseparator. The filter section above is
now exclusively interactive toggles. - Slots-panel title shortened: drops the redundant total in
slots (N total | cursor M / N)→slots (cursor M / N). The
filtered variant retainsM of N. vote & cert totalswidget on Overview rewritten as three
horizontal columns (votes/certs/finalized) instead
of stacked text. Headings styled intitle_style.- Overview headline-health
fast-finalizerow dropped the
fast NN.NN% / slow NN.NN%breakdown (the numbers now live
in thevote & cert totalsfinalizedcolumn). Verdict mark
and text retained. - Alerts-tab
detailblock + list block + Overviewalerts
widget gainPadding::new(...)for breathing room from the
block border. - Alerts-tab
detailwidget adds explicit blank lines between
thelastandspanrows and between thefirst sample
label and the sample body. - Leader-timeouts trend chart uses a packing-search algorithm
to pick(bar_width, bar_count)that fills the panel width.
bar_widthcapped at 6 columns so very wide terminals do not
collapse the chart to a handful of thick bars. - Header
crashed leadersmetric on Overview adopts the
standstill-aware count when standstill ranges exist (raw count
appears on a continuation line); when no standstill ranges
exist, the single-line display is unchanged. - Canonical-skip lower-bound marker (
≥) now applied on the
Slots-tab KPI strip whenindeterminate_skips > 0, matching
the header, overview, windows, and--textrunner surfaces. stake sharelabel removed. Renamedleader-slot share
(window-relative, not on-chain stake — the previous label
overstated what the tool measures).Severity::from_usthresholds (1.5 s / 3.0 s) documented as
provisional pending empirical calibration across multi-day
log archives.- True-FB cutoff
0.5%consolidated into
theme::TRUE_FB_ELEVATED_PCTand consumed at both render
sites (was a duplicated literal). - True-FB percentage formatted as
{:.2}%(was{:.3}%— no
false precision on an integer-count ratio).
Fixed
- Slots-tab canonical-skip percentage was missing the
≥
lower-bound marker even when indeterminate skips existed.
Same number now reads consistently across all surfaces. - Seven previously-undocumented
OverallStatsfields received
reserved-for-future docstrings explicitly marking them as
intentionally unsurfaced (matching the existing
parent_ready_recoveriesprecedent):malformed_produce_window,
standstill_extending_events,standstill_ended_events,
no_epoch_info_for_slot,updating_epoch_metadata,
evicting_epoch_metadata,invalid_cluster_slots_update.
Internal
- Test count: 187 → 201 across the workspace.
aggregator/tests.rs(989 LOC) split into 6 sub-modules under
aggregator/tests/(ingest,standstill,classify_skips,
log_patterns,produce_window,analyze_alerts).tui/app.rsinlinemod tests(309 LOC) extracted to
tui/app_tests.rsvia#[path]declaration; production
module drops to 753 LOC, under the 800 strong-warn threshold.OverallStatsunique-slot count docstrings clarified —
finalized_slot_count + skipped_slot_count + pending_slot_count
is overlap, not partition (a canonical-skip slot is counted in
bothfinalized_slot_countandskipped_slot_count).- rustfmt + strict clippy fixes for the workspace:
explicit_iter_loop,doc_overindented_list_items,
type_complexity,items_after_statements,derivable_impls.