Skip to content

Releases: millw14/merrymen

Android demo 0.1.2

Choose a tag to compare

@millw14 millw14 released this 03 Aug 16:38

This is the one that starts. 0.1.0 and 0.1.1 abort on launch on every Android 14+ device — delete them.

What was actually wrong

Self-inflicted, in two steps.

expo-screen-capture was added to stop the recovery phrase being screenshotted.
Inspecting the resulting APK showed it had pulled in
android.permission.DETECT_SCREEN_CAPTURE. That looked like an unexplained
permission for a wallet, so it was blocked.

It is not optional. ScreenCaptureModule.kt registers a screen-capture callback
inside OnCreate on Android 14+, with no permission check, at module creation —
whether or not the app ever asks to block screenshots. Without the permission
Android throws a SecurityException, which surfaces as an uncaught JS exception
before the runtime is ready and aborts the process:

Abort message: 'terminating due to uncaught exception … JavascriptException:
[runtime not ready]: Error: Exception in HostFunction: Permission Denial:
registerScreenCaptureObserver … requires android.permission.DETECT_SCREEN_CAPTURE

DETECT_SCREEN_CAPTURE is protection level normal — no prompt, no dialog,
no access to any content. It only lets the OS tell the app that a screenshot
happened, which for a wallet is a feature. It is now allowed. Verified present
in this APK's manifest.

The two earlier releases blamed a TextDecoder polyfill. That was a real latent
hazard and the fix is kept, but it was never this crash.

Still a demo

Every number it shows is generated on the phone, and it refuses to sign a
permission wall. Your recovery phrase is real and stays in the phone's keystore.

Permissions: INTERNET, ACCESS_NETWORK_STATE, USE_BIOMETRIC,
USE_FINGERPRINT, DETECT_SCREEN_CAPTURE. allowBackup=false. Signed with APK
Signature Scheme v2.

Android demo 0.1.1

Choose a tag to compare

@millw14 millw14 released this 03 Aug 11:01

⚠️ Broken — do not install

This build also aborts on launch on every Android 14+ device.

Use Android demo 0.1.2 instead.

These notes originally claimed this release fixed the 0.1.0 crash. That was
wrong.
The TextDecoder polyfill problem described below is real and the fix
is kept, but it was never the cause of the crash.

The actual cause was android.permission.DETECT_SCREEN_CAPTURE being blocked
in app.json while expo-screen-capture was installed. That library
registers a screen-capture callback at module creation on Android 14+, with no
permission check, so the missing permission threw a SecurityException before
the JS runtime was ready and aborted the process. Fixed in 0.1.2.


The TextDecoder issue (real, but not the crash)

polyfills.ts asserts TextDecoder exists and throws if it does not. The
text-codec shim ends with E || (TextDecoder = …, TextEncoder = …),
all-or-nothing on the environment's existing TextEncoder. Hermes ships
TextEncoder and not TextDecoder, so the guard short-circuited and the shim
installed neither. Browsers have both natively, so no web check could see it.

Fixed by hiding TextEncoder so the shim installs both, then restoring the
engine's own. Covered by a test that reproduces the Hermes shape.

Android demo 0.1.0

Choose a tag to compare

@millw14 millw14 released this 02 Aug 23:35

⚠️ Broken — do not install

This build crashes on launch on every Android device. It is kept only so
the link in older messages resolves to an explanation instead of a 404.

Use Android demo 0.1.2 instead. (0.1.1 is also broken.)

The cause given below was WRONG — see 0.1.2 for the real one
(DETECT_SCREEN_CAPTURE blocked while expo-screen-capture was installed).

Original, incorrect diagnosis: polyfills.ts asserts TextDecoder exists and throws if it does not —
the first code the app runs. The text-codec shim ends with
E || (TextDecoder = …, TextEncoder = …), all-or-nothing on the environment's
existing TextEncoder. Hermes ships TextEncoder and not TextDecoder, so
the guard short-circuited and the shim installed neither. Browsers have both
natively, so every web check passed and the failure could not be seen off a
real device.


A demo. It does not trade, and it will not sign anything.

This is the Android app running on generated data — every balance, position and
trade it shows is invented on the phone. It is here so you can see the thing and
walk the onboarding flow, not so you can run an agent.

It also refuses to sign a permission wall. Signing one would create a real
account on Robinhood Chain that real money could be sent to, while the app
reported fiction about it. So the demo build stops at that screen and says so.

Your recovery phrase is real and stays in the phone's keystore. Nothing is
uploaded anywhere — the app has no server to talk to in this build.

Desktop 0.1.7

Choose a tag to compare

@millw14 millw14 released this 29 Jul 00:26

The one-click Windows build — bundles Node, boots the agent worker and the dashboard, opens it in a native window. No terminal, no npm.

147 MB, down from 260 MB in 0.1.6.

Why it shrank

That drop is a bug fix, not better compression.

The desktop app depends on merrymen as a local path, which npm resolves to a symlink pointing at the repo root. The packager followed that symlink and copied the entire tree — including the build output directory holding previously built installers. Every release was packaging the previous release inside itself. 0.1.6 went out carrying 0.1.5; the first 0.1.7 build came out at 520 MB. It doubled every time.

The obvious fix — exclusion patterns in the packager config — does not work here, and fails silently: exclusions are not applied inside a symlinked package. Seven patterns were added and the rebuilt bundle still contained every directory they named. That silence is how this survived six releases. What ships is now decided by the same files allowlist that governs the npm package, so there is one list instead of two and a new directory cannot reach an installer without first being something deliberately published.

On the local-state directory

The same over-broad copy also swept in .data/, the directory where an agent running from a source checkout keeps its settings and trade database.

The published 0.1.6 was audited before this release. The database inside it is an empty scaffold — schema only, zero rows across agents, trades, positions, equity, events and fee_accruals — and the settings file is {}, last modified more than two weeks before that build. No keys, addresses, or trade history were ever published. Nothing needs to be rotated.

The mechanism was still a genuine hazard: on a machine that had actually run an agent from a checkout, that directory holds real API keys, and it would have gone into a public installer. It is now excluded structurally rather than by a pattern that can quietly stop matching.

Verified against the packaged build, not the source tree

  • Dashboard serves from the bundle — HTTP 200
  • Worker starts under the bundled runtime and ticks live — reached mainnet block 22008707
  • Bundle contains cli, node_modules, packages, strategies, web, worker and nothing else

Installing

Windows will show a SmartScreen warning, because the installer is unsigned. Click More infoRun anyway. If you would rather not, npm i -g merrymen gets you the same agent from a terminal.

To check what you downloaded:

Get-FileHash .\merrymen.Setup.0.1.7.exe -Algorithm SHA256

b9294b430da9010a7c12f0bce6a6657df03822ccbc15db92a1c46d21482b3418

macOS and Linux: npm i -g merrymen, then merrymen start.

Your keys stay on your machine. This app never sends them anywhere.

Desktop 0.1.6

Choose a tag to compare

@millw14 millw14 released this 26 Jul 20:09

Windows desktop app — bundles merrymen 0.17.0.

Includes fixes from three community contributors:

  • The vault sweep now sizes itself to your actual daily cap. Previously steady-basket could propose a deposit larger than the permission wall would ever accept, and re-propose the identical rejected deposit every tick, forever, while the cash never reached the vault. Found by @zeeonchain.
  • The Telegram /link code is minted as soon as merrymen starts, instead of only once Telegram is switched on — so a valid bot token no longer shows an empty code. Found by @Victory-byte.
  • Fixed a backtest bug that reported policy rejections which never happened: the harness never let the day roll over, so multi-day runs spent their budget on day one and reported daily-cap for every bar after. Found while reviewing @Akixama's strategy-playground PR.

Also in 0.17.0: every trade now records the decision behind it (including the model's own reasoning and the signals it saw), and per-position cost basis makes realized P&L a real number.

Security: this build carries the dashboard DNS-rebind fix. If you are still on 0.1.4, please update — that build is vulnerable.

SHA256 f026e47de02e26348192f6abc578b6168bfc3b6cb626e18049c459f3ab424bae

Desktop 0.1.5

Choose a tag to compare

@millw14 millw14 released this 25 Jul 02:45

Security update. The dashboard had a flaw where a malicious webpage could slip past the browser-origin guard and reach merrymen's API on your own machine — including the recovery endpoint. If you installed 0.1.4, please update. Keys and caps were never the weak point; the guard in front of the dashboard was. Bundles merrymen 0.17.0.