pi-goal-list-loop-audit 0.28.30 → 0.28.32
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 +146 -0
- package/package.json +1 -1
package/extensions/loops/goal.ts
CHANGED
|
@@ -4185,6 +4185,134 @@ function cmdLog(args: string, ctx: ExtensionContext): void {
|
|
|
4185
4185
|
ctx.ui.notify(`Ledger tail (last ${tail.length}${all ? "" : " non-noise"} events — /glla log <N> for more, /glla log all to include noise):\n${lines.join("\n")}`, "info");
|
|
4186
4186
|
}
|
|
4187
4187
|
|
|
4188
|
+
/**
|
|
4189
|
+
* v0.28.31: /glla reset — ONE confirmed command that leaves a project with
|
|
4190
|
+
* zero live glla state. User directive: "make sure we only have one goal or
|
|
4191
|
+
* loop or list at a time — many of my older projects have leftovers" (the
|
|
4192
|
+
* fleet scan found queued lists up to 56 deep, held loops at iter 50, and
|
|
4193
|
+
* paused goals across ~10 projects). The goal is archived HONESTLY (aborted
|
|
4194
|
+
* — lands in goals/ + the archive, reviewer's abort-suppression applies),
|
|
4195
|
+
* the list is cleared, the loop record is wiped after a graceful stop.
|
|
4196
|
+
* History stays in .pi-glla; only the live state goes.
|
|
4197
|
+
*/
|
|
4198
|
+
async function cmdGllaReset(ctx: ExtensionContext): Promise<void> {
|
|
4199
|
+
const g = state.goal;
|
|
4200
|
+
const live = g && (g.status === "active" || g.status === "paused" || g.status === "auditing");
|
|
4201
|
+
const n = listQueue().length;
|
|
4202
|
+
const loop = state.loop;
|
|
4203
|
+
if (!g && n === 0 && !loop) {
|
|
4204
|
+
ctx.ui.notify("glla state is already clean — no goal, no list, no loop.", "info");
|
|
4205
|
+
return;
|
|
4206
|
+
}
|
|
4207
|
+
const parts: string[] = [];
|
|
4208
|
+
if (live) parts.push(`goal archived as aborted: ${g!.objective.replace(/\s+/g, " ").slice(0, 70)}`);
|
|
4209
|
+
else if (g) parts.push(`terminal goal record cleared (${g.status})`);
|
|
4210
|
+
if (n > 0) parts.push(`list cleared (${n} item${n === 1 ? "" : "s"})`);
|
|
4211
|
+
if (loop) parts.push(`loop ${loop.active ? "stopped" : "cleared"} (iter ${loop.iteration}${loop.bestValue !== null && loop.bestValue !== undefined ? `, best ${loop.bestValue}` : ""})`);
|
|
4212
|
+
if (ctx.hasUI) {
|
|
4213
|
+
try {
|
|
4214
|
+
const ok = await ctx.ui.confirm("Reset glla state?", `${parts.map((p) => ` ${p}`).join("\n")}\n\nHistory stays in .pi-glla (archive + ledger); the live state is wiped.`);
|
|
4215
|
+
if (!ok) {
|
|
4216
|
+
ctx.ui.notify("Reset cancelled.", "info");
|
|
4217
|
+
return;
|
|
4218
|
+
}
|
|
4219
|
+
} catch {
|
|
4220
|
+
ctx.ui.notify("Reset cancelled.", "info");
|
|
4221
|
+
return;
|
|
4222
|
+
}
|
|
4223
|
+
}
|
|
4224
|
+
appendLedger(ctx.cwd, "glla_reset", { goalId: live ? g!.id : undefined, listCleared: n, loop: loop ? { iteration: loop.iteration, active: loop.active } : undefined });
|
|
4225
|
+
if (live) {
|
|
4226
|
+
archiveCurrentGoal(ctx, "aborted", "user reset (/glla reset)");
|
|
4227
|
+
ctx.abort();
|
|
4228
|
+
} else if (g) {
|
|
4229
|
+
state = { ...state, goal: null };
|
|
4230
|
+
}
|
|
4231
|
+
if (n > 0) {
|
|
4232
|
+
state = { ...state, list: [] };
|
|
4233
|
+
appendLedger(ctx.cwd, "list_cleared", { via: "glla_reset" });
|
|
4234
|
+
}
|
|
4235
|
+
if (loop) {
|
|
4236
|
+
clearLoopTimer();
|
|
4237
|
+
state.loop = undefined;
|
|
4238
|
+
await finishLoopGit(ctx, loop);
|
|
4239
|
+
appendLedger(ctx.cwd, "loop_stopped", { reason: "user reset (/glla reset)", iterations: loop.iteration, best: loop.bestValue });
|
|
4240
|
+
}
|
|
4241
|
+
persistState(ctx);
|
|
4242
|
+
ctx.ui.notify(`glla reset done: ${parts.join(" · ")}. Clean slate.`, "info");
|
|
4243
|
+
notifyExternal(ctx, "glla state reset by user — clean slate.");
|
|
4244
|
+
}
|
|
4245
|
+
|
|
4246
|
+
/**
|
|
4247
|
+
* v0.28.32: /glla resume — resume WHATEVER is resumable, without the user
|
|
4248
|
+
* needing to know whether they're supervising a goal, a list item, or a
|
|
4249
|
+
* held loop. Safe because one-active-thing is enforced (v0.28.14+): at
|
|
4250
|
+
* most one thing can be ACTIVE, so the only ambiguity is paused-goal +
|
|
4251
|
+
* held-loop coexisting (nothing running, two resumables — e.g. polis
|
|
4252
|
+
* today) → the v0.28.23 decision-picker pattern. Verbs whose semantics
|
|
4253
|
+
* genuinely differ per type (tweak/finish/next/decide/refine) stay typed.
|
|
4254
|
+
*/
|
|
4255
|
+
async function cmdGllaResume(ctx: ExtensionContext): Promise<void> {
|
|
4256
|
+
const g = state.goal;
|
|
4257
|
+
const goalResumable = g && g.status === "paused";
|
|
4258
|
+
const loopResumable = state.loop && !state.loop.active && state.loop.stopReason === HELD_ON_RESTORE;
|
|
4259
|
+
if (goalResumable && loopResumable) {
|
|
4260
|
+
if (ctx.hasUI) {
|
|
4261
|
+
try {
|
|
4262
|
+
const loopLabel = `Resume the held loop (iter ${state.loop!.iteration}, best ${state.loop!.bestValue ?? "n/a"}): ${state.loop!.target.replace(/\s+/g, " ").slice(0, 80)}`;
|
|
4263
|
+
const pick = await ctx.ui.select("Two things can resume — which one?", [
|
|
4264
|
+
`Resume the ${g!.policy === "list" ? "list item" : "goal"}: ${g!.objective.replace(/\s+/g, " ").slice(0, 80)}`,
|
|
4265
|
+
loopLabel,
|
|
4266
|
+
]);
|
|
4267
|
+
if (pick === undefined) {
|
|
4268
|
+
ctx.ui.notify("Resume cancelled.", "info");
|
|
4269
|
+
return;
|
|
4270
|
+
}
|
|
4271
|
+
if (pick === loopLabel) {
|
|
4272
|
+
await cmdLoop("resume", ctx);
|
|
4273
|
+
return;
|
|
4274
|
+
}
|
|
4275
|
+
await cmdResume(ctx);
|
|
4276
|
+
return;
|
|
4277
|
+
} catch {
|
|
4278
|
+
// picker failed — fall through to goal-first
|
|
4279
|
+
}
|
|
4280
|
+
}
|
|
4281
|
+
await cmdResume(ctx);
|
|
4282
|
+
return;
|
|
4283
|
+
}
|
|
4284
|
+
if (goalResumable) {
|
|
4285
|
+
await cmdResume(ctx);
|
|
4286
|
+
return;
|
|
4287
|
+
}
|
|
4288
|
+
if (loopResumable) {
|
|
4289
|
+
await cmdLoop("resume", ctx);
|
|
4290
|
+
return;
|
|
4291
|
+
}
|
|
4292
|
+
ctx.ui.notify("Nothing to resume — no paused goal/list-item, no held loop. /goal, /list, or /loop to start something.", "info");
|
|
4293
|
+
}
|
|
4294
|
+
|
|
4295
|
+
/**
|
|
4296
|
+
* v0.28.32: /glla cancel — cancel the ONE live thing, uniformly: a goal or
|
|
4297
|
+
* list item is archived as aborted (its queue is untouched), an active or
|
|
4298
|
+
* held loop is stopped. Same outcome shape regardless of hidden type —
|
|
4299
|
+
* the user's caveat ("this sucks if one command doesn't work for others")
|
|
4300
|
+
* is why /list cancel (item + drop queue) and /glla reset (nuke all)
|
|
4301
|
+
* remain the power verbs instead of being folded in.
|
|
4302
|
+
*/
|
|
4303
|
+
async function cmdGllaCancel(ctx: ExtensionContext): Promise<void> {
|
|
4304
|
+
const g = state.goal;
|
|
4305
|
+
if (g && (g.status === "active" || g.status === "paused" || g.status === "auditing")) {
|
|
4306
|
+
await cmdCancel(ctx);
|
|
4307
|
+
return;
|
|
4308
|
+
}
|
|
4309
|
+
if (state.loop) {
|
|
4310
|
+
await cmdLoop("stop", ctx);
|
|
4311
|
+
return;
|
|
4312
|
+
}
|
|
4313
|
+
ctx.ui.notify("Nothing to cancel — no active/paused goal/list-item, no loop. Queued list items: /list clear; everything: /glla reset.", "info");
|
|
4314
|
+
}
|
|
4315
|
+
|
|
4188
4316
|
function cmdAudits(args: string, ctx: ExtensionContext): void {
|
|
4189
4317
|
const full = /\bfull\b/.test(args);
|
|
4190
4318
|
const all = /\b(?:all|global|log)\b/.test(args);
|
|
@@ -4242,6 +4370,21 @@ async function cmdSettings(args: string, ctx: ExtensionContext): Promise<void> {
|
|
|
4242
4370
|
cmdLog(trimmed.slice("log".length).trim(), ctx);
|
|
4243
4371
|
return;
|
|
4244
4372
|
}
|
|
4373
|
+
// v0.28.31: /glla reset — one-shot clean slate for leftover-laden projects.
|
|
4374
|
+
if (/^reset\b/.test(trimmed)) {
|
|
4375
|
+
await cmdGllaReset(ctx);
|
|
4376
|
+
return;
|
|
4377
|
+
}
|
|
4378
|
+
// v0.28.32: /glla resume + /glla cancel — type-blind verbs over the ONE
|
|
4379
|
+
// live thing ("so we don't have to check what type we are running").
|
|
4380
|
+
if (/^resume\b/.test(trimmed)) {
|
|
4381
|
+
await cmdGllaResume(ctx);
|
|
4382
|
+
return;
|
|
4383
|
+
}
|
|
4384
|
+
if (/^cancel\b/.test(trimmed)) {
|
|
4385
|
+
await cmdGllaCancel(ctx);
|
|
4386
|
+
return;
|
|
4387
|
+
}
|
|
4245
4388
|
if (/^reviewer\b/.test(trimmed)) {
|
|
4246
4389
|
await cmdReviewerSettings(ctx);
|
|
4247
4390
|
return;
|
|
@@ -4633,6 +4776,9 @@ export default function (pi: ExtensionAPI): void {
|
|
|
4633
4776
|
["decisionpopup=", "on|off: decision pauses pop the select() picker (default on; the widget card always lists the options, /goal decide reopens the picker)"],
|
|
4634
4777
|
["auditcap=", "N: pause goal after N consecutive auditor disapprovals (default 5, 0 = unlimited)"],
|
|
4635
4778
|
["log", "event-trail tail: /glla log [N] — who created/resumed/paused what, from where (v0.28.28)"],
|
|
4779
|
+
["reset", "wipe live glla state (goal archived, list cleared, loop stopped) — one-shot cleanup for leftover-laden projects"],
|
|
4780
|
+
["resume", "resume WHATEVER is paused/held (goal, list item, or held loop) — no need to know the type"],
|
|
4781
|
+
["cancel", "cancel the ONE live thing uniformly (goal/list item archived, loop stopped) — queue untouched; /list clear or /glla reset for more"],
|
|
4636
4782
|
["auditfeedbackchars=", "cap on executor-visible disapproval report chars (0 = full report, the default)"],
|
|
4637
4783
|
["aggressivemode=", "on: keep-going defaults — autoResume, cap 10, stuck 10, wedge off, quota auto-retry, cap→TODOs"],
|
|
4638
4784
|
["quotaretryminutes=", "N: minutes before auto-retrying a quota-exhausted auditor (default 60)"],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-goal-list-loop-audit",
|
|
3
|
-
"version": "0.28.
|
|
3
|
+
"version": "0.28.32",
|
|
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",
|