(toolLabel)
| 792 | // §21.8 -- the ATP runners hit the same vector via consumerAgent / |
| 793 | // merchantAgent / atpExecute paths). |
| 794 | function refuseHelloIfDaemonRunning(toolLabel) { |
| 795 | try { |
| 796 | const lockFile = getLockFilePath(); |
| 797 | if (!fs.existsSync(lockFile)) return; // no daemon |
| 798 | const payload = _readLockPayload(lockFile); |
| 799 | if (!payload || !Number.isFinite(payload.pid) || payload.pid <= 0) return; |
| 800 | if (payload.pid === process.pid) return; // shouldn't happen for CLI |
| 801 | // Round-9: a lease-aware lock whose mtime has gone stale means the |
| 802 | // daemon is dead (or its PID was reused). Do NOT refuse on it -- that |
| 803 | // was the "CLI hard-exits because it trusts a recyclable PID" hole. |
| 804 | if (_lockIsStaleByLease(lockFile, payload)) return; |
| 805 | try { |
| 806 | process.kill(payload.pid, 0); |
| 807 | } catch (e) { |
| 808 | if (e && e.code === 'ESRCH') return; // stale lock, daemon is gone |
| 809 | // EPERM = alive under a different user; still a real daemon. Fall |
| 810 | // through to refuse. |
| 811 | } |
| 812 | console.error( |
| 813 | '[' + toolLabel + '] Refusing to send hello: an evolver daemon ' + |
| 814 | '(PID ' + payload.pid + ') is running and owns ~/.evomap/instance.lock.' |
| 815 | ); |
| 816 | console.error( |
| 817 | ' Two concurrent hello calls would rotate node_secret against ' + |
| 818 | 'each other and silence the daemon for hours.' |
| 819 | ); |
| 820 | console.error( |
| 821 | ' Either wait for the daemon to register (the secret will ' + |
| 822 | 'appear at ~/.evomap/node_secret), or stop the daemon and retry.' |
| 823 | ); |
| 824 | process.exit(1); |
| 825 | } catch (_) { |
| 826 | // Never let the lock-check helper itself escape; if the helper |
| 827 | // throws (FS permission, etc.) we fall through to the original code |
| 828 | // path. The race we're protecting against is rare; failing closed |
| 829 | // here would block legitimate CLI use. |
| 830 | } |
| 831 | } |
| 832 | |
| 833 | async function main() { |
| 834 | const args = process.argv.slice(2); |
no test coverage detected