Commit Graph
14 Commits
Author SHA1 Message Date
Jean-Pierre MartineauandClaude Fable 5 f69d1785b7 Performance sweep: cache the render funnel, the queries, the graphs
Every repaint re-rasterized every row and re-ran every layout; every
screen open re-scanned the whole history. Now work is done once per
change instead of once per frame:

Render pipeline — a content-keyed ANSI cache in render_to_ansi (every
Text/str row app-wide), memoized corner glow, and panel-wrap memos for
the base frame and stacked dialogs, all dropped on a platform switch or
emoji recalibration. Idle-frame compose falls 5-100x per screen
(contacts 5.6->0.1 ms, record card 8.5->0.07 ms, trace 7.6->0.6 ms).

Repository — an observed_at index turns every since-window query into a
range walk (recent_observations 7.5->1 ms); heard_nodes and first_seen
aggregate in one streaming pass by ISO-string comparison instead of
hydrating dataclasses and sorting; node_names groups in SQL (NOT
INDEXED past a slow planner choice).

Per packet — livefeed no longer repaints on events that drew nothing,
the channel list's stats TTL rises above the tick so the repository is
not queried per frame, watch-store alerts batch through the throttled
flush instead of a full-state disk write per new node, and the header's
360-bucket histogram/flags tuples are memoized per minute and packet.

Per open — the resolvers, topology canonical()/display_name(), and
Yen's route search memoize over their frozen inputs; timemachine, chat,
and livefeed drop duplicate queries; the config editor, device actions,
info, advert, and tx-optimize reuse the devstate session cache instead
of re-asking the radio.

Per frame, per screen — dashboard folds five window scans into one
digest; walk caches everything derived from its frozen graph (the
onward-count quadratic included); packet viewer, record dialog, trophy
rows, trace stats/log, and the node-detail route fan memoize on their
frozen inputs, invalidated by revision counters where the input can
move.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 18:14:53 -04:00
Jean-Pierre MartineauandClaude Fable 5 1efe3cae67 Exit groups: two lists still spelled Back by hand
The chat picker and the TX-optimize target picker appended their own
Separator + Back rows; back_rows is the enforcement point that keeps the
exit language from drifting (housekeeping H-004).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 23:06:02 -04:00
Jean-Pierre MartineauandClaude Opus 4.8 1edd4a3bf4 Remove Plotly and the TX-optimize HTML chart
The viz package existed solely to render one interactive HTML chart for
tx-optimize sweeps, pulling in Plotly — a heavyweight dependency serving a
single artifact while every other timeline renders in-terminal via
braillechart. Drop it with no replacement: delete meshterm/viz, the
--viz/--no-viz flag and its render call, the now-unused output_dir setting
(config field, default, loader, example), the Plotly test, and the README
and pyproject references.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 19:53:08 -04:00
Jean-Pierre MartineauandClaude Opus 4.8 310783c6a3 Repeater admin: float the login over the node picker, not a blank frame
The admin-login password prompt ran on an empty stack (the picker was popped
when it returned), so session.text pushed a blank base and the prompt — and any
"wrong password" rejection — floated over an erased background.

open_repeater_admin now redraws the node picker as a static backdrop (extracted
admin_picker_rows, shared with the live pick so they can't drift) and keeps it
pushed across _login, with the picked node highlighted. The password box and the
rejection float over the picker, matching the device-picker and trophy-case
dialogs. floating=True stays on the prompt as a belt-and-suspenders fallback.

Also drop the inert floating=True on tx_optimize._resolve_password: that
resolver only runs on the scripted CLI path (PlainUi, no stack), so the flag
never did anything — the menu path logs in inside the pushed sweep screen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 20:33:12 -04:00
Jean-Pierre MartineauandClaude Opus 4.8 59b26ae616 Dialogs: float confirms/prompts over their backdrop, never replace the screen
Enforce the UX standard "modal popups over the pushed backdrop" across three
flows that were drawing a full-frame replacement instead of a floating popup:

- Trophy case: keep the record browser pushed as a static backdrop while its
  delete-record / delete-discipline / delete-all confirms float over it, and
  run any trace hand-off after popping.
- Device picker: pass the picker's rows through to the removal confirm so it
  floats over a redraw of the list (backdrop_items/backdrop_default on
  confirm_startup), with the row being removed left highlighted.
- Remote-admin password: add an opt-in floating flag to Ui.text so a mid-flow
  password prompt draws as a centered popup over a blank base instead of the
  full frame; apply it to repeater_admin and tx_optimize logins. Tool-entry
  text prompts (Trace/tx target fallbacks) stay full-frame.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 20:07:41 -04:00
Jean-Pierre MartineauandClaude Opus 4.8 e07ef3b379 Device state: cache the picker reads that run before each screen
The session cache fixed the reads screens make on open, but opening the
heaviest screens still stalled for seconds — because the pickers and
screen-openers that run *in front of* those screens were still reading the
radio directly. The menu wraps prompt-gathering and execution in one busy
overlay, so a Trace or Chat open pays its picker's slow round-trips before
the (already-cached) screen behind it ever builds, which is why caching the
screens alone showed no improvement.

Route the interactive-open reads through ctx.devstate too:

- Chat's conversation picker read the channel-slot probe *and* the contacts
  table on every open (~5s) — both now come from the cache (channels mapped
  from the cached slots via the new _channels_from_slots, contacts served
  cached). The CLI list/send path keeps reading fresh.
- Trace and TX-optimize target pickers now read contacts from the cache.
- The repeater-admin screen and the channels manager (its slot probe, on a
  local copy so mutations still re-probe the fresh layout after invalidation)
  read through the cache.

Small, session-stable reads (self-info, build_snapshot's tuning/path-hash)
are left as direct reads — they were never the seconds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 22:41:58 -04:00
Jean-Pierre MartineauandClaude Fable 5 aef80d18bb Repeater admin: set up remote nodes over the mesh
A new Device management entry for administering repeaters and room
servers. The shared credentialed-first picker (extracted from TX
optimize) chooses the node, login runs on remembered passwords with a
one-time prompt otherwise (forgotten on rejection), and the editor
lands in the local device-configuration screen's exact lanes — but
speaking the node's text CLI through a new public
Device.send_remote_command, which brings the repeater-only knobs the
local editor never had: TX delay, Direct TX delay, RX delay, airtime
factor, advert intervals, flood max, repeat, guest password.

Reads cost one paced mesh round trip each, so the editor never
bulk-reads on open: values show what the last read said, age-stamped,
from a new per-node remote.json cache; Read settings refreshes them
under an abortable progress dialog and Apply sends the staged sets
the same way, folding confirmed values back into the cache and
keeping refused ones staged. Advert, clock sync, password change, and
reboot run as confirmed popups.

The Command line is a readline-style screen onto the node's raw CLI:
per-node history persisted across sessions (↑↓ recall, adjacent-dupe
suppression, capped), Tab completion over the known verbs plus every
catalog get/set spelling with ghost-text preview, one command in
flight at a time. The simulator grows a full repeater CLI so all of
it drives against --mock, and a scripted one-shot
(repeater-admin <node> <command…>) covers automation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 04:14:16 -04:00
Jean-Pierre MartineauandClaude Fable 5 5046a86980 TX optimize rebuilt on the trace screen's armed-idle pattern
The old flow asked for a hand-typed comma-separated path, logged in
before showing anything, and started transmitting the moment the
screen opened, on parameters you couldn't touch. It now walks like the
trace feature: two pickers choose the link — the node to tune
(credentialed repeaters lead, wearing the key glyph), then the target
whose reception is optimized — and the screen opens armed but idle.

An action list drives it: Route opens the trace path composer pinned
at the tuned node (suggestions from observed links; direct by
default), Range/Step/Samples float small dialogs, and the Sweep row
always quotes the worst-case transmission count, so the cost of a
commit is on screen before anything goes on the air (coarse_levels
goes public to price it). Sweep logs in first — the password prompt
floats only when nothing is remembered — then runs coarse → refine →
verify under the trace tool's in-flight dialog with Abort, levels
landing in the bar chart behind it, best starred. Completion parks the
cursor on a new Apply-winner action row (the after-sweep dialog's
second chance), and a finished sweep leaves the screen armed: adjust
and sweep again, the chart clearing as a new measurement starts.

The scripted CLI keeps its one-shot flag set, table, and HTML chart.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 03:51:01 -04:00
Jean-Pierre MartineauandClaude Fable 5 85fc82a606 Regroup the menu: Mesh, Device management, Tools
Messaging becomes Mesh and takes in Nodes (between Channels and Map —
the "who's out there" view) and Send advert (last in section: its one
action, after its views), so everything mesh-wide lives under one
heading. Device becomes Device management and keeps the box-level
tools; Diagnostics becomes Tools.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 03:35:00 -04:00
Jean-Pierre MartineauandClaude Fable 5 87d2d10dff Every main-menu item leads with its own emoji
Tools gain an icon attribute — menu-only, so result windows and the
CLI keep the plain title — and the menu loop composes it into the
aligned name lane. Single-codepoint, emoji-presentation glyphs only,
so the two-cell width holds across terminals: 💬 Chat, 📻 Channels,
🌍 Map, 👥 Nodes, 📡 Send advert, 🔧 configuration, 🔨 actions,
📋 info, 🎯/👣 the traces, 🎧 Monitor, 📶 TX optimize, 🚪 Quit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 03:27:35 -04:00
Jean-Pierre MartineauandClaude Fable 5 9979f66f2a TX optimize sweeps live and asks to apply after the evidence is in
The six-prompt chain (path, samples, min, max, step, apply-up-front)
collapses to one: pick the path, and the live sweep screen takes it
from there. Levels land in an SNR bar chart as they are measured,
ascending by power with the current best starred, while the optimizer
announces its phase — coarse sweep, refining around the leader,
verifying — through a new on_phase callback. Reliability and trace
counts sit beside every bar, and a level nothing got through at reads
as an explicit no-reply row.

The apply decision moves to where it belongs: after the sweep, a
floating dialog offers the winner against the node's original power
(Cancel left, Apply right, Enter commits), and `a` re-offers it if
first declined. The sweep itself runs with apply off, so Esc at any
point stops the search and the optimizer's unwind restores the
original transmit power.

The sweep persists under one runs row (levels and traces alike), the
scripted CLI keeps its full flag set, chart, and --apply semantics,
and the tool moves in with Trace under Diagnostics.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 05:24:21 -04:00
Jean-Pierre MartineauandClaude Fable 5 44a093c460 Retire Heard nodes, Link health, Link budget, Route map, and History
Five features leave the menu and CLI: the heard-nodes review, the
baseline-regression checker, the offline link-budget calculator, the
route-stability graph, and the run-history browser — along with their
services (link_quality, link_budget, route_stability), the pyvis route
renderer, and the pyvis/networkx dependencies.

The data layer is untouched where it still earns its keep: passive
monitoring keeps recording every overheard packet (the header counters,
Nodes, and Map read it, and `meshterm monitor` still captures a bounded
window from the CLI), run logging keeps writing `runs` rows, and trace
history stays queryable for the trace tools. Only the route-map-only
`all_traces` query goes.

Also fixes a latent tie-break flake in the nodes sort: ages are now
measured from one clock snapshot, so identical last-seen stamps really
tie and keep their A→Z order in both directions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 05:08:11 -04:00
Jean-Pierre MartineauandClaude Fable 5 a23b12f6a4 Normalize UI copy: casing, headers, descriptions, backtracking
Enforce one voice across every screen: column and section headers are
UPPERCASE, menu items are Capitalized buttons, and short descriptions
drop their trailing period (with real ellipses instead of "...").

Tools gain a display `title` separate from their kebab-case CLI name,
so a menu item now reads exactly like the screen it opens ("Device
configuration" opens Device configuration) and result windows inherit
the same name. Every sub-screen backs out via a "Back" row below a
blank separator (the config editor was missing both; its Close is now
Back, spelling out the discard when changes are staged), while the main
menu and device picker keep "Quit". Panel and dialog titles now wear a
brighter tint of their border colour via new title.* theme styles.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 22:51:42 -04:00
Jean-Pierre MartineauandClaude Opus 4.8 2ec18138a7 Rename project from MeshTools to MeshTerm
Rename the package directory, imports, brand strings, env-var prefixes,
console-script entry point, and the config/data dir (~/.config/meshterm).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 19:40:49 -04:00