pi-goal-list-loop-audit 0.29.21 → 0.29.22
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/extensions/loops/goal.ts +46 -14
- package/package.json +1 -1
package/extensions/loops/goal.ts
CHANGED
|
@@ -238,26 +238,53 @@ function goStaleTerminal(ctx: ExtensionContext, where: string): void {
|
|
|
238
238
|
updateGoal({ interruptedAt: nowIso(), interruptedReason: `extension api stale (${where})` }, ctx);
|
|
239
239
|
}
|
|
240
240
|
ctx.ui.notify(`glla: ${guidance}`, "warning");
|
|
241
|
-
notifyExternal(ctx, `glla: extension api stale —
|
|
242
|
-
|
|
241
|
+
notifyExternal(ctx, `glla: extension api stale — run /reload, then /glla resume. (${where})`);
|
|
242
|
+
attemptAutoReload(ctx, where);
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
/** v0.29.13: automatic recovery — the zombie handle can't call ctx.reload()
|
|
246
246
|
* (pi walls EVERY runtime method behind assertActive), but fs/child_process
|
|
247
|
-
* are extension-side and still work.
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
|
|
247
|
+
* are extension-side and still work. Inject /reload as keystrokes into our
|
|
248
|
+
* own terminal pane: pi rebuilds the extension runtime in place, the fresh
|
|
249
|
+
* instance loads .pi-glla state and holds (autoresume=on resumes for you).
|
|
250
|
+
* v0.29.22: transport-generalized — tmux OR WezTerm. Field: this rig runs
|
|
251
|
+
* WezTerm (TERM_PROGRAM=WezTerm, WEZTERM_PANE set, no TMUX), so the
|
|
252
|
+
* tmux-only gate failed silently 100% of the time — auto_reload_injected
|
|
253
|
+
* never fired fleet-wide, and every stale handle fell back to the manual
|
|
254
|
+
* warning (user: "stopping and told to reload is common"). v0.29.22 also
|
|
255
|
+
* fires from the entry-probe path (the most common stale discovery).
|
|
256
|
+
* Opt out: autoReloadOnStale=false. Best-effort: the manual warning
|
|
257
|
+
* already fired, so failures cost nothing. */
|
|
258
|
+
function attemptAutoReload(ctx: ExtensionContext, where: string): void {
|
|
253
259
|
try {
|
|
254
260
|
if (loadSettings(ctx.cwd).autoReloadOnStale === false) return;
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
+
const tmuxPane = process.env.TMUX_PANE;
|
|
262
|
+
const wezPane = process.env.WEZTERM_PANE;
|
|
263
|
+
let transport: "tmux" | "wezterm";
|
|
264
|
+
let cmd: string;
|
|
265
|
+
let pane: string;
|
|
266
|
+
if (process.env.TMUX && tmuxPane && /^%\d+$/.test(tmuxPane)) {
|
|
267
|
+
transport = "tmux";
|
|
268
|
+
pane = tmuxPane;
|
|
269
|
+
// v0.29.22: NO leading Escape — a late zombie probe can fire AFTER a
|
|
270
|
+
// fresh instance already resumed and started a turn, and Escape
|
|
271
|
+
// would abort that turn without consent (the consent line). /reload
|
|
272
|
+
// alone lands at a dead prompt and queues harmlessly mid-turn (pi
|
|
273
|
+
// refuses the reload itself if a response is streaming).
|
|
274
|
+
cmd = `tmux send-keys -t ${pane} -l '/reload' && tmux send-keys -t ${pane} Enter`;
|
|
275
|
+
} else if (wezPane && /^\d+$/.test(wezPane)) {
|
|
276
|
+
transport = "wezterm";
|
|
277
|
+
pane = wezPane;
|
|
278
|
+
// wezterm cli send-text --no-paste delivers bytes as keystrokes.
|
|
279
|
+
// /reload + CR only — no Escape (see above). Literal CR byte inside
|
|
280
|
+
// single quotes — no bash-isms (exec uses /bin/sh).
|
|
281
|
+
cmd = `wezterm cli send-text --pane-id ${pane} --no-paste '/reload\r'`;
|
|
282
|
+
} else {
|
|
283
|
+
appendLedger(ctx.cwd, "auto_reload_skipped", { where, reason: "no supported multiplexer (tmux/WezTerm) in env" });
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
appendLedger(ctx.cwd, "auto_reload_injected", { where, transport, pane });
|
|
287
|
+
ctx.ui.notify("glla: injecting /reload into this pane — extensions rebuild in place and the fresh instance holds state. /glla resume after (automatic with autoresume=on).", "info");
|
|
261
288
|
exec(cmd, () => { /* best-effort */ });
|
|
262
289
|
} catch {
|
|
263
290
|
/* never let recovery take the warning path down */
|
|
@@ -303,6 +330,11 @@ function warnIfStaleAtEntry(ctx: ExtensionContext, what: string): boolean {
|
|
|
303
330
|
`glla: this session's extension handle is stale (pi session replacement) — ${what} can't send continuations in this process. State is safe in .pi-glla/ — run /reload (extensions rebuild in place), then /glla resume. Restart pi only if /reload fails.`,
|
|
304
331
|
"warning",
|
|
305
332
|
);
|
|
333
|
+
// v0.29.22: deliberately NO self-heal from the entry probe — it fires
|
|
334
|
+
// when the user is ACTIVELY typing a /glla command, and injected
|
|
335
|
+
// keystrokes would race their input. User-present cases keep the manual
|
|
336
|
+
// warning; the self-heal stays on the autonomous paths (heartbeat
|
|
337
|
+
// probe, send paths) where no one is at the keyboard.
|
|
306
338
|
return true;
|
|
307
339
|
}
|
|
308
340
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-goal-list-loop-audit",
|
|
3
|
-
"version": "0.29.
|
|
3
|
+
"version": "0.29.22",
|
|
4
4
|
"description": "Goal. Loop. Audit. Done. \u2014 a pi-coding-agent extension that supervises long-running work, with isolated auditor on each completion. Beat bamboozling by design: the auditor runs in a fresh session with no extensions, no skills, no editor \u2014 only the read tools needed to verify your goal.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "dracon",
|