Commit Graph
205 Commits
Author SHA1 Message Date
Hugh Kaznowski b2e48a1002 Merge ticket/021-remove-alert-delivery-hint-text 2026-09-05 19:39:11 +01:00
Hugh Kaznowski 3428a24149 Merge ticket/014-json-log-structured-display 2026-09-05 19:39:04 +01:00
Hugh KaznowskiandClaude Sonnet 5 b3e0272544 Add JSON field path extraction for params/metrics (ticket 015)
RegexToMetricPrimitiveMatcher and the standalone param declaration
(DeclareParamRequest/DataValue::ParamDeclaration) gain an optional
json_field_path, an alternative to capture_group that reads a
dot-separated field path (e.g. "foo.bar") out of lines that parse as
JSON objects. It's additive and serde-defaulted, so existing
regex-based params/metrics are unaffected. Params.tsx now offers a
"JSON field" extraction option when the message match regex looks
like a JSON object.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 19:38:39 +01:00
Hugh KaznowskiandClaude Sonnet 5 56da086c7a Allow editing an existing metric declaration in place (ticket 022)
Clicking a declared metric badge in Metrics.tsx now loads its regex/params
into the declaration form for editing (in addition to selecting it for the
bucket-values view), and shows those properties inline once selected rather
than only on hover. The backend gains PUT /api/metrics/{name}, backed by a
new engine::update_metric that reuses declare_metric's validation, requires
the metric to already exist, supports renaming, and re-backfills bucket data
from the new regex/params instead of leaving stale buckets from the old one.
Submitting the form while editing calls the update endpoint in place rather
than creating a second declaration; declaring a brand-new metric is unchanged.

Note: tickets/022-edit-existing-metric-declarations.md does not exist on this
worktree's branch (it was added to tickets/ on main after this branch was
created), so there is nothing to delete here.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 19:38:00 +01:00
Hugh KaznowskiandClaude Sonnet 5 21419ae8ea Add IsError worked example to Parameters docs (ticket 019)
Shows how to declare a boolean IsError param (regex (?i)error, kind
boolean, no capture group) that's true/false on every log line, using
the boolean param kind added in ticket 018.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 19:35:32 +01:00
Hugh KaznowskiandClaude Sonnet 5 a9855de3ad Add Boolean param kind that is always present true/false (ticket 018)
MetricPrimitiveKind gains Boolean, serialized as "boolean". A param
declared with kind Boolean skips capture-group validation and, instead
of being omitted when message_match_regex doesn't match, is present on
every log line as true/false based purely on whether the regex matches
(case-insensitively or per the regex's own flags). Params.tsx lets you
pick boolean as a kind and disables the now-unused capture group input.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 19:35:02 +01:00
Hugh KaznowskiandClaude Sonnet 5 a198eae1fd Add json[field] filter accessor for JSON log lines (ticket 016)
Extends the FilterBar query language with a json[field] <op> value
comparison, parsed by filter_parser.pest/rs alongside metric[param],
and evaluated in engine.rs by parsing each line as JSON at query time
(lines that aren't valid JSON, or lack the field, simply don't match).
Also wired into alerts.rs since json[field], like regex/sequence/
timestamp, only needs the line's own text.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 19:34:21 +01:00
Hugh KaznowskiandClaude Sonnet 5 7463050357 Carry over rolling preset id to popout tabs and add range controls to standalone Metrics/Dashboards
Popped-out tabs now carry the active TimeRangePresetId (e.g. "5m") via a
`preset` query param instead of only resolved absolute startMs/endMs, so a
rolling preset keeps independently sliding in the new tab on its own polling
cadence rather than freezing to the source tab's window at open time. A
fixed/dragged range is still carried over as absolute bounds. StandaloneRanged
(metrics/dashboards standalone pages) now owns its own preset/range state and
renders LogTimeline for its own preset buttons and drag-to-select UI, instead
of only ever showing a frozen, uncontrollable range. log and params standalone
pages are unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 19:34:20 +01:00
Hugh KaznowskiandClaude Sonnet 5 68a18a286f Refetch dashboard panels on the shared polling cadence
PanelPreview only refetched its PromQL series when panel.promql,
chart_type, or range bounds changed, so panels went stale under a
fixed range or between rolling-preset ticks that didn't move the
window. Add a POLL_MS-driven tick folded into the same fetch effect
(alongside the existing deps) so it refreshes on the same cadence as
App.tsx's log/timeline polling without double-fetching when a range
change and a tick coincide. POLL_MS is now shared via
webapp/src/lib/polling.ts instead of living only in App.tsx.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 19:33:56 +01:00
Hugh KaznowskiandClaude Sonnet 5 83cc7105d6 Add regex cheat-sheet icon next to regex inputs
Adds RegexHelpIcon, a hover/click popover (modeled on HelpIcon) showing
a compact cheat sheet for the Rust `regex` crate's actual syntax, and
places it next to every user-facing regex field: Params/Metrics message
match regex, Alerts field regex, and FilterBar's regex(...) helper.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 19:32:36 +01:00
Hugh KaznowskiandClaude Sonnet 5 d30e204f80 Remove alert delivery hint text from Ntfy sink section
Drop the "Every alert rule delivers here — see the Alerts panel to
define rules." hint paragraph from the Ntfy settings UI in NavMenu.tsx.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 19:32:08 +01:00
Hugh KaznowskiandClaude Sonnet 5 8579a925d7 Apply theme/custom CSS in popped-out standalone tabs (ticket 025)
StandalonePage now calls useSettingsPanel() so colour scheme and any
active custom theme CSS are applied on mount and stay in sync with
settings changes, matching the main window's NavMenu-driven behavior.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 19:32:00 +01:00
Hugh KaznowskiandClaude Sonnet 5 cb101aa5da Render JSON log lines as collapsible key/value trees (ticket 014)
LogPreview.tsx now detects when a log line's raw text parses as a JSON
object and renders it as a collapsible tree instead of raw text; any
other line (non-JSON or invalid JSON) keeps today's plain-text
rendering unchanged. Client-side only, no backend changes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 19:31:19 +01:00
Hugh Kaznowski e423a6667a Tickets added 2026-09-05 19:29:01 +01:00
Hugh KaznowskiandClaude Sonnet 5 882822fb18 Merge ticket/010-resizable-sections
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 19:00:54 +01:00
Hugh KaznowskiandClaude Sonnet 5 f6a32b2b30 Make the log viewer resizable via a drag handle (ticket 010)
Adds a drag-to-resize handle between the log viewer and the sections
below it in the main layout, addressing the log view being too small
with no way to enlarge it. Height is tracked in state, clamped to a
sane range, and persisted to localStorage (ottyl.logViewerHeightPx)
following the app's existing per-viewer UI-state persistence pattern
(see CollapsibleSection.tsx, LogPreview.tsx).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 19:00:40 +01:00
Hugh KaznowskiandClaude Sonnet 5 ed1524139a Merge ticket/009-all-dashboards-print-friendly-view
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:55:08 +01:00
Hugh KaznowskiandClaude Sonnet 5 559883dbab Add "All dashboards" print-friendly stacked view (ticket 009)
Adds an "All dashboards" selector alongside the existing click-to-select
single-dashboard view. Selecting it stacks every dashboard vertically in
normal document flow, each preceded by a heading naming it, with no
fixed-height or scroll-clipping containers, so the browser's native print
function can render the full stack across pages.

Verified in-browser: single-dashboard editing still works unchanged, and
"All dashboards" renders all dashboards (including an empty one) stacked
with named separators; confirmed via computed layout that only the
pre-existing app-level scroll container grows to fit the content, with no
clipping container inside the Dashboards section itself.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:54:52 +01:00
Hugh KaznowskiandClaude Sonnet 5 6b6480e99d Merge ticket/007-simplify-dashboards-header-label
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:51:16 +01:00
Hugh KaznowskiandClaude Sonnet 5 b2e97520ec Simplify Dashboards header to just "Dashboards" (ticket 007)
Drop the redundant profile-name suffix from the Dashboards section
header; the active profile is already surfaced via the profile
dropdown in NavMenu.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:51:10 +01:00
Hugh KaznowskiandClaude Sonnet 5 cd9a5443d3 Merge ticket/006-collapse-via-title-bar-click
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:49:12 +01:00
Hugh KaznowskiandClaude Sonnet 5 5038295554 Collapse sections by clicking their title bar (ticket 006)
Alerts, Metrics, Params, and Dashboards now toggle collapsed state when
their header row is clicked, instead of requiring a dedicated collapse
button. The chevron (CollapseToggle) becomes a purely visual, non-focusable
indicator for these sections; HelpIcon and PopOutButton now stop
propagation so they keep working without also collapsing the section.

The log viewer's toggle (App.tsx/FilterBar) keeps its dedicated button,
since that row is a filter toolbar with an editable input rather than a
plain title bar, so CollapseToggle's onToggle prop stays available for
that case.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:48:59 +01:00
Hugh KaznowskiandClaude Sonnet 5 01eadf415c Merge ticket/002-collapsible-alerts-section
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:44:33 +01:00
Hugh KaznowskiandClaude Sonnet 5 87209ea401 Make Alerts section collapsible
Wire the Alerts section into the shared CollapsibleSection mechanism
(CollapseToggle + useSectionCollapsed), matching the pattern used by
Metrics and Params, with its own persisted 'alerts' section id.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:44:22 +01:00
Hugh KaznowskiandClaude Sonnet 5 89ada0395f Merge ticket/004-012-theme-consolidation
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:43:04 +01:00
Hugh KaznowskiandClaude Sonnet 5 ffeba3c274 Merge "custom themes" and "configured/imported CSS" into one mechanism (ticket 012)
The backend already stored both under one CssEntry list (Imported/Linked,
differing only by the is_theme flag), but the NavMenu Settings panel split
them into two visually-duplicated sections — "Custom themes" with its own
upload/link forms and list, and "Import CSS"/"Configured CSS" with a nearly
identical upload form and a separate list — and useSettingsPanel exposed
parallel importCssEntry/importThemeEntry and (theme-only) linkThemeEntry
wrappers around the same underlying API calls.

Consolidate to one "CSS" section: a single list of all CssEntries (each
tagged "theme" and selectable when is_theme is set), one import form and
one link form, each with a "Use as theme" checkbox instead of a duplicate
theme-only form. useSettingsPanel now exposes a single importCssEntry(name,
content, isTheme) and a generic linkCssEntry(url, isTheme) — the latter also
fixes the prior asymmetry where linking (vs. uploading) was only available
for themes, not arbitrary CSS.

No backend or settings-schema changes were needed: is_theme already
persists correctly, so existing custom-theme and imported-CSS
configuration keeps working unmodified under the unified UI.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:42:40 +01:00
Hugh KaznowskiandClaude Sonnet 5 ed0be9726f Remove duplicate "grey" theme, keep "dark" (ticket 004)
"grey" and "dark" rendered identically apart from accent colour, so
drop "grey" as a selectable colour scheme everywhere in the frontend
(index.css, api.ts's ColorScheme type, the NavMenu picker, the
downloadable BUILTIN_THEMES table) and keep "dark" as the single
equivalent theme.

Existing settings.json files saved with color_scheme: "grey" keep
loading correctly: the backend ColorScheme enum aliases the legacy
"grey" serde value onto Dark, so old configs transparently migrate to
"dark" without any manual intervention.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:42:40 +01:00
Hugh KaznowskiandClaude Sonnet 5 e6e5bc8f50 Merge ticket/008-docs-worked-examples
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:38:58 +01:00
Hugh KaznowskiandClaude Sonnet 5 049c4f8311 Remove tickets/008-docs-add-worked-examples.md (implemented)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:38:56 +01:00
Hugh KaznowskiandClaude Sonnet 5 1db3adde90 Add worked examples to docs pages
Add concrete, verified examples to the General idea, Filtering,
Parameters, Metrics, Dashboards, and Settings docs sections, covering
common tasks like declaring a value-role duration param, building a
requests dashboard with line/bar/pie panels, and filter-bar syntax
gotchas (quoted vs. unquoted values, metric-only [param] comparisons).
Verified each example against the actual filter/PromQL parsers and
engine behavior in src/filter_parser.rs, src/promql.rs, and
src/engine.rs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:38:49 +01:00
Hugh KaznowskiandClaude Sonnet 5 80515e0f84 Merge ticket/005-sharp-angular-timeline-spikes
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:38:43 +01:00
Hugh KaznowskiandClaude Sonnet 5 5e2e556ea1 Merge ticket/011-approximate-heap-tracker
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:38:32 +01:00
Hugh KaznowskiandClaude Sonnet 5 2c509b51fc Remove tickets/011-approximate-heap-tracker.md (implemented)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:38:29 +01:00
Hugh KaznowskiandClaude Sonnet 5 0834c246d6 Add approximate heap/memory tracker for ingested logs (ticket 011)
Tracks a running total of ingested log bytes (approximated as each
log's raw UTF-8 text length), incremented on ingest and decremented
in evict_excess_logs when a log is dropped. Exposed via StatsDto's
new approx_bytes_total field on GET /api/stats, and displayed in
NavMenu's stats panel formatted with toLocaleString() (comma
separators).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:38:08 +01:00
Hugh KaznowskiandClaude Sonnet 5 de48e218a1 Use sharp/angular tops for timeline event spikes
Remove the rounded-t Tailwind class from timeline bars so spike peaks
render as sharp, flat-topped rectangles instead of rounded corners,
making bucket boundaries clearer to read. Verified in the browser in
both light and dark theme.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:37:27 +01:00
Hugh KaznowskiandClaude Sonnet 5 b1e509efbd Record JSON log ingestion design decision, file follow-up tickets (ticket 003)
Decision covers detection, invalid-JSON handling, and a prioritized feature
roadmap (repowise decision fdb47034ad954e3ea0b898fdc2750c32). Files three
follow-up implementation tickets (014-016) and removes the investigation
ticket now that the decision is recorded.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:36:27 +01:00
Hugh KaznowskiandClaude Sonnet 5 bb513b5eac Merge ticket/013-ntfy-sink-inline-fields
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:35:43 +01:00
Hugh KaznowskiandClaude Sonnet 5 ca6898a9b3 Merge ticket/001-remove-dashboard-nav-entry
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:35:33 +01:00
Hugh KaznowskiandClaude Sonnet 5 83c617d628 Remove tickets/001-remove-dashboard-nav-entry.md (implemented)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:35:30 +01:00
Hugh KaznowskiandClaude Sonnet 5 70d9956059 Lay out ntfy sink server URL and topic inputs on one line
Combines the ntfy server URL and topic fields into a single flex row
separated by a "/" to visually communicate that they compose into one
destination (server + topic), instead of stacking as two full-width
rows.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:35:24 +01:00
Hugh KaznowskiandClaude Sonnet 5 6d0cb92c19 Remove redundant "Dashboard" nav bar entry
NavMenu rendered a static, non-functional "Dashboard" span alongside
Presets/Settings/Docs buttons. It didn't toggle any panel — the real
Dashboards content (App.tsx's <Dashboards />) is already always visible
in the main content area, so it needed no nav entry to be reachable.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:35:24 +01:00
Hugh Kaznowski 893464b3b1 Create tickets 2026-09-05 18:31:22 +01:00
Hugh KaznowskiandClaude Sonnet 5 0a21582282 Simplify docs and add concrete examples for input fields
Rewrites doc-panel descriptions to be direct and absolute (no edge-case
hedging), and adds concrete example values for params, metrics, filter
queries, alert conditions, and CLI arguments. Also updates the Alerts/
Settings/Presets sections to describe the ntfy-sink-in-Settings and
profile-dropdown changes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:19:37 +01:00
Hugh KaznowskiandClaude Sonnet 5 e69ce4e0ba Replace the Presets side panel with an inline profile dropdown
Presets is no longer a collapsible NavMenu tab. It's now a compact
dropdown in the sidebar listing profiles, with a "+" button that prompts
for a name and creates+activates a copy of the current profile, and a
"×" button that deletes the active profile (disabled for Default).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:17:23 +01:00
Hugh KaznowskiandClaude Sonnet 5 12381545c8 Show the resolved default settings path in --help; add Prometheus/OpenMetrics polling
--settings-path's help text now names the actual resolved default path
(computed once via LazyLock) instead of only describing where to look for
one. Also adds an optional --metrics-url flag that polls a Prometheus/
OpenMetrics-compatible endpoint on an interval, pushing samples straight
into a metric's bucket (bypassing log-line regex matching) so they're
queryable via PromQL/dashboards alongside log-derived metrics.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:16:13 +01:00
Hugh KaznowskiandClaude Sonnet 5 18c2d72d22 Move the ntfy alert sink to Settings, shared by all alert rules
Alert rules no longer carry their own ntfy topic/server; Settings now
holds one process-wide ntfy sink (with its own "send test notification"),
and the Alerts panel is left to just define rule conditions.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:13:51 +01:00
Hugh KaznowskiandClaude Sonnet 5 ae4e550c1f Anchor log viewer scroll to visible content and add 1m/2m timeline presets
The log table no longer jumps when a sliding window prunes rows from the
front: scroll position now tracks the same visible row instead of holding
scrollTop constant in pixels. Also adds 1m/2m to the timeline quick-range
presets.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 18:08:23 +01:00
Hugh Kaznowski 070e835fa4 Resolve ui stuff 2026-09-05 18:00:56 +01:00
Hugh KaznowskiandClaude Sonnet 5 00c21c8032 Trim comments across Rust and webapp source to direct one-liners (ticket 030)
Pass over src/*.rs, webapp/src/**, and the in-app "?" docs prose:
condensed multi-paragraph doc comments to single lines that state the
non-obvious why, deleted comments that only restated adjacent code, and
tightened the Docs.tsx help-panel wording. No logic, structure, or code
formatting changed — verified via cargo test (143 passed) and
tsc -b && vite build.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 17:02:33 +01:00
Hugh KaznowskiandClaude Sonnet 5 3cef6dc8ae Remove unused tower-http dependency (ticket 029)
Audited every entry in Cargo.toml and webapp/package.json against actual
usage. tower-http was declared but never referenced in src/ (no ServeDir,
CorsLayer, or other tower_http usage) — it was only pulled in transitively
via reqwest anyway, so it's dead weight as a direct dependency. All other
Cargo.toml and package.json entries have live usage (including include_dir,
which looked unused via grep but is required transitively by the
fs_embed::fs_embed! macro, and tailwindcss, which is pulled in via
@import "tailwindcss" in src/index.css rather than a JS import).

cargo test (143 passed) and webapp npm run build both pass after pruning.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
2026-09-05 16:50:54 +01:00