gm-skill 2.0.1575 → 2.0.1577
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 +2 -2
- package/gm-plugkit/package.json +1 -1
- package/gm-plugkit/plugkit-wasm-wrapper.js +25 -3
- package/gm.json +1 -1
- package/lib/spool-dispatch.js +3 -1
- package/lib/spool.js +1 -1
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -148,13 +148,13 @@ Push to any rs-* sibling triggers `cascade.yml` -> rs-plugkit `release.yml` -> s
|
|
|
148
148
|
|
|
149
149
|
Orchestration state is tracked via `.gm/` marker files, not hook events; the CLI layer calls `checkDispatchGates()` before tool execution to gate Write/Edit/git. Marker set (`prd.yml, mutables.yml, needs-gm, gm-fired-<sessionId>, residual-check-fired`) + SpoolDispatcher mechanism in rs-learn (`recall: gate enforcement layer`, `recall: spool dispatch gates marker files`).
|
|
150
150
|
|
|
151
|
-
**gm-skill tool-use sequencing**: `Skill(skill="gm-skill")`
|
|
151
|
+
**gm-skill tool-use sequencing**: `Skill(skill="gm-skill")` clears the needs-gm gate. One shipped skill, no subagent variant. Marker mechanics in rs-learn (`recall: gm-skill tool-use sequencing mechanics`).
|
|
152
152
|
|
|
153
153
|
**The skill is the driver, not a post-hoc witness**: when a request carries the standing instruction to use gm-skill (every `/loop` fire, any prompt naming `/gm-skill`), the FIRST working action is `Skill(skill="gm-skill")`, and the skill prose drives the chain PLAN->COMPLETE. Dispatching spool verbs directly without first entering the skill executes the work outside the skill the user asked to drive it; entering only at the end to confirm terminal state does NOT satisfy the instruction. The boot probe (`cat .gm/exec-spool/.status.json` ...) is prescribed by the skill and may precede invocation; everything that mutates state happens inside the skill-driven session.
|
|
154
154
|
|
|
155
155
|
**Dead-watcher recovery uses `bun x gm-plugkit@latest spool`, never direct-node boot** (mechanism in rs-learn: `recall: dead-watcher recovery bun x not direct-node`).
|
|
156
156
|
|
|
157
|
-
**The first verb after a genuine multi-minute IDLE is `instruction`, to reset the long-gap clock**:
|
|
157
|
+
**The first verb after a genuine multi-minute IDLE is `instruction`, to reset the long-gap clock**: gate fires when >300s since last instruction AND >300s since any SPOOL verb. Platform `Bash`/`Read`/`Edit`/`Grep` do NOT reset the clock -- a long investigation run in them trips a false stall; interleave `prd-add` or `instruction` to keep warm. For a predictable blocking wait (`TaskOutput`/`gh run watch`), dispatch `instruction` BEFORE entering the wait. Detail + platform-tool exception in rs-learn (`recall: first verb after multi-minute wait instruction long-gap`).
|
|
158
158
|
|
|
159
159
|
**A stop-hook firing on a terminal chain does not authorize re-polling**: when a stop-hook fires while already at `phase=COMPLETE` AND `prd_pending_count=0`, re-dispatching `instruction`/`phase-status` to "re-confirm" is a deviation (`deviation.complete-chain-poll`, `instructions/mod.rs`). Two admissible responses: (a) a prose-only turn (COMPLETE is in hand), or (b) genuinely new planned work opened with a FRESH `{"prompt":...}` body (resets phase to PLAN, driven through the skill). Repeatedly answering the same hook is a loop; state the terminal facts once and stop, or open new work.
|
|
160
160
|
|
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.1577",
|
|
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": {
|
|
@@ -2139,8 +2139,8 @@ async function runSpoolWatcher(instance, spoolDir) {
|
|
|
2139
2139
|
}
|
|
2140
2140
|
function lockBody() { return `${process.pid}|${Date.now()}|${_ownWrapperSha12}`; }
|
|
2141
2141
|
function acquireLock() {
|
|
2142
|
-
|
|
2143
|
-
|
|
2142
|
+
function checkExistingHolder() {
|
|
2143
|
+
try {
|
|
2144
2144
|
const content = fs.readFileSync(LOCK_PATH, 'utf-8').trim();
|
|
2145
2145
|
const parts = content.split('|');
|
|
2146
2146
|
const pidStr = parts[0];
|
|
@@ -2164,6 +2164,7 @@ async function runSpoolWatcher(instance, spoolDir) {
|
|
|
2164
2164
|
}));
|
|
2165
2165
|
} catch (_) {}
|
|
2166
2166
|
try { process.kill(parseInt(pidStr, 10), 'SIGTERM'); } catch (_) {}
|
|
2167
|
+
return 'takeover';
|
|
2167
2168
|
} else {
|
|
2168
2169
|
const msg = JSON.stringify({ ok: false, reason: 'another-watcher-active', pid: pidStr, age_ms: age });
|
|
2169
2170
|
console.error(`[plugkit-wasm] ${msg}; refusing to start`);
|
|
@@ -2181,11 +2182,32 @@ async function runSpoolWatcher(instance, spoolDir) {
|
|
|
2181
2182
|
} else if (!holderAlive) {
|
|
2182
2183
|
console.error(`[plugkit-wasm] stale lock (holder pid=${pidStr} dead, age=${age}ms); taking over`);
|
|
2183
2184
|
try { logEvent('plugkit', 'watcher.lock-pid-dead-takeover', { stale_pid: pidStr, lock_age_ms: age }); } catch (_) {}
|
|
2185
|
+
return 'takeover';
|
|
2184
2186
|
} else {
|
|
2185
2187
|
console.error(`[plugkit-wasm] stale lock (age=${age}ms); taking over`);
|
|
2188
|
+
return 'takeover';
|
|
2186
2189
|
}
|
|
2190
|
+
} catch (_) {
|
|
2191
|
+
return 'takeover';
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
try {
|
|
2195
|
+
let fd;
|
|
2196
|
+
try {
|
|
2197
|
+
fd = fs.openSync(LOCK_PATH, 'wx');
|
|
2198
|
+
} catch (e) {
|
|
2199
|
+
if (e.code !== 'EEXIST') throw e;
|
|
2200
|
+
const action = checkExistingHolder();
|
|
2201
|
+
if (action !== 'takeover') return;
|
|
2202
|
+
try { fs.unlinkSync(LOCK_PATH); } catch (_) {}
|
|
2203
|
+
fd = fs.openSync(LOCK_PATH, 'wx');
|
|
2204
|
+
}
|
|
2205
|
+
try {
|
|
2206
|
+
const body = Buffer.from(lockBody(), 'utf-8');
|
|
2207
|
+
fs.writeSync(fd, body);
|
|
2208
|
+
} finally {
|
|
2209
|
+
fs.closeSync(fd);
|
|
2187
2210
|
}
|
|
2188
|
-
fs.writeFileSync(LOCK_PATH, lockBody());
|
|
2189
2211
|
} catch (e) {
|
|
2190
2212
|
console.error(`[plugkit-wasm] lock acquire failed: ${e.message}`);
|
|
2191
2213
|
process.exit(1);
|
package/gm.json
CHANGED
package/lib/spool-dispatch.js
CHANGED
|
@@ -330,7 +330,9 @@ function checkDispatchGates(sessionId, operation, extra) {
|
|
|
330
330
|
if (content.includes('status: unknown')) {
|
|
331
331
|
residuals.push('unresolved mutables present -- resolve with witness_evidence before declaring done');
|
|
332
332
|
}
|
|
333
|
-
} catch (
|
|
333
|
+
} catch (e) {
|
|
334
|
+
residuals.push(`mutables.yml unreadable (${e.message}) -- cannot verify mutable state`);
|
|
335
|
+
}
|
|
334
336
|
}
|
|
335
337
|
const dirty = isWorktreeDirty(cwd);
|
|
336
338
|
if (dirty.available && dirty.dirty) {
|
package/lib/spool.js
CHANGED
|
@@ -49,7 +49,7 @@ function writeSpool(body, lang = 'nodejs', options = {}) {
|
|
|
49
49
|
fs.mkdirSync(inDir, { recursive: true });
|
|
50
50
|
|
|
51
51
|
const sessionId = options.sessionId || process.env.CLAUDE_SESSION_ID;
|
|
52
|
-
const code = sessionId ? `const SESSION_ID =
|
|
52
|
+
const code = sessionId ? `const SESSION_ID = ${JSON.stringify(sessionId)};\n${body}` : body;
|
|
53
53
|
|
|
54
54
|
fs.writeFileSync(inFile, code, 'utf8');
|
|
55
55
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-skill",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1577",
|
|
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",
|