[object Object]

← back to AbramsEgo

use owner-safe PM2 CLI wrapper

c19e2fecb3323e953c7ba32dcf1507fa40d1e36c · 2026-08-30 20:54:49 -0700 · Steve

Files touched

Diff

commit c19e2fecb3323e953c7ba32dcf1507fa40d1e36c
Author: Steve <steve@designerwallcoverings.com>
Date:   Sun Aug 30 20:54:49 2026 -0700

    use owner-safe PM2 CLI wrapper
---
 server.js | 27 +++------------------------
 1 file changed, 3 insertions(+), 24 deletions(-)

diff --git a/server.js b/server.js
index 2771885b..6547d257 100644
--- a/server.js
+++ b/server.js
@@ -98,29 +98,8 @@ function sh(cmd, args, timeoutMs = 8000) {
   });
 }
 
-// TK-10970: serialize local PM2 CLI access with the same lock used by the
-// fleet keepalive and microsite crawler. Concurrent `pm2 jlist` calls can fork
-// a socket-less God daemon during a transient rpc.sock access race.
-const PM2_CLI_LOCK = path.join(process.env.PM2_HOME || path.join(HOME, '.pm2'), 'cli.lock.d');
-async function withPm2CliLock(fn) {
-  const deadline = Date.now() + 10000;
-  const staleMs = 8000;
-  let held = false;
-  while (Date.now() < deadline) {
-    try { await fs.promises.mkdir(PM2_CLI_LOCK); held = true; break; }
-    catch (e) {
-      if (e.code !== 'EEXIST') break;
-      try {
-        const st = await fs.promises.stat(PM2_CLI_LOCK);
-        if (Date.now() - st.mtimeMs > staleMs) { await fs.promises.rmdir(PM2_CLI_LOCK); continue; }
-      } catch {}
-      await new Promise(resolve => setTimeout(resolve, 80));
-    }
-  }
-  if (!held) return { ok: false, out: '', err: 'pm2 CLI lock unavailable' };
-  try { return await fn(); }
-  finally { try { await fs.promises.rmdir(PM2_CLI_LOCK); } catch {} }
-}
+// TK-10970: all local PM2 CLI calls share the owner-checked shlock wrapper.
+const PM2_SERIALIZED = path.join(HOME, '.claude', 'skills', 'keep-alive', 'proposals', 'TK-10970', 'pm2-serialized.js');
 async function fetchJSON(url, timeoutMs = 5000) {
   const ctrl = new AbortController();
   const t = setTimeout(() => ctrl.abort(), timeoutMs);
@@ -237,7 +216,7 @@ async function collectLocalFleet() {
   const inCooldown = Date.now() - jlistFailedAt < JLIST_COOLDOWN_MS;
   const r = inCooldown
     ? { ok: false, out: '', err: 'jlist cooldown after recent failure' }
-    : await withPm2CliLock(() => sh(pm2Bin, ['jlist'], 7000));
+    : await sh(process.execPath, [PM2_SERIALIZED, 'jlist'], 22000);
   let list = null;
   if (r.ok) { try { list = JSON.parse(r.out); } catch (e) { /* fall through to cache */ } }
   if (!inCooldown && !list) jlistFailedAt = Date.now();

← 234ef754 auto-data-snapshot: 2026-08-30T20:54:26 (1 data files) — dat  ·  back to AbramsEgo  ·  auto-data-snapshot: 2026-08-30T21:32:01 (1 data files) — dat fe659e3a →