NexaFlow v3.79.0
Fixed
- Task runs silently skipped — four root causes eliminated. User-reported:
many automations did not execute on a connected device. Static analysis and
device logcat review traced every skip path to the admission layer, not the
actions:- Save-time snapshot race —
saveAutomationread the capability snapshot
synchronously while the refresh triggered on screen entry was still in
flight, so the pre-scan answer classified runnable tasks as inadmissible
and saved them disabled. Admission is now decided on
CapabilityStateStore.freshSnapshot(): request a refresh, wait (bounded,
4 s budget) for an observation made at or after the request. Inside the
store's 30 s minimum-refresh backoff the recent snapshot is returned
immediately, so the save flow can never hang. - Stale snapshot blocking runs — the whole-run capability gate blocked
any task whose snapshot was inadmissible, including snapshots observed
hours earlier while the process sat in the background. A snapshot older
than 60 s is now treated as not evidence about the device: the gate
admits and every action path re-verifies the concrete capability live
before its first side effect (diagnostic timeline entry
CAPABILITY_BLOCKED_STALE_SNAPSHOT). - Fresh-block learning — a block on a genuinely fresh, observed
unavailability now schedules a targeted capability refresh
(capabilitySnapshotInvalidator), so a grant that lands right after a
blocked run is seen by the next run instead of re-blocking on the same
evidence forever. - Grant visibility after failure — when an action failed with "No
elevated runtime", the engine only invalidated the root-probe cache,
which the 5 s storm-spacing guard then silently swallowed; a grant that
landed a second earlier stayed hidden through every "refresh".
SystemAppStatusDetector.refreshAndProbe()now bypasses the spacing
guard deliberately (documented: one extrasuspawn is the price of
never hiding a fresh grant), and the engine retries the action exactly
once when the re-probe flips to granted — safe, because the previous run
never reached the elevated runtime and no side effect can have started.
- Save-time snapshot race —
Tests
CapabilityGateFreshnessTest(4 tests): stale snapshot admits, startup
race admits, fresh block records and schedules a refresh, fresh admissible
runs.SaveAdmissionFreshnessTest(2 tests):freshSnapshotreturns a
post-refresh observation; respects the backoff window without hanging.RefreshAndProbeTest(3 tests): forced refresh bypasses the spacing guard,
result is cached for ordinary callers, invalidate-only can never observe a
grant. All tests seed a deterministic baseline so none depends on leftover
probe state or wall-clock distance.- Full suite: 816 unit tests across
core/execution,core/rom-integration
anddomain— 0 failures, 0 skipped.
Quality evidence
The tag workflow gates publication on the following automated checks. Consult the exact tag run and validation record for results; these checks do not establish physical-device coverage:
- Android Lint (zero-tolerance: UnusedResources, MissingTranslation, ExtraTranslation,
UnusedIds, CheckResult, HardcodedText, TypographyDashes) and Detekt static analysis. - Catalog parity gates: every
TriggerTypeandActionTypeenum value must exist
exactly once in the builder picker (restricted entries are pinned explicitly). - Full unit-test suite, including Room migration, scheduler, lifecycle, and recovery
regression coverage. - Release build with R8 full shrinking, APK signature verification (v2/v3 schemes and
certificate-fingerprint match against the production keystore), 16 KB page-size
alignment check, zipalign verification, bundletool AAB validation, and Gradle
dependency verification (SHA-256 checksums for every artifact). - Tag hygiene: the tag must match the newest
CHANGELOG.mdentry, so the notes below
are the actual, reviewed change record for this release.
Install
- Download
NexaFlow-<version>.apkfrom the assets below and install it. - Android updates require a compatible version code and the same signing certificate.
Back up important tasks before upgrading. - Pre-release tags (
alpha/beta/rc) are marked as pre-releases automatically.