BasaltAPS

BasaltAPS · A personal artificial pancreas

Many columns, one formation

Keep one person's glucose safely in range, around the clock, with a system they own, understand, and can trust to keep working when parts of it fail.

What it is

BasaltAPS does this by running a personal artificial pancreas not as one large app but as a set of small, independent ones that cooperate — today a pump driver, a data store, an algorithm, a viewer, a watch; tomorrow whatever the loop needs — each doing one thing, each able to fail and restart without taking the others down. Robustness is the organizing priority: the loop is spread across modules and devices so no single failure can stop it. Everything else the suite offers — predictions, fewer false alarms, better control — is built on that foundation, never traded against it.

Why basalt. When lava cools slowly it fractures into separate, mostly hexagonal columns that pack together into a single formation. Each column stands on its own; the formation stands because of all of them — and it has no fixed number of columns. That is the architecture: independent parts, as many as the loop needs, one formation.

The formation

Each column is one app with one job. Apps may depend only on the shared contracts and the algorithm library — never on each other — and the build fails if one does.

  1. BasaltStore

    the record

    The authoritative record: every sample, event and determination, and which source is fresh or stale. Every other app reads it through one contract.

  2. DanaBTController

    the pump driver

    Drives the Dana-i pump over Bluetooth, enforces its own hard dose limits whoever is asking, and writes an audit line for every command.

  3. BasaltML

    the algorithm

    Computes insulin on board, runs the oref1 port and decides each cycle. The only app allowed to command the pump.

  4. BasaltView

    the viewer

    The chart, the alerts and the one-tap kill switch. It can die without touching the loop.

  5. Basalt Wear

    the standby

    A watch that holds warm-standby loop state and takes over both radio links when the phone is gone.

    Planned · Phase 6

Beneath them, two libraries and no shared app code: contracts — the permissions, schema and pump interface every app speaks — and loop-core, the pure-Kotlin port of the oref1 algorithm.

Values

Robustness first
The measure of the system is whether it keeps working — through a crash, a dead battery, a lost connection, a missing device. Features are welcome on top of that; nothing is allowed to weaken it.
Safety is a property of failure, not success
Anyone can be safe when everything works. The system is judged by where it lands when a part dies mid-operation — and it must land somewhere safe by default.
You own the loop
Your data, your devices, your decisions. Nothing on the critical path depends on a server you don't control or a vendor who can switch it off. Cloud copies are extras, never the only copy.
No silent failures
Every part reports its own state — fresh or stale, measured or estimated, running or stopped — and the absence of a signal is never read as health. A failure that announces itself is manageable; a quiet one is the dangerous kind.
Every alert earns its interruption
An alert is a request for action, so each one must be actionable and valuable — an alert that can be ignored teaches you to ignore the next one. Noise cannot be driven to zero; it is the price of alarming on doubt. But it is minimized relentlessly, under one fixed condition: reducing alerts must never reduce what is detected. Prediction is how that price is paid down — better signal, fewer interruptions, the same coverage.

Principles

Redundancy that scales
Robustness isn't won by making one app bulletproof — it's won by having spares.
Any part, replaceable at any time
Pump, sensor, algorithm, screen, storage — each sits behind a plain contract, so any one can be swapped, upgraded, or — when it fails — taken over by a standby, without disturbing the rest.
Fail safe by default
Every failure path resolves to a safe state on its own. The loop going silent means insulin delivery reverts to profile basal as the pump's own timers expire — never a dose that runs away.
Bias every error toward the safe side
Detection errs toward alarming — a missed failure is unbounded. Action errs toward withholding — a skipped dose is recoverable next cycle; insulin delivered on a bad reading cannot be taken back.
One authority at a time, many copies
Exactly one component commands the pump at any moment, and exactly one record is authoritative; every other copy is a fallback.
Trust no caller
Each app enforces its own limits regardless of who is asking.
Engineer the catch-up, not the perfect handoff
A reliable recovery beats a fragile handoff every time.
Recovery must be simple under stress
A fallback you can't operate while low, tired, or without your glasses isn't a fallback.
Small enough to hold in one head
Each app is bounded so it can be understood and tested completely.
Reuse what's proven; invent only where you must
The algorithm, the constraints, the safety machinery are borrowed from years of field-tested work.
Earn authority with evidence, one column at a time
Nothing commands the pump until it has run alongside the trusted system in shadow mode and survived deliberate failure drills.

All eleven, in full, in the charter.

Where it stands

As of

BasaltAPS grows around a working AndroidAPS loop one phase at a time, and every phase ships something usable on its own. AndroidAPS keeps running the loop until Phase 4's failure drill passes on real hardware.

  • 0 Foundation Done

    One contract library, one signing key, four signature permissions, a threat model.

  • 1 Store read API Done

    The store exposes its record; the viewer reads it and survives a restart with full history.

  • 2 Pump API Done

    The pump driver's command interface, behind signature permissions, with dose limits enforced on the pump side.

  • 3 Algorithm in shadow Done

    BasaltML computes a determination every cycle beside AndroidAPS and writes it to the store, holding no pump permission.

  • 4 Guarded closed loop Built, not enabled

    The dosing stages, their guards, the kill switch and the chaos-drill runbook are merged. Every dosing stage ships off; nothing has run against real hardware yet.

  • 5 Retire AndroidAPS Ahead

    CGM straight from the sensor app, AndroidAPS uninstalled, predictions accepted only if they lower interruptions without lowering what is detected.

  • 6 Watch failover Ahead

    A warm-standby watch that takes over the pump and sensor links and runs a degraded loop when the phone is lost.

  • 7 Backup phone Ahead

    A spare phone kept current by an encrypted bundle, taken over in a few actions, reconciled from the pump's own history.