Reconcile the staged-projection and Diagnostics feature work with the CI
quality-gate changes from origin/main. The origin side of every conflict was
lint-only, so the feature imports were kept and the ruff fixes re-applied:
- keep the branch's added imports (timefmt, activity_readout, projection
ladder helpers) and drop the unused ones ruff reported
- restore `noqa: E402` on the post-bootstrap imports in fenris-monitor and
keep the `noqa: F401` re-exports in the TUI that tests assert on
- make the TUI monitoring-glyph test clock-relative instead of pinned to a
fixed date
Record host read and write commands, controller busy time, error log
entries, warning and critical temperature time, and thermal management
transitions from the existing smartctl -a -j acquisition. Schema 7 adds
nullable columns to samples so legacy rows read as unknown, and the
Diagnostics panel shows each counter with its change.
Toggle a Diagnostics panel with i, built on the Activity readout. It swaps
in for the Drive pane and shows the decoded critical_warning, power-on
hours, power cycles, unsafe shutdowns, media errors and available spare
with their change over the selection, and per-hour (Day) or per-day
(History) temperature min/avg/max, active/idle/powered-off/unknown split
and coverage. History bars draw reads beside writes while it is open, and a
set critical_warning shows as a badge in the endurance outlook without
affecting the projection. Counter deltas are withheld across a controller
segment change.
Declare every dashboard key as a Binding on the widget that owns it, and
generate the footer, activity tool chips and help screen from those
bindings so they cannot drift. The footer collapses to "? help · q quit"
under 80x24.
Add Home/End and PgUp/PgDn (one week) navigation, mouse-wheel selection on
the graphs, click-to-focus on every panel, and clickable footer chips.
Tab and Shift+Tab now visit only the dashboard panels.
Move activity data assembly out of tui.py into activity_readout, behind
readout(conn, selection, now). Dashboard and fenris-monitor enable now show
local time with a timezone label, inspected points keep a secondary UTC line,
and the legacy UTC-relabelled day and hour branches are gone. Time formatting
(including freshness_age_human) lives in timefmt. Hour offsets now render as
+05:30 to match day labels.
Add a b key and a no-baseline banner that open a form for rated TBW and an
optional source URL. The value is persisted as an unverified override through
fenris-monitor baseline set under the existing polkit action, and the outcome
is reported synchronously. Verified overrides stay CLI-only (ADR 0012 section 7).
Report a projection stage, an evidence ladder and the sustained-regime
write rate from compute_projection, per ADR 0012. A provisional lifespan
appears after 3 observed hours and carries the hours observed and a
short-horizon spread; the complete-local-day condition becomes a fact
instead of a gate, and the write rate replaces the lifespan when no
baseline applies. The TUI and CLI render the stage, ladder count and
full ladder, and drop their own two-sample pre-gates.
Use lifetime written bytes from the current segment's newest published
sample in the headline formula, select the Percentage-Used-implied
baseline after two increments in the segment (otherwise show the
too-coarse fact), and judge horizon agreement across existing horizons.
Make the vacuous projection tests assert unconditionally and add
coverage for implied-baseline gating and single-horizon agreement.