gm-skill 2.0.1519 → 2.0.1521

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-plugkit",
3
- "version": "2.0.1519",
3
+ "version": "2.0.1521",
4
4
  "description": "Bootstrap and daemon-spawn tool for gm plugkit binary. Downloads the correct platform binary, verifies SHA256, and starts the spool watcher daemon. Includes plugkit-wasm-wrapper for WASM-based spool watching.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -807,6 +807,49 @@ function cleanDeadProfileFragments(cwd) {
807
807
  }
808
808
  }
809
809
 
810
+ function parsePlaywriterSessionList(stdout) {
811
+ const rows = [];
812
+ if (!stdout) return rows;
813
+ const lines = stdout.split(/\r?\n/);
814
+ for (const line of lines) {
815
+ const m = line.match(/^\s*(\d+)\s+\S+\s+\S+\s+\S+\s+(\S+)/);
816
+ if (!m) continue;
817
+ const id = m[1];
818
+ let cwd = m[2];
819
+ if (cwd === '-') cwd = '';
820
+ rows.push({ id, cwd });
821
+ }
822
+ return rows;
823
+ }
824
+
825
+ function reapOrphanBrowserSessions(pw, cwd, claudeSessionId, reason) {
826
+ try {
827
+ const ports = readJsonFile(browserPortsFile(cwd), {});
828
+ const activeIds = new Set();
829
+ for (const ent of Object.values(ports)) {
830
+ if (ent && ent.pwSessionId) activeIds.add(String(ent.pwSessionId));
831
+ }
832
+ const r = runBrowserRunner(pw, ['session', 'list'], 15000, cwd, claudeSessionId);
833
+ if (!r || r.status !== 0) return { reaped: 0 };
834
+ const rows = parsePlaywriterSessionList(r.stdout || '');
835
+ const norm = (p) => String(p || '').replace(/[\\/]+$/, '').toLowerCase();
836
+ const wantCwd = norm(cwd);
837
+ let reaped = 0;
838
+ for (const { id, cwd: rowCwd } of rows) {
839
+ if (rowCwd && norm(rowCwd) !== wantCwd) continue;
840
+ if (activeIds.has(String(id))) continue;
841
+ const d = runBrowserRunner(pw, ['session', 'delete', id], 15000, cwd, claudeSessionId);
842
+ if (d && d.status === 0) {
843
+ reaped++;
844
+ try { logEvent('plugkit', 'browser.orphan-session-reaped', { session_id: id, reason: reason || 'boot', cwd }); } catch (_) {}
845
+ }
846
+ }
847
+ return { reaped };
848
+ } catch (_) {
849
+ return { reaped: 0 };
850
+ }
851
+ }
852
+
810
853
  function resolveWindowsExeLocal(cmd) {
811
854
  if (process.platform !== 'win32') return cmd;
812
855
  try {
@@ -994,7 +1037,11 @@ function startManagedBrowser(pw, profileDir) {
994
1037
  '--disable-default-apps',
995
1038
  '--disable-gpu-process-crash-limit',
996
1039
  ];
997
- if (headless) args.push('--headless=new');
1040
+ if (headless) {
1041
+ args.push('--headless=new');
1042
+ } else {
1043
+ args.push('--no-startup-window');
1044
+ }
998
1045
  const chromeLogPath = path.join(profileDir, '.chrome-launch.log');
999
1046
  let logFd;
1000
1047
  try { logFd = fs.openSync(chromeLogPath, 'a'); } catch (_) { logFd = null; }
@@ -1137,6 +1184,7 @@ function getOrCreateBrowserSession(cwd, claudeSessionId, pw) {
1137
1184
  }
1138
1185
  }
1139
1186
  cleanDeadProfileFragments(cwd);
1187
+ reapOrphanBrowserSessions(pw, cwd, claudeSessionId, 'pre-spawn');
1140
1188
  const profileDir = acquireProfileDir(cwd, claudeSessionId);
1141
1189
  const aliveCdpForProfile = (() => {
1142
1190
  for (const key of Object.keys(ports)) {
@@ -2085,6 +2133,8 @@ async function runSpoolWatcher(instance, spoolDir) {
2085
2133
  fs.writeFileSync(path.join(gmDir, 'long-gap-retry-state'), '');
2086
2134
  } catch (_) {}
2087
2135
 
2136
+ try { reapOrphanBrowserSessions(findBrowserRunner(), process.cwd(), process.env.CLAUDE_SESSION_ID || 'claude-loop-iter', 'watcher-boot'); } catch (_) {}
2137
+
2088
2138
 
2089
2139
  const LOCK_PATH = path.join(spoolDir, '.watcher.lock');
2090
2140
  try {
@@ -2722,6 +2772,7 @@ async function runSpoolWatcher(instance, spoolDir) {
2722
2772
  try { writeJsonFile(portsFile, ports); } catch (_) {}
2723
2773
  try { writeJsonFile(sessionsFile, sessions); } catch (_) {}
2724
2774
  }
2775
+ try { reapOrphanBrowserSessions(findBrowserRunner(), process.cwd(), process.env.CLAUDE_SESSION_ID || 'claude-loop-iter', 'idle-sweep'); } catch (_) {}
2725
2776
  } catch (e) {
2726
2777
  console.error(`[browser-idle] error: ${e.message}`);
2727
2778
  }
package/gm.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm",
3
- "version": "2.0.1519",
3
+ "version": "2.0.1521",
4
4
  "description": "Spool-dispatch orchestration engine with unified state machine, skills, and automated git enforcement",
5
5
  "author": "AnEntrypoint",
6
6
  "license": "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-skill",
3
- "version": "2.0.1519",
3
+ "version": "2.0.1521",
4
4
  "description": "Canonical universal harness — AI-native software engineering via skill-driven orchestration; bootstraps plugkit for task execution and session isolation. Install in any AI coding agent host.",
5
5
  "author": "AnEntrypoint",
6
6
  "license": "MIT",