ApexYX-Sovereign/docs/termux-tutorial.md at main · xhall-beep/ApexYX-Sovereign · GitHub
//blob/show" data-turbo-transient="true" />
Skip to content
Search/
Sign in<br>Sign upAppearance settings
You signed in with another tab or window. Reload to refresh your session.<br>You signed out in another tab or window. Reload to refresh your session.<br>You switched accounts on another tab or window. Reload to refresh your session.
Dismiss alert
{{ message }}
xhall-beep
ApexYX-Sovereign
Public
Notifications<br>You must be signed in to change notification settings
Fork
Star
FilesExpand file tree
main
/termux-tutorial.md
Copy path
Blame<br>More file actions
Blame<br>More file actions
Latest commit
History<br>History<br>History
151 lines (115 loc) · 7.17 KB
main
/termux-tutorial.md
Copy path
Top
File metadata and controls<br>Preview
Code
Blame
151 lines (115 loc) · 7.17 KB
Raw<br>Copy raw file<br>Download raw file
OutlineEdit and raw actions
Running a 10-tier SQLite Agent Mesh on Termux without Thermal Throttling
Phones are hostile hardware for agent systems. A passively-cooled SoC starts<br>throttling within minutes of sustained load, Android kills background<br>processes on a whim, and every polling loop you leave running converts<br>battery into heat into slower clocks into longer loops — a feedback spiral<br>that ends with a warm brick.
This is a walkthrough of the engineering decisions that let a 10-tier agent<br>mesh (message bus, router, executor, scheduler, learner, egress, state, plan,<br>guard, mirror) run indefinitely on a stock Pixel under Termux, with no root,<br>no cloud, and no cooling problems. Case study: ApexYX-Sovereign, which ships<br>these tiers with 421 hermetic self-tests. Everything below is in the shipped<br>code, not aspiration.
1. The enemy list
Three things kill long-running agents on Android:
Thermal throttling. Sustained CPU on a passively-cooled SoC raises<br>die temperature until the kernel governor cuts clocks. Work takes longer,<br>which holds temperature up, which keeps clocks down.
The phantom process killer. Since Android 12, apps (including Termux)<br>get a budget of 32 phantom child processes; exceed it or trip excessive-CPU<br>detection and the kernel starts SIGKILLing your daemons silently.
Doze and app standby. Long sleeps in a background process are not<br>guaranteed to wake on time; timers drift, sockets die.
The common thread: you cannot afford long-lived busy processes. Any<br>architecture built on "N daemons, each polling every few seconds" loses on<br>all three fronts at once.
2. Architecture: ticks, not daemons
Every tier in the mesh is a standalone CLI, and every recurring behaviour is<br>driven by ticks — a single short-lived process that evaluates everything<br>due, does the work, and exits:
mesh_sched.py --tick # evaluate all schedules/triggers once, cron-safe
The scheduler tier stores jobs in SQLite (every 30m, daily 07:30,<br>@boot, five-field cron specs, and sensor triggers like battery:).<br>The tick computes what is due, posts work items onto the bus, and exits in<br>well under a second. Between ticks, nothing is running. CPU duty cycle for<br>the orchestration layer is effectively the tick frequency times tick cost —<br>tens of milliseconds per minute.
Daemon mode exists for the executor (--interval 10) when you want low<br>latency, but it is optional. The design rule: daemons are an optimization,<br>ticks are the contract. A phantom-process kill of a daemon loses nothing,<br>because the next tick reconstructs all state from SQLite.
3. SQLite as the message bus (and why WAL matters on a phone)
The bus is one SQLite file (~/.mesh/bus.db), one table, and a CLI:
mesh post --node me --kind inbox --text "..." # append<br>mesh task --node me --text "..." --for exec # addressed work item<br>mesh claim --id 7 --node exec # exactly-once handoff<br>mesh done --id 7 --node exec # close out
Two pragmas do the heavy lifting:
PRAGMA journal_mode=WAL<br>PRAGMA busy_timeout=10000
WAL lets ten uncoordinated short-lived processes hammer the same file from<br>cron without readers blocking the writer; busy_timeout turns lock<br>collisions into brief waits instead of errors. On flash storage this also<br>concentrates writes into the WAL file instead of scattering page rewrites —<br>kinder to both latency and flash wear.
Rows are append-only and sealed with a sha256 hash chain; mesh verify<br>recomputes the chain and screams if any byte of history was edited. Exactly-<br>once execution is a single UPDATE ... WHERE state='new' compare-and-swap —<br>no distributed-lock machinery, because SQLite is the lock.
4. Thermal admission control: nothing runs unless the phone can afford it
The guard tier is the part most agent frameworks are missing. Before any<br>expensive work runs, it must pass admission:
guard check model --node brain --tokens 4000<br># exit 0 = allow, 10 = defer, 20 = deny — shell-scriptable
The sensor layer reads battery percentage, charging state, and temperature<br>via termux-battery-status when present, falling back to<br>/sys/class/power_supply/battery/* and a...