Commit Graph
143 Commits
Author SHA1 Message Date
Torlando fabd3713df fix(nomadnet): make the transient-stall time window wrap-safe across millis()
A stall spanning the 32-bit millis() rollover zero-extends to a value smaller
than the pre-wrap start, so the now_ms >= start_ms guard blocked the bail until
the counter lapped the ~49.7-day start value. Use 32-bit unsigned subtraction,
which measures true elapsed time across the wrap. Regression: a stall starting
near the counter max and wrapping bails in bounded ticks.
2026-09-15 14:03:25 +00:00
Torlando 32a09938d8 fix(nomadnet): address Greploop round 1 on the cache transient-stall guard
Three findings on the transient-stall bail, all valid:

- Reload invalidation: a bail recorded BYPASS, but NomadNetCacheFlow::service()
  accepts only MISS as a successful invalidation, so a bail during an admitted
  reload reported 'Page cache invalidation failed' instead of falling through
  to a live fetch. The bail now records MISS.

- Open-resource leak: the bail cleared read_open_/write_open_ (and abandoned an
  open directory enumeration) without calling endRead()/abortWrite()/endList(),
  leaking SD handles. The bail now releases each in-flight resource via the
  seam's own teardown (bounded best-effort; a still-transient close is
  accepted rather than re-pinning the op).

- Tick-vs-time: the not-ready UNAVAILABLE path returns immediately (no bus
  wait), so a pure 500-tick budget could expire during a legitimate SD mount
  window and disable caching for the whole session. The bail is now gated on
  BOTH the tick floor AND a 10s wall-time window (service() takes a monotonic
  ms clock; production passes millis(), 0 is a safe default for tests).

Regression tests: reload-invalidation bail -> NEED_LIVE (flow), flat-clock does
not bail, healable transient keeps authority, list-open (RECOVERY_END) stall
bails and releases the handle (cache).
2026-09-15 06:27:14 +00:00
Torlando feb7f0574b fix(nomadnet): bound cache transient-stall so a failing SD seam cannot freeze the UI
The SD page cache (16af3b5) made the SD card a soft dependency of
NomadNet page loads, but its step machine retries a transient storage
result (BUSY = SPI-mutex timeout, UNAVAILABLE = card not mounted)
forever with no budget. On a persistently unhealthy seam the boot-time
recovery pins operation_ != NONE, the flow stays LOOKUP, and the UI
freezes at 'Checking SD page cache...' (the CACHE state has no
deadline, unlike every other NomadNet state).

NomadNetCache::service() now compares each call's entry state to the
previous call's. Any advance (op, offset, scan/cleanup index, scan
count, open-flags) resets a stall counter, so slow-but-progressing
steps (chunked 64 KB transfers, up to 96-record directory scans) never
false-trip; a no-progress tick is a transient stall. Past 500
consecutive no-progress ticks (far beyond any real SPI contention or
SD mount window) the cache bails: mark the namespace non-authoritative
for the session (lookups/commits bypass) and clear the op, so the flow
falls through to a live fetch -- the pre-cache page-load behavior.

Regression tests: cache-level (persistent UNAVAILABLE recovery bails;
lookup bypasses after bail) and flow-level (a permanently BUSY
beginList no longer parks the flow in LOOKUP; it reaches NEED_LIVE in
bounded ticks). Both fail on the pre-fix code and pass with it.

Verified: tdeck firmware build SUCCESS; tests/native 121 passed (3
pre-existing env failures, fail identically on origin/main baseline);
tests/build_scripts 184 passed.
2026-09-07 18:52:03 +00:00
Torlando 3c6275d9e6 chore(diag): gate [SENDT] and [PG] instrumentation behind build flags
[SENDT] send-pipeline timing and the microReticulum [PG] path-store
call-site counters now compile to no-ops unless explicitly enabled:
  - DPYXIS_SEND_DIAG / -DRNS_PATHGET_DIAG added to env:tdeck base flags
  - both removed by env:tdeck-release build_unflags (no-op in release)

So production tdeck/tdeck-release builds are merge-clean, while the
instrumented build stays one env/flag away for the path-request
spammer hunt. Bumps microReticulum pin to 921b3aa (same endpoint
hot-path read gate, counters gated behind RNS_PATHGET_DIAG).

Contract suite: 176/176.
2026-09-06 22:42:16 +00:00
Torlando db3033d3b0 fix(propagation): gate endpoint hot-path path-table reads (microReticulum bump)
Bumps microReticulum pin to e2c9d4d (diag/path-get-caller on cd0338e):
Transport::inbound() and path_request() no longer perform a full
microStore get() (flash write + read) for every inbound packet / path
request on endpoint-only nodes. The read is gated on the exact
conditions where destination_entry is consumed, and the local-destination
path-request answer uses the in-memory _destinations table, so the
device stays discoverable. The build still carries the temporary [PG]
counters for the live before/after capture; counters are stripped in a
follow-up before anything merges.
2026-09-06 19:14:44 +00:00
Torlando 8a0eabf432 diag: bump microReticulum to ef07187 (path-get caller counters)
TEMPORARY DIAGNOSTIC PIN. ef07187 = cd0338e + per-call-site
_new_path_table.get() counters ([PG] summary every 30s on serial).
Purpose: identify which Transport call site drives the ~1.5s full
FileStore get() on the offline propagation node (6b9f6601...).
Revert this commit (back to cd0338e) after the capture.
2026-09-06 06:12:05 +00:00
Torlando 3de986daed fix(lxmf): bound automatic path requests to 30 min per identity
Greptile P2 on PR #92: with 64 tracked sources, evicting the oldest
entry discarded its open cooldown, so a flood of distinct bogus
identities reset other sources' windows and forced unbounded path
requests (each answered by every peer holding the announce).

- Per-identity cooldown 5 min -> 30 min.
- The table no longer evicts an open window: while all 64 slots hold
  unexpired windows, never-before-seen identities are deferred until a
  slot frees (at most one 30-minute window) instead of dropping
  someone else's cooldown. Open windows are only ever pruned after
  they expire.
- Aggregate bound: at most kMaxTrackedSources automatic path requests
  per rolling 30-minute window, capping the worst-case network cost of
  a rotating-identity flood.

Host tests extended: saturated-table deferral, 512-identity flood bound
(one window and across consecutive windows), lazy expiry/prune,
boundary checks at the 30-minute cooldown.
2026-09-02 17:05:14 +00:00
Torlando 2eec34dfe1 test: extract unknown-source key-request policy + host tests
Move the rate-limit/cooldown/cap decision out of the UIManager.cpp
anonymous namespace into a pure, header-only policy
(UI/LXMF/UnknownSourceKeyRequest.h) so it is host-testable without the
ESP/microReticulum stack. UIManager keeps only the side effect
(Transport::request_path).

Adds tests/native/test_unknown_source_key_request.{cpp,py} (24 checks,
ASan+UBSan): new-source request, 5-min cooldown boundary, re-record
resets the window, per-source independence, 64-entry cap with oldest
eviction, and steady-state cost.
2026-09-02 16:22:56 +00:00
Torlando 0f6309c5a6 fix: widen MapTileStore path buffer for 31-char pack IDs
Raise MapTileStore::PATH_CAPACITY from 64 to 80 so the mount buffer
(PATH_CAPACITY + 4) holds the 80-character mounted tile path produced by
a maximum-length (31-char) pack ID with full-width tile coordinates.
Pre-fix, any tile with a two-digit x or y returned INVALID_ARGUMENT from
the mount-prefix snprintf, which MapTilePack maps to IO_ERROR and the UI
shows as 'Tile I/O error' even though the file exists and is intact.

The host regression test added in the prior commit now passes under both
strict C++11 and ASan/UBSan; reverting this change fails it.
2026-08-28 22:44:27 +00:00
Torlando b7ab97d624 test: add host regression for MapTileStoreSD mount-path overflow
A 31-character pack ID makes mounted tile paths
(/sd/pyxis-map/packs/<id>/tiles/<z>/<x>/<y>.png) exceed the 68-byte mount
buffer once either x or y is two digits, so beginRead returns
INVALID_ARGUMENT and the UI shows 'Tile I/O error' at z4+ even though the
file exists and is intact.

Compiles the unmodified MapTilePack/MapTileStoreSD/SDAccess/codec/manifest
sources against small Arduino/FreeRTOS host shims. The core section (no
card needed) drives the real store with a model of the mount-prefix
arithmetic and asserts the 31-char-ID boundary loads at z4/z5; an optional
end-to-end section runs the real MapTilePack over a bound card root when
/sd is writable.

Fails on the current 64-byte PATH_CAPACITY: red by design.
2026-08-28 22:44:27 +00:00
Torlando 7c96ffac82 fix(maps): cancel stale tile rendering safely 2026-08-20 04:53:00 +00:00
Torlando d9cb64a1ea feat(maps): resolve visible tiles without span indexes 2026-08-20 04:53:00 +00:00
torlando-agent[bot] 26de7c3e41 fix(nomadnet): keep partial refresh status in chrome 2026-08-18 01:30:14 +00:00
torlando-agent[bot] 1027667f5a feat(nomadnet): integrate dynamic partial rendering 2026-08-17 23:49:13 +00:00
torlando-agent[bot] b793f356e3 test(nomadnet): accept attested package reference 2026-08-17 20:09:48 +00:00
torlando-agent[bot] b6faec8104 feat(nomadnet): add bounded partial core 2026-08-17 19:54:41 +00:00
torlando-agent[bot] 27ac127f5e fix: preserve eight-column NomadNet tables 2026-08-17 16:50:21 +00:00
torlando-agent[bot] ca73ff2e3f fix: show NomadNet navigation progress promptly 2026-08-17 15:47:41 +00:00
torlando-agent[bot] 5b76abfdbe fix: align NomadNet cache response policy 2026-08-17 14:50:00 +00:00
torlando-agent[bot] 2f0f7900ca feat: enforce NomadNet limits and observability 2026-08-17 09:11:10 +00:00
torlando-agent[bot] 3658c54cc7 fix: retry cache lookup after busy operation 2026-08-17 06:03:38 +00:00
torlando-agent[bot] 16af3b53af feat: add bounded NomadNet SD page cache 2026-08-17 05:48:30 +00:00
torlando-agent[bot] 2ef6b0254d ci: provision mandatory NomadNet peer gate 2026-08-17 02:34:24 +00:00
torlando-agent[bot] f40fec17c4 fix: refine NomadNet form input handling 2026-08-17 01:07:19 +00:00
torlando-agent[bot] 98dca8e516 feat: add bounded NomadNet forms 2026-08-16 21:36:30 +00:00
torlando-agent[bot] 64eec3acd7 fix: isolate NomadNet table cell styles 2026-08-16 15:48:55 +00:00
torlando-agent[bot] d9945bce24 feat: add bounded NomadNet table rendering 2026-08-16 15:33:52 +00:00
torlando-agent[bot] 9ce2f10107 fix: add NomadNet anchor navigation 2026-08-16 02:40:10 +00:00
torlando-agent[bot] 48349a1df4 fix: match NomadNet heading presentation 2026-08-16 01:25:37 +00:00
torlando-agent[bot] 5f3696716f fix: consume unknown NomadNet modifiers 2026-08-16 01:25:07 +00:00
torlando-agent[bot] cf72c9b399 fix: support NomadNet grayscale colors 2026-08-16 01:25:07 +00:00
torlando-agent[bot] 97e3e8b09a fix: preserve NomadNet divider characters 2026-08-16 01:24:13 +00:00
torlando-agent[bot] 5961c791d6 Virtualize NomadNet page layout 2026-08-15 02:33:37 +00:00
torlando-agent[bot] fd776d7b78 Bound NomadNet pages and preserve decompression headroom 2026-08-14 22:50:00 +00:00
torlando-agent[bot] b50ae852ac fix(nomadnet): submit configured link variables 2026-08-14 18:11:32 +00:00
torlando-agent[bot] 76eae01ef3 fix(nomadnet): coalesce link focus outlines 2026-08-14 04:59:02 +00:00
torlando-agent[bot] 427206ef8f fix(nomadnet): honor micron colors 2026-08-14 01:59:25 +00:00
torlando-agent[bot] 42f87b8c75 fix(nomadnet): preserve navigation glyph coverage 2026-08-14 01:19:37 +00:00
torlando-agent[bot] 5826ad9b6a fix(nomadnet): scope page fonts to rendered content 2026-08-14 00:47:52 +00:00
torlando-agent[bot] 12def2c746 fix(nomadnet): use JetBrains Mono NL faces 2026-08-14 00:47:52 +00:00
torlando-agent[bot] 656f1c03cb fix(nomadnet): validate addresses before teardown 2026-08-14 00:39:04 +00:00
torlando-agent[bot] f605aa386d fix(nomadnet): release directory memory before navigation 2026-08-13 20:58:23 +00:00
torlando-agent[bot] 77e5123455 feat(nomadnet): checkpoint compact page lifecycle
Add bounded compact page rendering, serialized Link and Resource lifecycle handling, TCP reconnect corrections, and deterministic Python RNS conformance coverage.

Physically verified anonymous index retrieval and rendering on T-Deck. Same-destination Link reuse and italic rendering remain follow-up fixes.
2026-08-13 20:58:23 +00:00
torlando-agent[bot] b7b39a16df fix: keep navigation responsive during style activation 2026-08-12 19:02:03 +00:00
torlando-agent[bot] 78300b00ee Merge origin/main into feat/map-style-picker 2026-08-12 18:22:33 +00:00
torlando-agent[bot] c4d20e2907 test: cover incomplete LittleFS scans 2026-08-12 16:44:06 +00:00
torlando-agent[bot] b5aae24e77 fix: safely initialize erased LittleFS partitions 2026-08-12 15:44:26 +00:00
torlando-agent[bot] f6fc95d046 fix: prevent tile worker starvation on unchanged map model 2026-08-11 01:19:07 +00:00
torlando-agent[bot] f03e1c5937 fix: serialize map style activation lifecycle 2026-08-08 18:10:02 +00:00
torlando-agent[bot] 66f551515f feat: add offline map style switcher 2026-08-08 15:21:42 +00:00