KeeperHub / KeeperHub/keeperhub

Add treasury runway analysis to the Math plugin

Open
#2,483 4 comments 0 reactions 0 assignees View on GitHub
confirmed enhancement needs-discussion
Dominant language
TypeScript
Stars
24
Forks
93
Avg merge
1d 4h
Merged PRs (30d)
253

Description

### Before filing

- [x] I searched open and closed issues for this proposal.
- [x] I checked the docs and the current behaviour on `staging`.
- [x] This is one change, not several. (Several means several issues.)

### Reason: what you cannot do today

While building [Runlock](https://github.com/Fatumayattani/runlock), I needed to calculate treasury runway inside a KeeperHub workflow before deciding whether a recovery action was required.

KeeperHub can assemble parts of this calculation using multiple existing Math and condition nodes, but it does not currently provide one native action that consistently calculates spendable balance, net burn rate, remaining runway, estimated depletion time, required recovery funding, and a machine-readable treasury status.

I checked the Math plugin on `staging` commit `249cf2e0721716cdbb5d475d56c5403f3d891848`. Its registered actions are Aggregate, Compare With Tolerance, and Format Number. I also searched the repository and open and closed issues for treasury runway and related terms without finding an existing dedicated implementation.

My current workaround is to calculate the runway and recovery policy inside Runlock before passing an approved execution action to KeeperHub. Although this requirement came from building Runlock, it is not specific to Runlock, Safe, Superfluid, a particular token, or a particular chain. Any treasury workflow using balances, recurring inflows, recurring outflows, and a protected reserve could use the same analysis.

### Reason: what the workaround costs

The current workaround requires me to calculate treasury runway outside KeeperHub or assemble it from several separate Math and condition nodes.

Calculating it externally moves an important treasury decision outside KeeperHub’s workflow and audit trail. Building it from multiple nodes requires every workflow author to define the same rules for token decimals, protected reserves, net burn, zero or negative burn, runway, recovery requirements, and status boundaries.

This adds unnecessary workflow complexity and creates opportunities for inconsistent rounding, division-by-zero errors, loss of precision on large token values, or accidentally treating protected reserves as spendable funds. It also makes the final decision harder to review because one treasury-health result is spread across several nodes instead of being produced by one clearly defined action.

### Scope: what this touches, and what it does not

I propose adding one credential-free, read-only Treasury Runway action to the existing `plugins/math/` integration.

The action would accept a treasury balance, incoming flow rate, outgoing flow rate, protected reserve, minimum runway threshold, and token decimals. It would return the spendable balance, net burn rate, remaining runway, estimated depletion time when applicable, required recovery amount, and a machine-readable `safe`, `warning`, or `critical` status for downstream workflow conditions.

The change would include the action registration, precision-safe calculation logic, and focused unit tests covering protected reserves, status boundaries, invalid inputs, zero or negative net burn, token decimals, and large integer values.

It would not fetch treasury data, contact an RPC or external service, execute transactions, alter existing Math actions, change existing response shapes, add credentials or dependencies, modify authentication or database schemas, or affect pricing and spend limits.

This is one change because the status, runway, depletion estimate, and recovery amount are all derived from the same normalized inputs and treasury policy. Separating them would recreate the multi-node workaround this action is intended to solve.

### Plan: what you propose

I propose adding a `treasury-runway` action to the existing Math plugin.

The action would accept precision-safe string inputs for the treasury balance, incoming flow rate, outgoing flow rate, and protected reserve, together with token decimals and a minimum runway measured in days. The rate fields would use one clearly documented configurable period so values from different upstream sources can be normalized before the runway calculation.

The calculation would follow these rules:

* Spendable balance is the treasury balance minus the protected reserve, bounded at zero.
* Net burn is the outgoing rate minus the incoming rate.
* When net burn is positive, runway is the spendable balance divided by net burn.
* When net burn is zero or negative, the treasury is not depleting and no recovery amount is required.
* Required recovery is the additional balance needed to reach the configured minimum runway.
* `safe` means the minimum runway is satisfied or the treasury is not depleting.
* `warning` means runway is positive but below the required minimum.
* `critical` means no spendable runway remains while net burn is positive.
* Estimated depletion time is returned only when the treasury is depleting.

The output would expose `success`, `spendableBalance`, `netBurnRate`, `runwayDays`, `depletionAt`, `requiredRecoveryAmount`, `status`, and a structured error when validation fails. Precision-sensitive amounts and durations would be returned as strings, and `depletionAt` would be `null` when the treasury is not depleting.

I would implement the calculation with KeeperHub’s fixed-point decimal helpers and integer arithmetic so token-sized values are not converted through JavaScript floating-point arithmetic.

I would follow `plugins/CLAUDE.md`: register the action in `plugins/math/index.ts`, wrap the step with `runPluginStep`, set `maxRetries = 0`, add no credentials or network egress, and place reusable calculation logic in a `treasury-runway-core.ts` file if it needs to be exported for focused unit testing.

Existing Math actions and their callers would remain unchanged.

### Plan: alternatives you considered

I considered composing the result from the existing Aggregate, Compare With Tolerance, and workflow condition nodes. I rejected that approach because it requires every workflow author to reproduce the same unit conversions, protected-reserve rules, status boundaries, and zero-burn behaviour across several nodes.

I also considered keeping the calculation entirely inside Runlock. That works for one application, but it leaves a reusable treasury decision outside KeeperHub’s workflow and audit boundary.

A Runlock-specific plugin or a separate Treasury plugin was another option. I rejected that because this calculation has no Runlock dependency, requires no credentials or network access, and fits naturally as deterministic arithmetic within KeeperHub’s existing Math plugin.

Doing nothing would preserve the current flexibility, but workflow authors would continue rebuilding the same treasury analysis and accepting the additional complexity and risk of inconsistent calculations.

### Scope: compatibility

- [ ] Changes an existing response shape, status code, CLI flag, or default.
- [ ] Adds, removes, or upgrades a dependency.
- [ ] Changes database schema or requires a migration.
- [ ] Touches authentication, permissions, validation, or spend limits.
- [ ] Changes pricing, plan limits, or anything a user is charged.

Contributor guide

Open the contributing guide

Research direction

Start by reading plugins/CLAUDE.md and plugins/math/index.ts to understand action registration and the existing Math actions, then locate their focused tests and fixed-point decimal helpers. Add the treasury-runway action and any treasury-runway-core.ts logic described in the issue, with tests for the listed validation, precision, reserve, burn, status, and large-value cases. Done means the action is registered, uses runPluginStep with maxRetries = 0, adds no credentials or network access, and leaves existing actions unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.