MCPcopy Create free account
hub / github.com/EvoMap/evolver / main

Function main

index.js:833–3649  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

831}
832
833async function main() {
834 const args = process.argv.slice(2);
835 const command = args[0];
836 // Solo mode (--solo): the "constrained wild" profile. Implies loop (a solo
837 // run IS a Mad Dog loop) but hard-cuts the network + ATP, snapshots the
838 // target repo each cycle and rolls back on failure, and circuit-breaks on
839 // repeated failures instead of blind-respawning. It is a NEW side path — the
840 // wild --mad-dog / controlled-daemon behavior below is untouched when isSolo
841 // is false.
842 const isSolo = args.includes('--solo');
843 const isLoop = args.includes('--loop') || args.includes('--mad-dog') || isSolo;
844 // Solo lockdown: hard-cut network + autonomous spend at the SOURCE, in-process,
845 // before any module reads these envs. The block-level `if (!isSolo)` gates
846 // below are belt-and-suspenders for the startup path; THIS is what also closes
847 // the in-cycle paths (src/evolve/guards.js starts autoBuyer/autoDeliver from
848 // inside evolve.run()) and the validator daemon (network + staked credits).
849 // These are overwrites, not defaults — a user cannot re-enable ATP/hub/validator
850 // under --solo by setting the env themselves. That is the "no escape valve" the
851 // boss pinned. Numeric knobs (e.g. EVOLVER_SOLO_MAX_FAILS) stay tunable; the
852 // four safety cuts do not.
853 if (isSolo) {
854 process.env.A2A_HUB_URL = '';
855 process.env.EVOMAP_HUB_URL = '';
856 process.env.EVOLVER_ATP = 'off'; // getAtpMode() → 'off'
857 process.env.EVOLVER_ATP_AUTOBUY = 'off'; // getConsent() → disabled (env wins over ack)
858 process.env.EVOLVER_ATP_AUTODELIVER = 'off';
859 process.env.EVOLVER_VALIDATOR_ENABLED = 'false';
860 process.env.EVOMAP_PROXY = '0';
861 }
862 const isVerbose = args.includes('--verbose') || args.includes('-v') ||
863 String(process.env.EVOLVER_VERBOSE || '').toLowerCase() === 'true';
864 if (isVerbose) process.env.EVOLVER_VERBOSE = 'true';
865
866 if (!command || command === 'run' || command === '/evolve' || isLoop) {
867 if (isLoop) {
868 // EPIPE protection. The daemon may outlive the controlling
869 // terminal (user closes the iTerm tab, ssh session drops, parent
870 // shell exits). The SIGHUP handler below covers the signal side,
871 // but the underlying pty fd is gone and the FIRST subsequent
872 // console.log writes to a closed pipe -> stdout emits 'error'
873 // with EPIPE. Without a listener attached, Node escalates EPIPE
874 // to uncaughtException, which our handler then turns into
875 // process.exit(1). Net result: daemon silently dies the next
876 // time it tries to log, with no useful trace. Swallow EPIPE
877 // explicitly so the daemon stays alive when its terminal goes
878 // away (matching standard daemonization practice).
879 try {
880 // EPIPE: swallow (daemon must outlive its controlling terminal).
881 // Non-EPIPE (EIO, ENOSPC on redirected log, etc.): the listener
882 // already prevents 'error' from escalating to uncaughtException,
883 // so write a one-line trace to the *other* stream so operators
884 // can see the failure mode instead of finding a silent daemon.
885 process.stdout.on('error', function (err) {
886 if (err && err.code === 'EPIPE') return;
887 try { process.stderr.write('[evolver] stdout error: ' + (err && (err.code || err.message) || err) + '\n'); } catch (_) {}
888 });
889 process.stderr.on('error', function (err) {
890 if (err && err.code === 'EPIPE') return;

Callers 1

index.jsFile · 0.70

Calls 15

tsFunction · 0.85
acquireLockFunction · 0.85
startLockRefreshFunction · 0.85
getEvolverLogPathFunction · 0.85
shutdownFunction · 0.85
_interruptAllSleepsFunction · 0.85
releaseLockFunction · 0.85
_heartbeatLooksAliveFunction · 0.85
getEvolutionDirFunction · 0.85
parseMsFunction · 0.85
parseBoolEnvFunction · 0.85

Tested by

no test coverage detected