melete-ai 0.88.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +72 -0
- package/bin/melete-server.mjs +345 -0
- package/bin/melete.mjs +165 -0
- package/dist/achievability.d.ts +38 -0
- package/dist/achievability.d.ts.map +1 -0
- package/dist/achievability.js +135 -0
- package/dist/achievability.js.map +1 -0
- package/dist/aegis.d.ts +52 -0
- package/dist/aegis.d.ts.map +1 -0
- package/dist/aegis.js +191 -0
- package/dist/aegis.js.map +1 -0
- package/dist/arms.d.ts +70 -0
- package/dist/arms.d.ts.map +1 -0
- package/dist/arms.js +399 -0
- package/dist/arms.js.map +1 -0
- package/dist/batch.d.ts +30 -0
- package/dist/batch.d.ts.map +1 -0
- package/dist/batch.js +151 -0
- package/dist/batch.js.map +1 -0
- package/dist/bench.d.ts +49 -0
- package/dist/bench.d.ts.map +1 -0
- package/dist/bench.js +124 -0
- package/dist/bench.js.map +1 -0
- package/dist/certify.d.ts +48 -0
- package/dist/certify.d.ts.map +1 -0
- package/dist/certify.js +125 -0
- package/dist/certify.js.map +1 -0
- package/dist/cliff.d.ts +41 -0
- package/dist/cliff.d.ts.map +1 -0
- package/dist/cliff.js +132 -0
- package/dist/cliff.js.map +1 -0
- package/dist/confidence.d.ts +38 -0
- package/dist/confidence.d.ts.map +1 -0
- package/dist/confidence.js +98 -0
- package/dist/confidence.js.map +1 -0
- package/dist/constrained.d.ts +59 -0
- package/dist/constrained.d.ts.map +1 -0
- package/dist/constrained.js +191 -0
- package/dist/constrained.js.map +1 -0
- package/dist/cortex.d.ts +56 -0
- package/dist/cortex.d.ts.map +1 -0
- package/dist/cortex.js +81 -0
- package/dist/cortex.js.map +1 -0
- package/dist/costaware.d.ts +49 -0
- package/dist/costaware.d.ts.map +1 -0
- package/dist/costaware.js +185 -0
- package/dist/costaware.js.map +1 -0
- package/dist/drift.d.ts +36 -0
- package/dist/drift.d.ts.map +1 -0
- package/dist/drift.js +157 -0
- package/dist/drift.js.map +1 -0
- package/dist/efficiency.d.ts +49 -0
- package/dist/efficiency.d.ts.map +1 -0
- package/dist/efficiency.js +143 -0
- package/dist/efficiency.js.map +1 -0
- package/dist/engine.d.ts +64 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +130 -0
- package/dist/engine.js.map +1 -0
- package/dist/federated.d.ts +38 -0
- package/dist/federated.d.ts.map +1 -0
- package/dist/federated.js +121 -0
- package/dist/federated.js.map +1 -0
- package/dist/frontier.d.ts +51 -0
- package/dist/frontier.d.ts.map +1 -0
- package/dist/frontier.js +117 -0
- package/dist/frontier.js.map +1 -0
- package/dist/guardian.d.ts +46 -0
- package/dist/guardian.d.ts.map +1 -0
- package/dist/guardian.js +101 -0
- package/dist/guardian.js.map +1 -0
- package/dist/index.d.ts +90 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +189 -0
- package/dist/index.js.map +1 -0
- package/dist/interaction.d.ts +44 -0
- package/dist/interaction.d.ts.map +1 -0
- package/dist/interaction.js +167 -0
- package/dist/interaction.js.map +1 -0
- package/dist/interactive.d.ts +25 -0
- package/dist/interactive.d.ts.map +1 -0
- package/dist/interactive.js +75 -0
- package/dist/interactive.js.map +1 -0
- package/dist/inverse.d.ts +44 -0
- package/dist/inverse.d.ts.map +1 -0
- package/dist/inverse.js +141 -0
- package/dist/inverse.js.map +1 -0
- package/dist/ipshield.d.ts +62 -0
- package/dist/ipshield.d.ts.map +1 -0
- package/dist/ipshield.js +104 -0
- package/dist/ipshield.js.map +1 -0
- package/dist/journalist.d.ts +56 -0
- package/dist/journalist.d.ts.map +1 -0
- package/dist/journalist.js +132 -0
- package/dist/journalist.js.map +1 -0
- package/dist/lineage.d.ts +43 -0
- package/dist/lineage.d.ts.map +1 -0
- package/dist/lineage.js +112 -0
- package/dist/lineage.js.map +1 -0
- package/dist/metabrain.d.ts +59 -0
- package/dist/metabrain.d.ts.map +1 -0
- package/dist/metabrain.js +215 -0
- package/dist/metabrain.js.map +1 -0
- package/dist/mixedspace.d.ts +61 -0
- package/dist/mixedspace.d.ts.map +1 -0
- package/dist/mixedspace.js +267 -0
- package/dist/mixedspace.js.map +1 -0
- package/dist/multiobjective.d.ts +42 -0
- package/dist/multiobjective.d.ts.map +1 -0
- package/dist/multiobjective.js +123 -0
- package/dist/multiobjective.js.map +1 -0
- package/dist/noise.d.ts +45 -0
- package/dist/noise.d.ts.map +1 -0
- package/dist/noise.js +148 -0
- package/dist/noise.js.map +1 -0
- package/dist/noiserobust.d.ts +71 -0
- package/dist/noiserobust.d.ts.map +1 -0
- package/dist/noiserobust.js +215 -0
- package/dist/noiserobust.js.map +1 -0
- package/dist/oracle.d.ts +63 -0
- package/dist/oracle.d.ts.map +1 -0
- package/dist/oracle.js +106 -0
- package/dist/oracle.js.map +1 -0
- package/dist/poopt.d.ts +79 -0
- package/dist/poopt.d.ts.map +1 -0
- package/dist/poopt.js +148 -0
- package/dist/poopt.js.map +1 -0
- package/dist/portfolio.d.ts +51 -0
- package/dist/portfolio.d.ts.map +1 -0
- package/dist/portfolio.js +132 -0
- package/dist/portfolio.js.map +1 -0
- package/dist/prescription.d.ts +57 -0
- package/dist/prescription.d.ts.map +1 -0
- package/dist/prescription.js +131 -0
- package/dist/prescription.js.map +1 -0
- package/dist/prime.d.ts +85 -0
- package/dist/prime.d.ts.map +1 -0
- package/dist/prime.js +157 -0
- package/dist/prime.js.map +1 -0
- package/dist/provenance.d.ts +77 -0
- package/dist/provenance.d.ts.map +1 -0
- package/dist/provenance.js +155 -0
- package/dist/provenance.js.map +1 -0
- package/dist/rashomon.d.ts +40 -0
- package/dist/rashomon.d.ts.map +1 -0
- package/dist/rashomon.js +93 -0
- package/dist/rashomon.js.map +1 -0
- package/dist/reliability.d.ts +79 -0
- package/dist/reliability.d.ts.map +1 -0
- package/dist/reliability.js +197 -0
- package/dist/reliability.js.map +1 -0
- package/dist/replay.d.ts +62 -0
- package/dist/replay.d.ts.map +1 -0
- package/dist/replay.js +146 -0
- package/dist/replay.js.map +1 -0
- package/dist/replicate.d.ts +72 -0
- package/dist/replicate.d.ts.map +1 -0
- package/dist/replicate.js +103 -0
- package/dist/replicate.js.map +1 -0
- package/dist/resonance.d.ts +32 -0
- package/dist/resonance.d.ts.map +1 -0
- package/dist/resonance.js +190 -0
- package/dist/resonance.js.map +1 -0
- package/dist/sensitivity.d.ts +44 -0
- package/dist/sensitivity.d.ts.map +1 -0
- package/dist/sensitivity.js +109 -0
- package/dist/sensitivity.js.map +1 -0
- package/dist/server.d.ts +26 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +1410 -0
- package/dist/server.js.map +1 -0
- package/dist/shape.d.ts +37 -0
- package/dist/shape.d.ts.map +1 -0
- package/dist/shape.js +170 -0
- package/dist/shape.js.map +1 -0
- package/dist/sloppiness.d.ts +44 -0
- package/dist/sloppiness.d.ts.map +1 -0
- package/dist/sloppiness.js +194 -0
- package/dist/sloppiness.js.map +1 -0
- package/dist/sovereign.d.ts +77 -0
- package/dist/sovereign.d.ts.map +1 -0
- package/dist/sovereign.js +144 -0
- package/dist/sovereign.js.map +1 -0
- package/dist/space.d.ts +38 -0
- package/dist/space.d.ts.map +1 -0
- package/dist/space.js +107 -0
- package/dist/space.js.map +1 -0
- package/dist/surprise.d.ts +43 -0
- package/dist/surprise.d.ts.map +1 -0
- package/dist/surprise.js +123 -0
- package/dist/surprise.js.map +1 -0
- package/dist/territory.d.ts +43 -0
- package/dist/territory.d.ts.map +1 -0
- package/dist/territory.js +102 -0
- package/dist/territory.js.map +1 -0
- package/dist/trace.d.ts +58 -0
- package/dist/trace.d.ts.map +1 -0
- package/dist/trace.js +0 -0
- package/dist/trace.js.map +1 -0
- package/dist/transfer.d.ts +46 -0
- package/dist/transfer.d.ts.map +1 -0
- package/dist/transfer.js +112 -0
- package/dist/transfer.js.map +1 -0
- package/dist/twin.d.ts +41 -0
- package/dist/twin.d.ts.map +1 -0
- package/dist/twin.js +116 -0
- package/dist/twin.js.map +1 -0
- package/examples/train.mjs +8 -0
- package/examples/tune.mjs +11 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shinnapat Phunsriphatchalakul
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="assets/meli.svg" alt="Meli β the Melete mascot" width="130" />
|
|
4
|
+
|
|
5
|
+
# Melete
|
|
6
|
+
|
|
7
|
+
### The Sovereign Verifiable AI Analyst & Optimizer
|
|
8
|
+
|
|
9
|
+
**Find the best β and most *robust* β settings for any system you can measure, in the fewest experiments β then hand over a signed verdict anyone can re-verify offline.**
|
|
10
|
+
|
|
11
|
+
π Live demo β **[melete.mneme-ai.space](https://melete.mneme-ai.space)**
|
|
12
|
+
|
|
13
|
+
`MIT` Β· zero runtime dependencies Β· runs on your machine
|
|
14
|
+
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## What it is (in one line)
|
|
20
|
+
You have a system you can **measure** β an ML pipeline, a server/DB/network config, a recipe, a simulation. Melete proposes the next setting to try, you measure it (or give a formula), and it converges to the best **stable** answer β then explains *why* in plain language and signs a verdict you (or an auditor) can re-check offline. **Your data never leaves your machine.**
|
|
21
|
+
|
|
22
|
+
## Use it in 60 seconds β 3 ways
|
|
23
|
+
|
|
24
|
+
**1) Through the website (no code).** Open the [live demo](https://melete.mneme-ai.space), pick your field (Pharma Β· Semiconductor Β· AI/ML Β· β¦), press **Watch** to see it discover, or use **guided mode**: it proposes β you measure in real life β you type the score β repeat.
|
|
25
|
+
|
|
26
|
+
**2) CLI / npm (on your own machine):**
|
|
27
|
+
```bash
|
|
28
|
+
npm i -g melete-ai
|
|
29
|
+
melete bench # measured: beats random / grid search
|
|
30
|
+
melete gauntlet # every engine's correctness check (must be 100)
|
|
31
|
+
melete poopt cert.json # verify a signed certificate offline
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**3) API β connect your real process (air-gapped).**
|
|
35
|
+
First, get an endpoint to call β two options:
|
|
36
|
+
```bash
|
|
37
|
+
# A) hosted demo (quick try): base URL = https://melete.mneme-ai.space
|
|
38
|
+
# B) self-host (sovereign β data never leaves your machine):
|
|
39
|
+
npm i -g melete-ai
|
|
40
|
+
melete-server # β serves on http://localhost:8790
|
|
41
|
+
```
|
|
42
|
+
Then POST to that base URL:
|
|
43
|
+
```bash
|
|
44
|
+
POST /next { space, observations } β the next setting to try
|
|
45
|
+
POST /aegis { space, objective, budget } β the best ROBUST setting (survives wobble)
|
|
46
|
+
POST /discover { space, objective, budget } β full run + signed Sovereign Verdict + Replay Token
|
|
47
|
+
POST /sovereign/verify { β¦verdict } β re-verify provenance OFFLINE
|
|
48
|
+
POST /replay/verify { β¦token } β re-derive the decision step-by-step OFFLINE
|
|
49
|
+
```
|
|
50
|
+
β¦or skip HTTP entirely and call the library in-process: `import { sovereignAnalyze, aegisDiscover, proposeNext } from "melete-ai"`.
|
|
51
|
+
|
|
52
|
+
## What's inside β 43 engines, 4 layers
|
|
53
|
+
| | layer | what it does |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| π | **DISCOVER** | find the best setting in the fewest tries (adaptive ensemble) |
|
|
56
|
+
| β | **DECIDE** | the Ξ¦ brain's safety-first verdict + π‘ AEGIS, the *robust* answer (not the fragile spike) |
|
|
57
|
+
| π¬ | **DIAGNOSE** | plain-language *why*: which knobs matter, where the cliffs are, the shape, the achievable ceiling |
|
|
58
|
+
| π | **CERTIFY** | an Ed25519 **Sovereign Verdict** + a **Replay Token** β signed, offline-verifiable, step-by-step replayable |
|
|
59
|
+
|
|
60
|
+
## The moat
|
|
61
|
+
- π **Sovereign** β runs air-gapped, on your machine; data never touches a cloud.
|
|
62
|
+
- π **Verifiable** β every verdict is Ed25519-signed; an auditor re-verifies it offline with the embedded public key, no trust in us required.
|
|
63
|
+
- βͺ **Replayable** β the engine is fully deterministic, so a signed Replay Token re-derives the exact decision, step by step, on any machine, forever.
|
|
64
|
+
|
|
65
|
+
## Honest by design (DIAKRISIS)
|
|
66
|
+
Melete is an **optimizer + analyst**, not a fortune-teller. "Verifiable" means **provenance + reproducibility** β proof of *what was tested and the result reached, unaltered and re-derivable* β **not** a proof that your code is bug-free or exploit-free (that is undecidable in general; we don't claim it). Efficiency, robustness, and Pareto results are exact and reproducible. Run `melete gauntlet` β every claim is a check you can re-run.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
<div align="center">
|
|
71
|
+
<sub>Mneme remembers; Melete discovers. Β· <a href="https://melete.mneme-ai.space/pitch">pitch</a> Β· <a href="https://melete.mneme-ai.space/docs">API docs</a></sub>
|
|
72
|
+
</div>
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Melete discovery-as-a-service HTTP server. Self-contained (node:http + node:vm). Stateless.
|
|
4
|
+
* GET / β landing page (live demo)
|
|
5
|
+
* GET /health β { ok, version }
|
|
6
|
+
* POST /discover β { space, objective, budget, goal, engine } β best + armStats + signed trace + verify
|
|
7
|
+
* POST /verify β { trace } β { ok, reason }
|
|
8
|
+
*
|
|
9
|
+
* The objective is evaluated in a frozen VM sandbox (Math only) with a timeout β a demo-grade safety
|
|
10
|
+
* boundary, not a hostile-multi-tenant guarantee. Budget is capped server-side.
|
|
11
|
+
*/
|
|
12
|
+
import { createServer } from "node:http";
|
|
13
|
+
import { createContext, runInContext } from "node:vm";
|
|
14
|
+
import { readFileSync } from "node:fs";
|
|
15
|
+
import { fileURLToPath } from "node:url";
|
|
16
|
+
import { dirname, join } from "node:path";
|
|
17
|
+
import * as M from "../dist/index.js";
|
|
18
|
+
import { createHash } from "node:crypto";
|
|
19
|
+
|
|
20
|
+
const VERSION = (() => { try { return JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), "..", "package.json"), "utf8")).version; } catch { return "0.2.0"; } })();
|
|
21
|
+
const PORT = +(process.env.PORT || 8790); const HOST = process.env.HOST || "127.0.0.1";
|
|
22
|
+
const MAX_BUDGET = +(process.env.MELETE_MAX_BUDGET || 120);
|
|
23
|
+
|
|
24
|
+
const json = (res, code, obj) => { const b = JSON.stringify(obj); res.writeHead(code, { "content-type": "application/json", "access-control-allow-origin": "*", "content-length": Buffer.byteLength(b) }); res.end(b); };
|
|
25
|
+
const readBody = (req) => new Promise((resolve) => { let d = ""; req.on("data", (c) => { d += c; if (d.length > 1e6) req.destroy(); }); req.on("end", () => { try { resolve(d ? JSON.parse(d) : {}); } catch { resolve(null); } }); });
|
|
26
|
+
|
|
27
|
+
function makeOracle(space, objective) {
|
|
28
|
+
const ctx = createContext({ Math }); // sandbox has Math only (no require/process/fs); writable so dims can be bound
|
|
29
|
+
return (e) => { for (const d of space.dims) ctx[d.name] = e[d.name]; const v = Number(runInContext(objective, ctx, { timeout: 100 })); return Number.isFinite(v) ? v : -1e18; };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const server = createServer(async (req, res) => {
|
|
33
|
+
try {
|
|
34
|
+
const url = new URL(req.url, "http://x"); const path = url.pathname;
|
|
35
|
+
if (req.method === "OPTIONS") return json(res, 204, {});
|
|
36
|
+
if (req.method === "GET" && path === "/") { const html = M.landingPage(VERSION); res.writeHead(200, { "content-type": "text/html; charset=utf-8" }); return res.end(html); }
|
|
37
|
+
if (req.method === "GET" && path === "/pitch") { const html = M.pitchDeck(VERSION); res.writeHead(200, { "content-type": "text/html; charset=utf-8" }); return res.end(html); }
|
|
38
|
+
if (req.method === "GET" && path === "/docs") { const html = M.docsPage(VERSION); res.writeHead(200, { "content-type": "text/html; charset=utf-8" }); return res.end(html); }
|
|
39
|
+
if (req.method === "GET" && path === "/health") return json(res, 200, { ok: true, version: VERSION, service: "melete" });
|
|
40
|
+
|
|
41
|
+
// βͺ REPLAY β re-run a Replay Token OFFLINE: verify signature + deterministically reproduce step-by-step
|
|
42
|
+
if (req.method === "POST" && path === "/replay/verify") {
|
|
43
|
+
const body = await readBody(req); if (!body) return json(res, 400, { error: "invalid JSON" });
|
|
44
|
+
try { return json(res, 200, M.replayToken(body)); } catch (e) { return json(res, 400, { error: "replay failed: " + e.message.slice(0, 120) }); }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// π‘ IP SHIELD β re-verify a patent-grade IP audit trail OFFLINE
|
|
48
|
+
if (req.method === "POST" && path === "/ip-audit/verify") {
|
|
49
|
+
const body = await readBody(req); if (!body) return json(res, 400, { error: "invalid JSON" });
|
|
50
|
+
try { return json(res, 200, M.verifyIpAuditTrail(body)); } catch (e) { return json(res, 400, { error: "verify failed: " + e.message.slice(0, 120) }); }
|
|
51
|
+
}
|
|
52
|
+
// π¨ GUARDIAN β one heartbeat: detect drift/breach in a live metric history + recommend a re-tune
|
|
53
|
+
if (req.method === "POST" && path === "/guardian/tick") {
|
|
54
|
+
const body = await readBody(req); if (!body) return json(res, 400, { error: "invalid JSON" });
|
|
55
|
+
const history = Array.isArray(body.history) ? body.history.map(Number).filter(Number.isFinite) : [];
|
|
56
|
+
try { return json(res, 200, M.guardianTick(history, { baseline: body.baseline, lowerIsBetter: !!body.lowerIsBetter, breachFrac: body.breachFrac, degradeFrac: body.degradeFrac, window: body.window })); }
|
|
57
|
+
catch (e) { return json(res, 400, { error: "guardian failed: " + e.message.slice(0, 120) }); }
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// π SOVEREIGN β re-verify a signed Sovereign Verdict OFFLINE (provenance + reproducibility)
|
|
61
|
+
if (req.method === "POST" && path === "/sovereign/verify") {
|
|
62
|
+
const body = await readBody(req); if (!body) return json(res, 400, { error: "invalid JSON" });
|
|
63
|
+
try { return json(res, 200, M.verifySovereign(body)); } catch (e) { return json(res, 400, { error: "verify failed: " + e.message.slice(0, 120) }); }
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// π‘ AEGIS β the self-aware engine: returns the best ROBUST optimum (survives wobble), not the fragile spike
|
|
67
|
+
if (req.method === "POST" && path === "/aegis") {
|
|
68
|
+
const body = await readBody(req); if (!body) return json(res, 400, { error: "invalid JSON" });
|
|
69
|
+
const space = { dims: Array.isArray(body.space) ? body.space : body.space?.dims };
|
|
70
|
+
if (!space.dims?.length) return json(res, 400, { error: "space must be a non-empty array of {name,type,min,max}" });
|
|
71
|
+
if (space.dims.length > 12) return json(res, 400, { error: "demo limit: β€12 dimensions" });
|
|
72
|
+
if (typeof body.objective !== "string" || !body.objective.trim()) return json(res, 400, { error: "objective must be a JS expression string in your dimension names" });
|
|
73
|
+
const budget = Math.max(4, Math.min(MAX_BUDGET, (body.budget | 0) || 50));
|
|
74
|
+
let oracle; try { oracle = makeOracle(space, body.objective); oracle(Object.fromEntries(space.dims.map((d) => [d.name, (d.min + d.max) / 2]))); } catch (e) { return json(res, 400, { error: "objective failed to evaluate: " + e.message.slice(0, 120) }); }
|
|
75
|
+
const goal = body.goal === "minimize" ? "minimize" : "maximize";
|
|
76
|
+
try { const r = M.aegisDiscover({ space, oracle, budget, goal, seed: (body.seed | 0) || 1, robustWeight: typeof body.robustWeight === "number" ? body.robustWeight : 0.6 });
|
|
77
|
+
return json(res, 200, { best: r.best, rawBest: r.rawBest, robustnessOfBest: r.robustnessOfBest, tradedHeight: r.tradedHeight, evaluations: r.evaluations, goal }); }
|
|
78
|
+
catch (e) { return json(res, 400, { error: "aegis failed: " + e.message.slice(0, 120) }); }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// π° NOISE-ROBUST β trustworthy optimum under MEASUREMENT noise. Injects deterministic gaussian noise of
|
|
82
|
+
// the given std onto your objective (a stand-in for a noisy real oracle), replicate-measures, and returns
|
|
83
|
+
// the optimum you can trust (highest lower-confidence-bound) + the "lucky max" it rejected + a risk band.
|
|
84
|
+
if (req.method === "POST" && path === "/noise-robust") {
|
|
85
|
+
const body = await readBody(req); if (!body) return json(res, 400, { error: "invalid JSON" });
|
|
86
|
+
const space = { dims: Array.isArray(body.space) ? body.space : body.space?.dims };
|
|
87
|
+
if (!space.dims?.length) return json(res, 400, { error: "space must be a non-empty array of {name,type,min,max}" });
|
|
88
|
+
if (space.dims.length > 12) return json(res, 400, { error: "demo limit: β€12 dimensions" });
|
|
89
|
+
if (typeof body.objective !== "string" || !body.objective.trim()) return json(res, 400, { error: "objective must be a JS expression string in your dimension names" });
|
|
90
|
+
const budget = Math.max(12, Math.min(MAX_BUDGET, (body.budget | 0) || 110));
|
|
91
|
+
const noise = (typeof body.noise === "number" && body.noise >= 0) ? body.noise : 0.3;
|
|
92
|
+
let base; try { base = makeOracle(space, body.objective); base(Object.fromEntries(space.dims.map((d) => [d.name, (d.min + d.max) / 2]))); } catch (e) { return json(res, 400, { error: "objective failed to evaluate: " + e.message.slice(0, 120) }); }
|
|
93
|
+
const goal = body.goal === "minimize" ? "minimize" : "maximize";
|
|
94
|
+
const rng = M.lcg((body.seed | 0) || 1);
|
|
95
|
+
const noisyOracle = (e) => { const u1 = Math.max(1e-9, rng()), u2 = rng(); const g = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2); return base(e) + noise * g; };
|
|
96
|
+
try {
|
|
97
|
+
const r = M.noiseRobustDiscover({ space, oracle: noisyOracle, budget, goal, seed: (body.seed | 0) || 1, z: typeof body.z === "number" ? body.z : 1.85, replicates: (body.replicates | 0) || 5 });
|
|
98
|
+
return json(res, 200, { best: r.best, bestMean: r.bestMean, bestStd: r.bestStd, bestN: r.bestN, bestLcb: r.bestLcb, luckyMax: r.luckyMax, rejectedLucky: r.rejectedLucky, noiseFiltered: r.noiseFiltered, points: r.points.slice(0, 12), evaluations: r.evaluations, goal, noise });
|
|
99
|
+
} catch (e) { return json(res, 400, { error: "noise-robust failed: " + e.message.slice(0, 120) }); }
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// π§© MIXED-SPACE β optimize a space with categorical / integer / conditional knobs (not just continuous).
|
|
103
|
+
// Dims accept {type:"categorical",choices:[...]} and {activeWhen:{dim,equals}}; objective is a JS expr that
|
|
104
|
+
// may compare categoricals (e.g. engine==='B'?1:0.7). Returns the best full recipe + per-combo leaderboard.
|
|
105
|
+
if (req.method === "POST" && path === "/mixed") {
|
|
106
|
+
const body = await readBody(req); if (!body) return json(res, 400, { error: "invalid JSON" });
|
|
107
|
+
const dims = Array.isArray(body.space) ? body.space : body.space?.dims;
|
|
108
|
+
if (!Array.isArray(dims) || !dims.length) return json(res, 400, { error: "space must be a non-empty array of dims" });
|
|
109
|
+
if (dims.length > 12) return json(res, 400, { error: "demo limit: β€12 dimensions" });
|
|
110
|
+
if (dims.some((d) => d.type === "categorical" && (!Array.isArray(d.choices) || !d.choices.length))) return json(res, 400, { error: "each categorical dim needs a non-empty choices[]" });
|
|
111
|
+
if (typeof body.objective !== "string" || !body.objective.trim()) return json(res, 400, { error: "objective must be a JS expression string in your dimension names" });
|
|
112
|
+
const budget = Math.max(12, Math.min(600, (body.budget | 0) || 300)); // mixed is combo-heavy β its own cap
|
|
113
|
+
const goal = body.goal === "minimize" ? "minimize" : "maximize";
|
|
114
|
+
let oracle; try { oracle = makeOracle({ dims }, body.objective); } catch (e) { return json(res, 400, { error: "objective failed to compile: " + e.message.slice(0, 120) }); }
|
|
115
|
+
try {
|
|
116
|
+
const r = M.mixedDiscover({ space: { dims }, oracle, budget, goal, seed: (body.seed | 0) || 1 });
|
|
117
|
+
return json(res, 200, { best: r.best, bestCombo: r.bestCombo, byCombo: r.byCombo.slice(0, 12), evaluations: r.evaluations, comboCount: r.comboCount, sampledCombos: r.sampledCombos, goal });
|
|
118
|
+
} catch (e) { return json(res, 400, { error: "mixed failed: " + e.message.slice(0, 120) }); }
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// π PROVENANCE β demo the O(1) tamper-evident audit trail: build a checkpoint over `count` synthetic
|
|
122
|
+
// events, sign it, and prove (a) the snapshot is bounded and (b) altering any past event is detected.
|
|
123
|
+
if (req.method === "POST" && path === "/provenance") {
|
|
124
|
+
const body = await readBody(req); if (!body) return json(res, 400, { error: "invalid JSON" });
|
|
125
|
+
const count = Math.max(1, Math.min(200000, (body.count | 0) || 5000));
|
|
126
|
+
const windowSize = Math.max(1, Math.min(500, (body.windowSize | 0) || 50));
|
|
127
|
+
try {
|
|
128
|
+
const events = []; for (let i = 0; i < count; i++) events.push({ kind: i % 3 === 0 ? "decision" : "experiment", payload: { i, x: (i * 7) % 100 } });
|
|
129
|
+
const cp = M.signCheckpoint(M.buildCheckpoint(events, windowSize));
|
|
130
|
+
const sizeBytes = M.checkpointSize(cp);
|
|
131
|
+
const sigValid = M.verifyCheckpointSignature(cp).ok;
|
|
132
|
+
const intact = M.verifyAgainst(cp, events).ok;
|
|
133
|
+
// tamper an old event and show it's caught
|
|
134
|
+
const tampered = events.slice(); const pos = Math.floor(count / 2); tampered[pos] = { kind: tampered[pos].kind, payload: { i: pos, x: 999999 } };
|
|
135
|
+
const tamperDetected = !M.verifyAgainst(cp, tampered).ok;
|
|
136
|
+
return json(res, 200, { count: cp.count, windowSize, sizeBytes, foldedRoot: cp.foldedRoot, signatureValid: sigValid, intactVerifies: intact, tamperDetected, algo: cp.algo });
|
|
137
|
+
} catch (e) { return json(res, 400, { error: "provenance failed: " + e.message.slice(0, 120) }); }
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (req.method === "POST" && path === "/discover") {
|
|
141
|
+
const body = await readBody(req); if (!body) return json(res, 400, { error: "invalid JSON" });
|
|
142
|
+
// VERTICAL live-demo: load the domain-shaped (simulated) objective + space + goal from the gallery
|
|
143
|
+
const vert = (typeof body.vertical === "string" && M.VERTICALS && M.VERTICALS[body.vertical]) ? M.VERTICALS[body.vertical] : null;
|
|
144
|
+
if (vert) { body.space = vert.space.dims; body.objective = vert.objective; body.goal = vert.goal; if (!body.budget) body.budget = 50; }
|
|
145
|
+
const space = { dims: Array.isArray(body.space) ? body.space : body.space?.dims };
|
|
146
|
+
if (!space.dims?.length) return json(res, 400, { error: "space must be a non-empty array of {name,type,min,max}" });
|
|
147
|
+
if (space.dims.length > 12) return json(res, 400, { error: "demo limit: β€12 dimensions" });
|
|
148
|
+
if (typeof body.objective !== "string" || !body.objective.trim()) return json(res, 400, { error: "objective must be a JS expression string in your dimension names" });
|
|
149
|
+
const budget = Math.max(2, Math.min(MAX_BUDGET, (body.budget | 0) || 40));
|
|
150
|
+
let oracle; try { oracle = makeOracle(space, body.objective); oracle(Object.fromEntries(space.dims.map((d) => [d.name, (d.min + d.max) / 2]))); } catch (e) { return json(res, 400, { error: "objective failed to evaluate: " + e.message.slice(0, 120) }); }
|
|
151
|
+
const goal = body.goal === "minimize" ? "minimize" : "maximize";
|
|
152
|
+
const sig = await M.discoverSigned({ space, oracle, budget, seed: (body.seed | 0) || 1, goal, engine: ["portfolio", "bayes", "resonance"].includes(body.engine) ? body.engine : "portfolio" });
|
|
153
|
+
// Discovery Map: for a 2-D problem, sample the learned surface on a grid so the client can show
|
|
154
|
+
// WHERE the brain searched and WHY β the visual "story" of the discovery.
|
|
155
|
+
let surface = null;
|
|
156
|
+
if (space.dims.length === 2) {
|
|
157
|
+
const [dx, dy] = space.dims; const N = 44; const z = [];
|
|
158
|
+
for (let j = 0; j < N; j++) for (let i = 0; i < N; i++) { const e = { [dx.name]: dx.min + (dx.max - dx.min) * (i / (N - 1)), [dy.name]: dy.min + (dy.max - dy.min) * (j / (N - 1)) }; let v = oracle(e); if (!Number.isFinite(v)) v = 0; z.push(v); }
|
|
159
|
+
surface = { nx: N, ny: N, xName: dx.name, yName: dy.name, xMin: dx.min, xMax: dx.max, yMin: dy.min, yMax: dy.max, z };
|
|
160
|
+
}
|
|
161
|
+
// per-experiment path WITH the strategy (arm) that proposed each β lets the client colour the
|
|
162
|
+
// discovery by strategy and replay it step by step.
|
|
163
|
+
const path = (sig.result.history || []).map((s) => ({ experiment: s.experiment, value: s.value, n: s.n, arm: (String(s.rationale || "").match(/^\[([^\]]+)\]/) || [, "seed"])[1] }));
|
|
164
|
+
const dims = space.dims.map((d) => ({ name: d.name, min: d.min, max: d.max, type: d.type }));
|
|
165
|
+
// FRONTIER: "should you have run more, or was this the practical best?" β decision support from the
|
|
166
|
+
// run's own diminishing-returns curve (honest; no fabricated $ unless the client supplies a cost).
|
|
167
|
+
const frontierObs = (sig.result.history || []).map((st) => ({ experiment: st.experiment, value: st.value }));
|
|
168
|
+
// RELIABLE MODE (opt-in): a NelderβMead memetic polish on the global best β the local exploiter that
|
|
169
|
+
// lifts hard curved valleys (Rosenbrock 59%β100%). Deterministic; the signed trace covers the global
|
|
170
|
+
// search, the polish is a reported refinement on top.
|
|
171
|
+
let best = sig.result.best; let extraEvals = 0; const reliable = !!body.reliable;
|
|
172
|
+
if (reliable) {
|
|
173
|
+
const localBudget = Math.max(20, Math.round(budget * 0.6));
|
|
174
|
+
const pol = M.polish(space, oracle, best.experiment, localBudget, goal); extraEvals = localBudget;
|
|
175
|
+
const improved = goal === "minimize" ? pol.value < best.value : pol.value > best.value;
|
|
176
|
+
if (improved) best = { experiment: pol.experiment, value: pol.value };
|
|
177
|
+
frontierObs.push({ experiment: best.experiment, value: best.value });
|
|
178
|
+
}
|
|
179
|
+
const cost = (typeof body.costPerExperiment === "number" && body.costPerExperiment > 0) ? body.costPerExperiment : null;
|
|
180
|
+
const frontier = M.stoppingAdvice(frontierObs, goal, cost);
|
|
181
|
+
// OPTIMALITY CERTIFICATE: a provable "within X% of the best possible" under a data-estimated Lipschitz bound.
|
|
182
|
+
const certificate = M.certifyOptimality(frontierObs, space, goal);
|
|
183
|
+
const totalEvals = sig.result.evaluations + extraEvals;
|
|
184
|
+
// BASELINE β a raw score means nothing without a reference. Compare Melete's best against (a) where you
|
|
185
|
+
// started and (b) a plain random search on the SAME budget, so the number becomes "X% better than random".
|
|
186
|
+
const startVal = frontierObs.length ? frontierObs[0].value : best.value;
|
|
187
|
+
const rng = M.lcg(987654321);
|
|
188
|
+
let randomBest = goal === "minimize" ? Infinity : -Infinity;
|
|
189
|
+
for (let i = 0; i < totalEvals; i++) { const e = {}; for (const dd of space.dims) { const lo2 = dd.min ?? 0, hi2 = dd.max ?? 1; let v = lo2 + (hi2 - lo2) * rng(); if (dd.type === "int") v = Math.round(v); e[dd.name] = v; } const val = oracle(e); if (Number.isFinite(val) && (goal === "minimize" ? val < randomBest : val > randomBest)) randomBest = val; }
|
|
190
|
+
const baseline = { start: startVal, random: Number.isFinite(randomBest) ? randomBest : null, best: best.value, evaluations: totalEvals };
|
|
191
|
+
// PROOF OF OPTIMIZATION β a portable, offline-verifiable certificate fusing efficiency + optimality + provenance.
|
|
192
|
+
let poopt = null;
|
|
193
|
+
try {
|
|
194
|
+
const traceHash = createHash("sha256").update(JSON.stringify(sig.trace)).digest("hex");
|
|
195
|
+
poopt = M.issueProofOfOptimization({
|
|
196
|
+
subject: typeof body.subject === "string" ? body.subject.slice(0, 80) : "optimization",
|
|
197
|
+
goal, dims: space.dims.length, experimentsUsed: totalEvals, bestValue: best.value,
|
|
198
|
+
certifiedWithinPct: certificate ? certificate.withinPct : null, traceHash, issuedAtMs: Date.now(),
|
|
199
|
+
energyPerExperimentKwh: typeof body.energyPerExperimentKwh === "number" ? body.energyPerExperimentKwh : null,
|
|
200
|
+
carbonKgPerKwh: typeof body.carbonKgPerKwh === "number" ? body.carbonKgPerKwh : null,
|
|
201
|
+
});
|
|
202
|
+
} catch { poopt = null; }
|
|
203
|
+
// SENSITIVITY β per-variable process tolerance + robustness of the optimum (Taguchi-style).
|
|
204
|
+
let sensitivity = null; try { sensitivity = M.analyzeSensitivity(frontierObs, space, goal); } catch { sensitivity = null; }
|
|
205
|
+
// NOISE β measurement-reliability / replication advisor.
|
|
206
|
+
let noise = null; try { noise = M.analyzeNoise(frontierObs, space, goal); } catch { noise = null; }
|
|
207
|
+
// INTERACTIONS β which variables are coupled (cannot be tuned independently).
|
|
208
|
+
let interactions = null; try { interactions = M.analyzeInteractions(frontierObs, space, goal); } catch { interactions = null; }
|
|
209
|
+
let coverage = null; try { coverage = M.coverageScore(frontierObs, space); } catch { coverage = null; }
|
|
210
|
+
// DRIFT β is the improvement caused by your variables, or confounded with a time-trend (a hidden factor)?
|
|
211
|
+
let drift = null; try { drift = M.analyzeDrift(frontierObs, space, goal); } catch { drift = null; }
|
|
212
|
+
// EFFICIENCY Ξ· = β(GΒ·RΒ·T) β one honest number: real gain Γ robust optimum Γ trustworthy (not confounded).
|
|
213
|
+
let efficiency = null; try { efficiency = M.discoveryEfficiency(frontierObs, space, goal); } catch { efficiency = null; }
|
|
214
|
+
// PRESCRIPTION β the plain-language action card: what to DO with this result.
|
|
215
|
+
let prescription = null; try { prescription = M.buildPrescription(frontierObs, space, goal); } catch { prescription = null; }
|
|
216
|
+
// DISCOVERY BRAIN β the improvement-lineage tree (search drawn as converging roots)
|
|
217
|
+
let lineage = null; try { lineage = M.buildLineage(frontierObs, space, goal); } catch { lineage = null; }
|
|
218
|
+
// SLOPPINESS β how many combinations of variables actually matter (effective dimensionality)
|
|
219
|
+
let sloppiness = null; try { sloppiness = M.analyzeSloppiness(frontierObs, space, goal); } catch { sloppiness = null; }
|
|
220
|
+
// CLIFFS β tipping points where a small change collapses the result
|
|
221
|
+
let cliffs = null; try { cliffs = M.analyzeCliffs(frontierObs, space, goal); } catch { cliffs = null; }
|
|
222
|
+
// BREAKTHROUGH RADAR β surprising results (potential breakthroughs / anomalies)
|
|
223
|
+
let surprise = null; try { surprise = M.analyzeSurprise(frontierObs, space, goal); } catch { surprise = null; }
|
|
224
|
+
// RASHOMON β the family of genuinely different recipes that all score near-best
|
|
225
|
+
let rashomon = null; try { rashomon = M.analyzeRashomon(frontierObs, space, goal); } catch { rashomon = null; }
|
|
226
|
+
// SHAPE β the geometry of the optimum (peak / ridge / saddle / plateau / bowl)
|
|
227
|
+
let shape = null; try { shape = M.analyzeShape(frontierObs, space, goal); } catch { shape = null; }
|
|
228
|
+
// β MELETE PRIME β the Red Diamond: the unified brain that composes every lens into one decision
|
|
229
|
+
let prime = null; try { prime = M.meletePrime(frontierObs, space, goal); } catch { prime = null; }
|
|
230
|
+
// π SOVEREIGN β the ecosystem verdict: 4 layers + an Ed25519 PROVENANCE certificate, offline-verifiable
|
|
231
|
+
let sovereign = null; try { sovereign = M.sovereignAnalyze(frontierObs, space, goal, { issuedAtMs: 0 }); } catch { sovereign = null; }
|
|
232
|
+
// βͺ REPLAY TOKEN β deterministic, signed, offline step-by-step replay of this analysis (audit/compliance)
|
|
233
|
+
let replayToken = null; try { replayToken = M.issueReplayToken(frontierObs, space, goal, { issuedAtMs: 0 }); } catch { replayToken = null; }
|
|
234
|
+
// π‘ AEGIS β the self-aware engine: the best ROBUST optimum (survives wobble) vs the raw peak
|
|
235
|
+
let aegis = null; try { const a = M.aegisDiscover({ space, oracle, budget: Math.min(60, Math.max(24, totalEvals)), goal, seed: (body.seed | 0) || 1, robustWeight: 0.65 }); aegis = { best: a.best, rawBest: a.rawBest, robustnessOfBest: a.robustnessOfBest, tradedHeight: a.tradedHeight }; } catch { aegis = null; }
|
|
236
|
+
// expose the space + a capped sample of observations so the browser can run the WHAT-IF twin (/predict)
|
|
237
|
+
const obsOut = (frontierObs || []).slice(0, 200).map((o) => ({ experiment: o.experiment, value: o.value }));
|
|
238
|
+
// π‘ AI JOURNALIST β Sci-Fi command-center narration of THIS real run (only real numbers), for the vertical gallery
|
|
239
|
+
let narration = null; if (vert) { try { narration = M.narrate(body.vertical, { best, evaluations: totalEvals, vsStartPct: prescription ? prescription.vsStartPct : undefined, verdictHash: sovereign ? sovereign.certify.payloadHash : undefined, robust: !!(aegis && aegis.robustnessOfBest > 0.5) }); } catch { narration = null; } }
|
|
240
|
+
const vertical = vert ? { key: vert.key, emoji: vert.emoji, title: vert.title, sector: vert.sector, knobsCopy: vert.knobsCopy, scoreCopy: vert.scoreCopy, scoreName: vert.scoreName, scoreUnit: vert.scoreUnit, realWorld: vert.realWorld } : null;
|
|
241
|
+
return json(res, 200, { best, evaluations: totalEvals, converged: sig.result.converged, engine: sig.engine, reliable, goal, dims, space: space.dims, observations: obsOut, armStats: sig.result.armStats ?? null, surface, path, frontier, certificate, baseline, poopt, sensitivity, noise, interactions, coverage, drift, efficiency, prescription, lineage, sloppiness, cliffs, surprise, rashomon, shape, aegis, prime, sovereign, replayToken, vertical, narration, trace: sig.trace, verify: M.verifyTrace(sig.trace).ok });
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (req.method === "POST" && path === "/next") {
|
|
245
|
+
const body = await readBody(req); if (!body) return json(res, 400, { error: "invalid JSON" });
|
|
246
|
+
const space = { dims: Array.isArray(body.space) ? body.space : body.space?.dims };
|
|
247
|
+
if (!space.dims?.length) return json(res, 400, { error: "space must be a non-empty array of {name,type,min,max}" });
|
|
248
|
+
if (space.dims.length > 12) return json(res, 400, { error: "demo limit: β€12 dimensions" });
|
|
249
|
+
const obs = Array.isArray(body.observations) ? body.observations.filter((o) => o && o.experiment && Number.isFinite(+o.value)).map((o) => ({ experiment: o.experiment, value: +o.value })) : [];
|
|
250
|
+
const goal = body.goal === "minimize" ? "minimize" : "maximize";
|
|
251
|
+
try {
|
|
252
|
+
const next = M.proposeNext(space, obs, goal, (body.seed | 0) || 1);
|
|
253
|
+
const best = obs.length ? obs.reduce((a, b) => (goal === "minimize" ? (b.value < a.value ? b : a) : (b.value > a.value ? b : a))) : null;
|
|
254
|
+
const cost = (typeof body.costPerExperiment === "number" && body.costPerExperiment > 0) ? body.costPerExperiment : null;
|
|
255
|
+
const advice = M.stoppingAdvice(obs, goal, cost);
|
|
256
|
+
const territory = M.assessTerritory(next, obs, space);
|
|
257
|
+
const confidence = M.stopConfidence(obs, goal);
|
|
258
|
+
// ACHIEVABILITY β if the user named a target, is it even reachable with these variables?
|
|
259
|
+
let achievability = null, inverse = null;
|
|
260
|
+
if (typeof body.target === "number" && Number.isFinite(body.target)) {
|
|
261
|
+
try { achievability = M.assessAchievability(obs, space, body.target, goal); } catch { achievability = null; }
|
|
262
|
+
// INVERSE DESIGN β the recipes that hit the target (needs a few measurements first)
|
|
263
|
+
if (obs.length >= 5) { try { inverse = M.inverseDesign(obs, space, body.target); } catch { inverse = null; } }
|
|
264
|
+
}
|
|
265
|
+
return json(res, 200, { next, t: obs.length, best, goal, advice, territory, confidence, achievability, inverse });
|
|
266
|
+
} catch (e) { return json(res, 400, { error: "propose failed: " + e.message.slice(0, 120) }); }
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// INVERSE DESIGN β "find the recipes that hit my target value" (the inverse of optimization)
|
|
270
|
+
if (req.method === "POST" && path === "/inverse") {
|
|
271
|
+
const body = await readBody(req); if (!body) return json(res, 400, { error: "invalid JSON" });
|
|
272
|
+
const space = { dims: Array.isArray(body.space) ? body.space : body.space?.dims };
|
|
273
|
+
if (!space.dims?.length) return json(res, 400, { error: "space must be a non-empty array of {name,type,min,max}" });
|
|
274
|
+
if (space.dims.length > 12) return json(res, 400, { error: "demo limit: β€12 dimensions" });
|
|
275
|
+
if (typeof body.target !== "number" || !Number.isFinite(body.target)) return json(res, 400, { error: "target must be a finite number" });
|
|
276
|
+
const obs = Array.isArray(body.observations) ? body.observations.filter((o) => o && o.experiment && Number.isFinite(+o.value)).map((o) => ({ experiment: o.experiment, value: +o.value })) : [];
|
|
277
|
+
try { return json(res, 200, M.inverseDesign(obs, space, body.target)); }
|
|
278
|
+
catch (e) { return json(res, 400, { error: "inverse failed: " + e.message.slice(0, 120) }); }
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// SAFE OPTIMIZATION β best setting within constraints + safety margins, and a safe next proposal
|
|
282
|
+
if (req.method === "POST" && path === "/safe") {
|
|
283
|
+
const body = await readBody(req); if (!body) return json(res, 400, { error: "invalid JSON" });
|
|
284
|
+
const space = { dims: Array.isArray(body.space) ? body.space : body.space?.dims };
|
|
285
|
+
if (!space.dims?.length) return json(res, 400, { error: "space must be a non-empty array of {name,type,min,max}" });
|
|
286
|
+
const cons = Array.isArray(body.constraints) ? body.constraints.filter((c) => c && c.name) : [];
|
|
287
|
+
const obs = Array.isArray(body.observations) ? body.observations.filter((o) => o && o.experiment && Number.isFinite(+o.value)).map((o) => ({ experiment: o.experiment, value: +o.value, metrics: (o.metrics && typeof o.metrics === "object") ? o.metrics : undefined })) : [];
|
|
288
|
+
const goal = body.goal === "minimize" ? "minimize" : "maximize";
|
|
289
|
+
try { const report = M.bestFeasible(obs, goal, cons); const nextSafe = M.proposeNextSafe(space, obs, goal, cons, (body.seed | 0) || 1); return json(res, 200, { ...report, nextSafe }); }
|
|
290
|
+
catch (e) { return json(res, 400, { error: "safe failed: " + e.message.slice(0, 120) }); }
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// WHAT-IF TWIN β "what score would I get at THIS setting?" (predict without running it)
|
|
294
|
+
if (req.method === "POST" && path === "/predict") {
|
|
295
|
+
const body = await readBody(req); if (!body) return json(res, 400, { error: "invalid JSON" });
|
|
296
|
+
const space = { dims: Array.isArray(body.space) ? body.space : body.space?.dims };
|
|
297
|
+
if (!space.dims?.length) return json(res, 400, { error: "space must be a non-empty array of {name,type,min,max}" });
|
|
298
|
+
const obs = Array.isArray(body.observations) ? body.observations.filter((o) => o && o.experiment && Number.isFinite(+o.value)).map((o) => ({ experiment: o.experiment, value: +o.value })) : [];
|
|
299
|
+
if (!body.query || typeof body.query !== "object") return json(res, 400, { error: "query must be a {name:value} setting object" });
|
|
300
|
+
try { return json(res, 200, M.predictAt(obs, space, body.query)); }
|
|
301
|
+
catch (e) { return json(res, 400, { error: "predict failed: " + e.message.slice(0, 120) }); }
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// BATCH PLANNER β "give me the k best experiments to run in PARALLEL this round"
|
|
305
|
+
if (req.method === "POST" && path === "/batch") {
|
|
306
|
+
const body = await readBody(req); if (!body) return json(res, 400, { error: "invalid JSON" });
|
|
307
|
+
const space = { dims: Array.isArray(body.space) ? body.space : body.space?.dims };
|
|
308
|
+
if (!space.dims?.length) return json(res, 400, { error: "space must be a non-empty array of {name,type,min,max}" });
|
|
309
|
+
if (space.dims.length > 12) return json(res, 400, { error: "demo limit: β€12 dimensions" });
|
|
310
|
+
const obs = Array.isArray(body.observations) ? body.observations.filter((o) => o && o.experiment && Number.isFinite(+o.value)).map((o) => ({ experiment: o.experiment, value: +o.value })) : [];
|
|
311
|
+
const goal = body.goal === "minimize" ? "minimize" : "maximize";
|
|
312
|
+
const k = Math.max(1, Math.min(16, (body.k | 0) || 4));
|
|
313
|
+
try { return json(res, 200, { batch: M.proposeBatch(space, obs, goal, k, (body.seed | 0) || 1), k, t: obs.length, goal }); }
|
|
314
|
+
catch (e) { return json(res, 400, { error: "batch failed: " + e.message.slice(0, 120) }); }
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (req.method === "POST" && path === "/next-multi") {
|
|
318
|
+
const body = await readBody(req); if (!body) return json(res, 400, { error: "invalid JSON" });
|
|
319
|
+
const space = { dims: Array.isArray(body.space) ? body.space : body.space?.dims };
|
|
320
|
+
if (!space.dims?.length) return json(res, 400, { error: "space must be a non-empty array of {name,type,min,max}" });
|
|
321
|
+
if (space.dims.length > 12) return json(res, 400, { error: "demo limit: β€12 dimensions" });
|
|
322
|
+
const goals = Array.isArray(body.goals) ? body.goals.map((g) => ({ name: g?.name, goal: g?.goal === "minimize" ? "minimize" : "maximize" })) : null;
|
|
323
|
+
if (!goals || !goals.length) return json(res, 400, { error: "goals must be a non-empty array of {goal:'maximize'|'minimize'} β one per objective" });
|
|
324
|
+
if (goals.length > 8) return json(res, 400, { error: "demo limit: β€8 objectives" });
|
|
325
|
+
const obs = Array.isArray(body.observations) ? body.observations.filter((o) => o && o.experiment && Array.isArray(o.values) && o.values.length === goals.length && o.values.every((v) => Number.isFinite(+v))).map((o) => ({ experiment: o.experiment, values: o.values.map(Number) })) : [];
|
|
326
|
+
try {
|
|
327
|
+
const next = M.proposeNextMulti(space, obs, goals, (body.seed | 0) || 1);
|
|
328
|
+
const pareto = M.paretoFront(obs, goals);
|
|
329
|
+
return json(res, 200, { next, t: obs.length, goals, paretoFront: pareto, paretoSize: pareto.length });
|
|
330
|
+
} catch (e) { return json(res, 400, { error: "propose failed: " + e.message.slice(0, 120) }); }
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (req.method === "POST" && path === "/verify") {
|
|
334
|
+
const body = await readBody(req); if (!body) return json(res, 400, { error: "invalid JSON" });
|
|
335
|
+
const v = M.verifyTrace(body.trace || body); return json(res, 200, v);
|
|
336
|
+
}
|
|
337
|
+
if (req.method === "POST" && path === "/poopt/verify") {
|
|
338
|
+
const body = await readBody(req); if (!body) return json(res, 400, { error: "invalid JSON" });
|
|
339
|
+
const cert = body.poopt || body; const v = M.verifyProofOfOptimization(cert);
|
|
340
|
+
return json(res, 200, { ...v, subject: cert?.subject ?? null, efficiencyPct: cert?.efficiencyPct ?? null, experimentsSaved: cert?.experimentsSaved ?? null, co2SavedKg: cert?.co2SavedKg ?? null });
|
|
341
|
+
}
|
|
342
|
+
json(res, 404, { error: "no such endpoint", path, endpoints: M.ENDPOINTS });
|
|
343
|
+
} catch (e) { json(res, 500, { error: e.message }); }
|
|
344
|
+
});
|
|
345
|
+
server.listen(PORT, HOST, () => process.stdout.write(`π Melete discovery-as-a-service on http://${HOST}:${PORT} (max budget ${MAX_BUDGET})\n`));
|
package/bin/melete.mjs
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* melete β the Self-Driving Discovery Brain CLI.
|
|
4
|
+
* melete bench prove the brain beats random/grid (measured)
|
|
5
|
+
* melete gauntlet run every module's correctness gauntlet (must be 100)
|
|
6
|
+
* melete discover [opts] run a closed-loop discovery + write a signed discovery trace
|
|
7
|
+
* melete verify <trace.json> re-verify a discovery trace OFFLINE (signatures + hash chain)
|
|
8
|
+
*
|
|
9
|
+
* discover options:
|
|
10
|
+
* --demo use the built-in 2D benchmark surface as the oracle
|
|
11
|
+
* --objective "<js: x,y -> number>" custom objective, e.g. --objective "-(x-3)**2-(y+1)**2"
|
|
12
|
+
* --space '<json>' [{name,type,min,max}] (default: x,y in [0,10])
|
|
13
|
+
* --budget N --seed N --goal maximize|minimize --engine bayes|resonance
|
|
14
|
+
* --target N stop early once reached
|
|
15
|
+
* --out trace.json write the signed trace (default: ./melete-trace.json)
|
|
16
|
+
*/
|
|
17
|
+
import { writeFileSync, readFileSync } from "node:fs";
|
|
18
|
+
import { createContext, runInContext } from "node:vm";
|
|
19
|
+
import * as M from "../dist/index.js";
|
|
20
|
+
|
|
21
|
+
const argv = process.argv.slice(2);
|
|
22
|
+
const cmd = argv[0];
|
|
23
|
+
const flag = (n, d) => { const i = argv.indexOf("--" + n); return i >= 0 ? (argv[i + 1] && !argv[i + 1].startsWith("--") ? argv[i + 1] : true) : d; };
|
|
24
|
+
const out = (s) => process.stdout.write(s + "\n");
|
|
25
|
+
|
|
26
|
+
async function main() {
|
|
27
|
+
if (cmd === "gauntlet") {
|
|
28
|
+
const g = await M.meleteGauntlet();
|
|
29
|
+
out(`\nπ§ͺ MELETE GAUNTLET: ${g.score}/100\n`);
|
|
30
|
+
for (const m of g.modules) { out(` ${m.score === 100 ? "β
" : "β"} ${m.name.padEnd(10)} ${m.score}/100`); for (const c of m.checks) if (!c.pass) out(` β ${c.name}`); }
|
|
31
|
+
process.exit(g.score === 100 ? 0 : 1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (cmd === "bench" && flag("robust")) {
|
|
35
|
+
out(`\nπ SUPER NOVA robustness β portfolio vs each single arm, mean best across landscapes (higher = better):\n`);
|
|
36
|
+
const rows = await M.robustnessBench(+(flag("seeds", 6)));
|
|
37
|
+
out(` landscape PORTFOLIO kernel-ucb cmaes resonance random`);
|
|
38
|
+
for (const r of rows) {
|
|
39
|
+
const f = (v) => v.toFixed(3).padStart(9);
|
|
40
|
+
out(` ${r.landscape.padEnd(13)} ${f(r.portfolio)}${r.portfolioIsBest ? " π" : " "} ${f(r.kernelUcb)} ${f(r.cmaes)} ${f(r.resonance)} ${f(r.random)}`);
|
|
41
|
+
}
|
|
42
|
+
out(`\n β the portfolio is never the worst, and on the rugged landscape the ensemble beats every single algorithm.`);
|
|
43
|
+
out(` No-Free-Lunch made productive: one engine that adapts to the problem instead of being re-tuned per problem.`);
|
|
44
|
+
process.exit(0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (cmd === "bench") {
|
|
48
|
+
const budget = +(flag("budget", 150)), target = +(flag("target", 0.99)), seeds = +(flag("seeds", 30));
|
|
49
|
+
out(`\nβοΈ Discovery benchmark β experiments to reach ${target} of the optimum (lower = better):\n`);
|
|
50
|
+
const sd = await M.resonanceVsBayes({ budget, target, seeds });
|
|
51
|
+
const row = (n, v) => out(` ${n.padEnd(22)} ${v == null ? "did not reach within " + budget : v + " experiments"}`);
|
|
52
|
+
row("BRAIN (bayes core)", sd.bayes); row("random search (avg)", sd.random); row("systematic grid", sd.grid); row("resonance (experimental)", sd.resonance);
|
|
53
|
+
if (sd.bayes && sd.random) out(`\n β the brain is ${(sd.random / sd.bayes).toFixed(1)}Γ more sample-efficient than random. Each saved experiment = saved reagents / robot-time / money.`);
|
|
54
|
+
out(` honest: measured on a smooth multimodal surface; the resonance engine is experimental and currently does not beat the core.`);
|
|
55
|
+
process.exit(0);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (cmd === "discover") {
|
|
59
|
+
const space = flag("space") ? JSON.parse(flag("space")) : { dims: [{ name: "x", type: "real", min: 0, max: 10 }, { name: "y", type: "real", min: 0, max: 10 }] };
|
|
60
|
+
let oracle;
|
|
61
|
+
const obj = flag("objective");
|
|
62
|
+
if (obj && obj !== true) { const ctx = createContext({ Math }); oracle = (e) => { for (const k of Object.keys(e)) ctx[k] = e[k]; return Number(runInContext(obj, ctx, { timeout: 200 })); }; }
|
|
63
|
+
else oracle = (e) => M.multimodal(e); // --demo / default
|
|
64
|
+
const budget = +(flag("budget", 60)), seed = +(flag("seed", 1));
|
|
65
|
+
const goal = flag("goal", "maximize"), engine = flag("engine", "portfolio");
|
|
66
|
+
const target = flag("target") ? +flag("target") : undefined;
|
|
67
|
+
out(`\nπ¬ Discovering (${engine} engine, ${goal}, budget ${budget})β¦`);
|
|
68
|
+
const sig = await M.discoverSigned({ space, oracle, budget, seed, goal, engine, target });
|
|
69
|
+
out(` best value: ${sig.result.best.value.toFixed(6)}`);
|
|
70
|
+
out(` at: ${JSON.stringify(sig.result.best.experiment)}`);
|
|
71
|
+
out(` experiments: ${sig.result.evaluations} converged: ${sig.result.converged}`);
|
|
72
|
+
const file = flag("out", "melete-trace.json");
|
|
73
|
+
writeFileSync(file, JSON.stringify(sig.trace, null, 2));
|
|
74
|
+
out(`\n π signed discovery trace β ${file} (${sig.trace.frames.length} frames)`);
|
|
75
|
+
out(` verify it offline: melete verify ${file}`);
|
|
76
|
+
process.exit(0);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (cmd === "tune") {
|
|
80
|
+
// melete tune --cmd "node train.js --lr {lr} --depth {depth}" --space '[...]' [--budget N] [--goal min]
|
|
81
|
+
const space = flag("space") ? JSON.parse(flag("space")) : null;
|
|
82
|
+
const cmdTpl = flag("cmd");
|
|
83
|
+
if (!space || !Array.isArray(space) && !space.dims || typeof cmdTpl !== "string") { out('usage: melete tune --cmd "your-prog --a {a} --b {b}" --space \'[{"name":"a","type":"real","min":0,"max":1}]\' [--budget N] [--goal minimize]\n {dim} placeholders are filled with each proposed value; the LAST number your command prints is the score. No dataset needed.'); process.exit(2); }
|
|
84
|
+
const dims = Array.isArray(space) ? space : space.dims;
|
|
85
|
+
const { execSync } = await import("node:child_process");
|
|
86
|
+
const oracle = (e) => { const c = cmdTpl.replace(/\{(\w+)\}/g, (_, k) => String(e[k])); const sresult = String(execSync(c, { encoding: "utf8", timeout: 600000, stdio: ["ignore", "pipe", "ignore"] })); const v = Number((sresult.match(/-?\d+(?:\.\d+)?(?:[eE][-+]?\d+)?/g) ?? []).at(-1)); if (!Number.isFinite(v)) throw new Error("command printed no number"); return v; };
|
|
87
|
+
const budget = +(flag("budget", 30)), goal = flag("goal", "maximize");
|
|
88
|
+
out(`\nπ§ Tuning via your command (${goal}, budget ${budget}) β running it ${budget}Γ to find the best paramsβ¦`);
|
|
89
|
+
const sig = await M.discoverSigned({ space: { dims }, oracle, budget, seed: (+flag("seed", 1)) || 1, goal, engine: "portfolio" });
|
|
90
|
+
out(` best params: ${JSON.stringify(sig.result.best.experiment)}`);
|
|
91
|
+
out(` best score: ${sig.result.best.value}`);
|
|
92
|
+
out(` ran your command ${sig.result.evaluations}Γ Β· arms: ${(sig.result.armStats || []).filter(a => a.pulls).map(a => a.name + "Γ" + a.pulls).join(" ")}`);
|
|
93
|
+
const file = flag("out", "melete-trace.json"); writeFileSync(file, JSON.stringify(sig.trace, null, 2));
|
|
94
|
+
out(` π signed trace β ${file} Β· verify: melete verify ${file}`);
|
|
95
|
+
process.exit(0);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (cmd === "replicate") {
|
|
99
|
+
// melete replicate --trace t.json (--cmd "prog --a {a}" | --objective "<js>") [--samples N] [--tol 1e-3]
|
|
100
|
+
const tf = argv[1] && !argv[1].startsWith("--") ? argv[1] : flag("trace");
|
|
101
|
+
if (!tf) { out('usage: melete replicate <trace.json> --cmd "your-prog --a {a}" (or --objective "<js>")\n re-runs the discovery\'s best + a sample of its path to certify it REPLICATES β cheap cross-agent trust.'); process.exit(2); }
|
|
102
|
+
const trace = JSON.parse(readFileSync(tf, "utf8"));
|
|
103
|
+
const claim = M.extractClaim(trace);
|
|
104
|
+
let oracle;
|
|
105
|
+
if (flag("cmd")) { const { execSync } = await import("node:child_process"); const tpl = flag("cmd"); oracle = (e) => { const c = tpl.replace(/\{(\w+)\}/g, (_, k) => String(e[k])); const s = String(execSync(c, { encoding: "utf8", timeout: 600000, stdio: ["ignore", "pipe", "ignore"] })); return Number((s.match(/-?\d+(?:\.\d+)?(?:[eE][-+]?\d+)?/g) ?? []).at(-1)); }; }
|
|
106
|
+
else if (flag("objective") && flag("objective") !== true) { const obj = flag("objective"); const ctx = createContext({ Math }); oracle = (e) => { for (const k of Object.keys(e)) ctx[k] = e[k]; return Number(runInContext(obj, ctx, { timeout: 200 })); }; }
|
|
107
|
+
else { out("provide how to re-score: --cmd \"<command with {dims}>\" or --objective \"<js expression>\""); process.exit(2); }
|
|
108
|
+
out(`\nπ Replicating a published discovery (re-running its best + sampled points)β¦`);
|
|
109
|
+
const report = await M.replicate({ claim, oracle, samples: +(flag("samples", 3)), tolerance: +(flag("tol", 1e-3)) });
|
|
110
|
+
out(` ${report.replicates ? "β
REPLICATES" : "β DOES NOT REPLICATE"}`);
|
|
111
|
+
out(` best: claimed ${report.best.claimed} Β· re-scored ${report.best.measured} Β· ${report.best.match ? "match" : "MISMATCH"}`);
|
|
112
|
+
for (const s of report.samples) out(` Β· ${JSON.stringify(s.experiment)} claimed ${s.claimed} re-scored ${s.measured} ${s.match ? "β" : "β"}`);
|
|
113
|
+
out(` ${report.reEvaluations} re-evaluations verified a ${claim.path.length}-experiment discovery (cross-agent trust, ${(claim.path.length / Math.max(1, report.reEvaluations)).toFixed(0)}Γ cheaper than re-running it).`);
|
|
114
|
+
const cert = M.certifyReplication(report); const cf = flag("out", "replication-cert.json"); writeFileSync(cf, JSON.stringify(cert, null, 2));
|
|
115
|
+
out(` π signed replication certificate β ${cf} Β· verify: melete verify ${cf}`);
|
|
116
|
+
process.exit(report.replicates ? 0 : 2);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (cmd === "verify") {
|
|
120
|
+
const path = argv[1]; if (!path) { out("usage: melete verify <trace.json>"); process.exit(2); }
|
|
121
|
+
const trace = JSON.parse(readFileSync(path, "utf8"));
|
|
122
|
+
const v = M.verifyTrace(trace);
|
|
123
|
+
out(`\nπ ${v.ok ? "β
VALID" : "β INVALID"} discovery trace β ${v.frames} frames`);
|
|
124
|
+
out(` ${v.reason}`);
|
|
125
|
+
if (!v.ok && v.brokenAt != null) out(` broken at frame ${v.brokenAt}`);
|
|
126
|
+
out(` (verified OFFLINE with the embedded public key β no Melete, no network, no shared secret)`);
|
|
127
|
+
process.exit(v.ok ? 0 : 1);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (cmd === "multi") {
|
|
131
|
+
const goals = [{ name: "f1", goal: "maximize" }, { name: "f2", goal: "maximize" }];
|
|
132
|
+
const space = { dims: [{ name: "x", type: "real", min: 0, max: 10 }] };
|
|
133
|
+
const f = (x) => [-((x - 2) ** 2), -((x - 8) ** 2)]; // f1 peaks at x=2, f2 at x=8 β they trade off
|
|
134
|
+
const obs = [];
|
|
135
|
+
for (let i = 0; i < 40; i++) { const e = M.proposeNextMulti(space, obs, goals, 7); const v = f(e.x ?? 0); obs.push({ experiment: e, values: v }); }
|
|
136
|
+
const front = M.paretoFront(obs, goals).sort((a, b) => (a.experiment.x ?? 0) - (b.experiment.x ?? 0));
|
|
137
|
+
out("\n𧬠Multi-objective demo β two goals that trade off (f1 peaks at x=2, f2 at x=8)");
|
|
138
|
+
out(` Pareto front: ${front.length} non-dominated trade-offs`);
|
|
139
|
+
for (const o of front) out(` x=${(o.experiment.x ?? 0).toFixed(2)} f1=${o.values[0].toFixed(2)} f2=${o.values[1].toFixed(2)}`);
|
|
140
|
+
out(" (real use: POST /next-multi with YOUR N objectives β Melete proposes, you measure each)");
|
|
141
|
+
process.exit(0);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (cmd === "poopt") {
|
|
145
|
+
const path = argv[1]; if (!path) { out("usage: melete poopt <certificate.json>"); process.exit(2); }
|
|
146
|
+
const cert = JSON.parse(readFileSync(path, "utf8"));
|
|
147
|
+
const v = M.verifyProofOfOptimization(cert.poopt || cert);
|
|
148
|
+
out(`\nπ ${v.ok ? "β
VALID" : "β INVALID"} Proof of Optimization`);
|
|
149
|
+
out(` ${v.reason}`);
|
|
150
|
+
if (v.recomputed) out(` efficiency: ${v.recomputed.efficiencyPct}% (${v.recomputed.experimentsSaved} experiments saved vs a full grid sweep)`);
|
|
151
|
+
out(` (verified OFFLINE with the embedded public key β no Melete, no network)`);
|
|
152
|
+
process.exit(v.ok ? 0 : 1);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
out("melete β the Self-Driving Discovery Brain\n");
|
|
156
|
+
out(" melete tune --cmd \"prog --a {a}\" --space '[...]' tune ANY command/script (no dataset needed)");
|
|
157
|
+
out(" melete bench [--robust] prove the brain beats random/grid");
|
|
158
|
+
out(" melete gauntlet run all correctness gauntlets");
|
|
159
|
+
out(" melete discover --demo run a discovery + write a signed trace");
|
|
160
|
+
out(" melete multi multi-objective demo β print the Pareto front");
|
|
161
|
+
out(" melete verify <trace.json> re-verify a discovery trace offline");
|
|
162
|
+
out(" melete poopt <cert.json> verify a Proof of Optimization offline");
|
|
163
|
+
process.exit(cmd ? 1 : 0);
|
|
164
|
+
}
|
|
165
|
+
main().catch((e) => { out("error: " + e.message); process.exit(1); });
|