gm-skill 2.0.1488 → 2.0.1490
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/AGENTS.md +1 -1
- package/gm-plugkit/package.json +1 -1
- package/gm-plugkit/plugkit-wasm-wrapper.js +29 -14
- package/gm-plugkit/supervisor.js +10 -2
- package/gm.json +1 -1
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -40,7 +40,7 @@ Agents dispatch verbs by writing to `.gm/exec-spool/in/<verb>/<N>.txt` (request
|
|
|
40
40
|
|
|
41
41
|
**git verbs**: git is a first-class spool surface, never a shell command; `git_finalize {message}` is the bundled COMPLETE-phase push surface and `git_push` is the only admissible raw push (porcelain-gated, rebase-retry). A git-dominant `bash`/`powershell` body is gated (`deviation.bash-git-bypass`). Full per-verb shapes, host_git `.exe` resolution, and the gate detail live in rs-learn (`recall: git verbs rs-plugkit spool surface`).
|
|
42
42
|
|
|
43
|
-
**filter verb**: pure stdout → compact-stdout transformation
|
|
43
|
+
**filter verb**: pure stdout → compact-stdout transformation, in-wasm, no subprocess; pipe raw command output through it before it enters context. Full per-kind spec in rs-learn (`recall: filter verb rs-plugkit spool spec`).
|
|
44
44
|
|
|
45
45
|
## Documentation Policy
|
|
46
46
|
|
package/gm-plugkit/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-plugkit",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1490",
|
|
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": {
|
|
@@ -677,15 +677,24 @@ function isProfileLocked(profileDir) {
|
|
|
677
677
|
return true;
|
|
678
678
|
}
|
|
679
679
|
|
|
680
|
-
function
|
|
680
|
+
function sessionProfileSlug(claudeSessionId) {
|
|
681
|
+
const s = String(claudeSessionId || 'default').replace(/[^a-zA-Z0-9_-]/g, '-').slice(0, 64);
|
|
682
|
+
return s || 'default';
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
function sessionProfileDir(cwd, claudeSessionId) {
|
|
686
|
+
return path.join(cwd, '.gm', `browser-profile-${sessionProfileSlug(claudeSessionId)}`);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
function acquireProfileDir(cwd, claudeSessionId) {
|
|
681
690
|
const gmDir = path.join(cwd, '.gm');
|
|
682
691
|
try { fs.mkdirSync(gmDir, { recursive: true }); } catch (_) {}
|
|
683
|
-
const primary = path.join(gmDir, 'browser-profile');
|
|
684
692
|
ensureGitignored(cwd, '.gm/browser-profile/');
|
|
685
693
|
ensureGitignored(cwd, '.gm/browser-profile-*/');
|
|
694
|
+
const primary = sessionProfileDir(cwd, claudeSessionId);
|
|
686
695
|
try { fs.mkdirSync(primary, { recursive: true }); } catch (_) {}
|
|
687
696
|
if (!isProfileLocked(primary)) return primary;
|
|
688
|
-
const fallback = path.join(gmDir, `browser-profile-${process.pid}`);
|
|
697
|
+
const fallback = path.join(gmDir, `browser-profile-${sessionProfileSlug(claudeSessionId)}-${process.pid}`);
|
|
689
698
|
try { fs.mkdirSync(fallback, { recursive: true }); } catch (_) {}
|
|
690
699
|
return fallback;
|
|
691
700
|
}
|
|
@@ -696,15 +705,21 @@ function cleanDeadProfileFragments(cwd) {
|
|
|
696
705
|
if (!fs.existsSync(gmDir)) return { cleaned: 0 };
|
|
697
706
|
let cleaned = 0;
|
|
698
707
|
for (const name of fs.readdirSync(gmDir)) {
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
const
|
|
702
|
-
if (
|
|
703
|
-
|
|
704
|
-
fs.rmSync(
|
|
705
|
-
|
|
706
|
-
|
|
708
|
+
if (!/^browser-profile($|-)/.test(name)) continue;
|
|
709
|
+
const dir = path.join(gmDir, name);
|
|
710
|
+
const pidM = name.match(/-(\d+)$/);
|
|
711
|
+
if (pidM) {
|
|
712
|
+
if (!isProcessAliveSync(parseInt(pidM[1], 10))) {
|
|
713
|
+
try { fs.rmSync(dir, { recursive: true, force: true }); cleaned++; } catch (_) {}
|
|
714
|
+
}
|
|
715
|
+
continue;
|
|
707
716
|
}
|
|
717
|
+
try {
|
|
718
|
+
if (fs.existsSync(dir) && !isProfileLocked(dir)) {
|
|
719
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
720
|
+
cleaned++;
|
|
721
|
+
}
|
|
722
|
+
} catch (_) {}
|
|
708
723
|
}
|
|
709
724
|
if (cleaned > 0) {
|
|
710
725
|
logEvent('bootstrap', 'browser-profile.hygiene', { cwd, cleaned });
|
|
@@ -982,9 +997,9 @@ function getOrCreateBrowserSession(cwd, claudeSessionId, pw) {
|
|
|
982
997
|
const sessions = readJsonFile(sessionsFile, {});
|
|
983
998
|
const existing = ports[claudeSessionId];
|
|
984
999
|
if (existing && existing.pid && existing.wsEndpoint) {
|
|
985
|
-
const wantProfile =
|
|
1000
|
+
const wantProfile = sessionProfileDir(cwd, claudeSessionId);
|
|
986
1001
|
const pidOk = isProcessAliveSync(existing.pid);
|
|
987
|
-
const profileOk = !existing.profileDir || existing.profileDir === wantProfile || existing.profileDir.startsWith(
|
|
1002
|
+
const profileOk = !existing.profileDir || existing.profileDir === wantProfile || existing.profileDir.startsWith(wantProfile);
|
|
988
1003
|
const cdpOk = pidOk && !!fetchJsonSync(`http://127.0.0.1:${existing.port}/json/version`, 1000);
|
|
989
1004
|
if (pidOk && profileOk && cdpOk) {
|
|
990
1005
|
const pwIds = sessions[claudeSessionId] || [];
|
|
@@ -1033,7 +1048,7 @@ function getOrCreateBrowserSession(cwd, claudeSessionId, pw) {
|
|
|
1033
1048
|
}
|
|
1034
1049
|
}
|
|
1035
1050
|
cleanDeadProfileFragments(cwd);
|
|
1036
|
-
const profileDir = acquireProfileDir(cwd);
|
|
1051
|
+
const profileDir = acquireProfileDir(cwd, claudeSessionId);
|
|
1037
1052
|
const aliveCdpForProfile = (() => {
|
|
1038
1053
|
for (const key of Object.keys(ports)) {
|
|
1039
1054
|
const ent = ports[key];
|
package/gm-plugkit/supervisor.js
CHANGED
|
@@ -144,13 +144,16 @@ function spawnWatcher(bootReason) {
|
|
|
144
144
|
const shutdownReason = readShutdownReason();
|
|
145
145
|
const reason = shutdownReason && shutdownReason.reason;
|
|
146
146
|
const idleClean = reason === 'idle';
|
|
147
|
+
const lockRejected = code === 75;
|
|
147
148
|
const plannedReasons = new Set(['idle', 'sigterm', 'version-change', 'wrapper-change', 'peer-stale-takeover', 'external-planned']);
|
|
148
|
-
const isPlanned = plannedReasons.has(reason);
|
|
149
|
+
const isPlanned = plannedReasons.has(reason) || lockRejected;
|
|
149
150
|
const eventName = idleClean
|
|
150
151
|
? 'supervisor.watcher-exited-idle'
|
|
151
152
|
: reason === 'version-change'
|
|
152
153
|
? 'supervisor.watcher-exited-for-update'
|
|
153
|
-
:
|
|
154
|
+
: lockRejected
|
|
155
|
+
? 'supervisor.watcher-exited-lock-rejected'
|
|
156
|
+
: 'supervisor.watcher-exited-unexpectedly';
|
|
154
157
|
logEvent(eventName, {
|
|
155
158
|
watcher_pid: currentChildPid,
|
|
156
159
|
exit_code: code,
|
|
@@ -166,6 +169,11 @@ function spawnWatcher(bootReason) {
|
|
|
166
169
|
try { fs.unlinkSync(SUPERVISOR_PATH); } catch (_) {}
|
|
167
170
|
process.exit(0);
|
|
168
171
|
}
|
|
172
|
+
if (lockRejected) {
|
|
173
|
+
writeSupervisorStatus('exited-lock-rejected', { watcher_pid: currentChildPid });
|
|
174
|
+
try { fs.unlinkSync(SUPERVISOR_PATH); } catch (_) {}
|
|
175
|
+
process.exit(0);
|
|
176
|
+
}
|
|
169
177
|
const respawnReason = reason === 'version-change' ? 'planned-restart-version-change' : 'unplanned-restart-after-exit';
|
|
170
178
|
writeSupervisorStatus('restarting', {
|
|
171
179
|
prior_watcher_pid: currentChildPid,
|
package/gm.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-skill",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1490",
|
|
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",
|