pi-goal-list-loop-audit 0.29.7 → 0.29.8
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/README.md +5 -4
- package/extensions/goal-loop-core.ts +9 -5
- package/extensions/goal-loop-forever.ts +19 -0
- package/extensions/loops/goal.ts +57 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -39,10 +39,11 @@ Five top-level commands — `/goal`, `/list`, `/loop`, `/glla`, `/review`:
|
|
|
39
39
|
/goal resume # resume
|
|
40
40
|
/goal cancel # abort
|
|
41
41
|
/goal decide # re-open the decision picker (v0.28.23)
|
|
42
|
-
/goal audit
|
|
42
|
+
/goal audit ["focus on payments"] # one-shot project audit (v0.29.8): fix the non-decisions, present the decisions — findings in .pi-glla/audit-loop/findings.md
|
|
43
|
+
/goal verify # run the isolated auditor on the current goal now — no agent turn (v0.28.27, renamed from /goal audit in v0.29.8)
|
|
43
44
|
/goal tweak "<new objective>" # edit in place (Confirm dialog)
|
|
44
45
|
/goal archive # archived goals, newest first
|
|
45
|
-
/glla # settings UI table · /glla key=value · /glla stats · /glla audits [N|full] · /glla postaudit · /glla wipe (nuclear reset, Confirm-gated) · /glla autoaccept=on
|
|
46
|
+
/glla # settings UI table · /glla status (unified what's-running view) · /glla key=value · /glla stats · /glla audits [N|full] · /glla postaudit · /glla wipe (nuclear reset, Confirm-gated) · /glla autoaccept=on
|
|
46
47
|
/list fix the login bug, add dark mode, write docs # dump it — the agent shapes it into items, one Confirm
|
|
47
48
|
/list plan.md # file detected → bulk import, one Confirm (sisyphus/Ralph style)
|
|
48
49
|
/list <paste a checklist> # multi-line paste → same batch flow
|
|
@@ -66,7 +67,7 @@ matches `/list show`.
|
|
|
66
67
|
/loop # draft the loop (agent grills; measure is test-run before you confirm)
|
|
67
68
|
/loop start "keep polishing the UI" # infinite metricless loop (v0.23.6): no plateau, no cap — ends at time=/tokens= or /loop stop
|
|
68
69
|
/loop respec # infinite metricless loop reconciling the codebase against the root SPEC.md / spec.md (v0.24.3) — 2 specs = you pick, 0 specs = drafting, 1 spec = auto-start (v0.24.4)
|
|
69
|
-
/loop audit # project-audit loop (v0.29.0): each iteration audits fresh, appends findings to .pi-glla/audit-loop/findings.md, fixes the top ones — the orchestrator counts open findings and the plateau stop ends it when the well is dry
|
|
70
|
+
/loop audit # project-audit loop (v0.29.0): each iteration audits fresh, appends findings to .pi-glla/audit-loop/findings.md, fixes the top ones — the orchestrator counts open findings and the plateau stop ends it when the well is dry (one-shot version: /goal audit)
|
|
70
71
|
/loop start "reduce TODOs" measure="grep -c TODO src.txt | head -1" direction=min
|
|
71
72
|
/loop start "shrink the bundle" measure="..." direction=min time=4 tokens=500000 # arbitrary bounds
|
|
72
73
|
/loop start "reduce TODOs" measure="..." direction=min branch=1 # scratch-branch mode
|
|
@@ -361,7 +362,7 @@ prompts/
|
|
|
361
362
|
goal-loop-forever-draft.md # /loop drafting prompt
|
|
362
363
|
scripts/
|
|
363
364
|
smoke.sh # live integration harness (tmux + real models)
|
|
364
|
-
tests/ #
|
|
365
|
+
tests/ # 614 tests across 58 files, no live pi required (mock-ctx harness drives the orchestrator)
|
|
365
366
|
docs/DESIGN.md # architectural decisions
|
|
366
367
|
PLAN.md # milestones, decisions, gates
|
|
367
368
|
```
|
|
@@ -216,10 +216,14 @@ export interface Goal {
|
|
|
216
216
|
export type GoalRoute =
|
|
217
217
|
| { kind: "draft" }
|
|
218
218
|
| { kind: "set"; text: string }
|
|
219
|
-
| { kind: "sub"; name: "status" | "pause" | "resume" | "cancel" | "decide" | "audit" | "tweak" | "archive" | "start"; rest: string };
|
|
219
|
+
| { kind: "sub"; name: "status" | "pause" | "resume" | "cancel" | "decide" | "verify" | "audit" | "tweak" | "archive" | "start"; rest: string };
|
|
220
220
|
|
|
221
|
-
|
|
222
|
-
|
|
221
|
+
// v0.29.8: "audit" moved to ARG subs ("/goal audit [focus]" is the one-shot
|
|
222
|
+
// project audit — user: "/goal audit IS the audit goal"); the v0.28.27
|
|
223
|
+
// manual current-goal verification moved to "verify" (it happens
|
|
224
|
+
// automatically at completion anyway — verify is the on-demand handle).
|
|
225
|
+
const GOAL_EXACT_SUBS = new Set(["status", "pause", "resume", "cancel", "decide", "verify"]);
|
|
226
|
+
const GOAL_ARG_SUBS = new Set(["audit", "tweak", "archive", "start"]);
|
|
223
227
|
|
|
224
228
|
export function routeGoalArgs(raw: string): GoalRoute {
|
|
225
229
|
const trimmed = raw.trim();
|
|
@@ -228,10 +232,10 @@ export function routeGoalArgs(raw: string): GoalRoute {
|
|
|
228
232
|
const first = (space === -1 ? trimmed : trimmed.slice(0, space)).toLowerCase();
|
|
229
233
|
const rest = space === -1 ? "" : trimmed.slice(space + 1).trim();
|
|
230
234
|
if (GOAL_EXACT_SUBS.has(first) && rest === "") {
|
|
231
|
-
return { kind: "sub", name: first as "status" | "pause" | "resume" | "cancel" | "decide", rest: "" };
|
|
235
|
+
return { kind: "sub", name: first as "status" | "pause" | "resume" | "cancel" | "decide" | "verify", rest: "" };
|
|
232
236
|
}
|
|
233
237
|
if (GOAL_ARG_SUBS.has(first)) {
|
|
234
|
-
return { kind: "sub", name: first as "tweak" | "archive" | "start", rest };
|
|
238
|
+
return { kind: "sub", name: first as "audit" | "tweak" | "archive" | "start", rest };
|
|
235
239
|
}
|
|
236
240
|
return { kind: "set", text: trimmed };
|
|
237
241
|
}
|
|
@@ -423,3 +423,22 @@ export function auditMeasureCmd(): string {
|
|
|
423
423
|
export function auditTarget(): string {
|
|
424
424
|
return `Audit the project for real problems and fix them, iteration by iteration. Every iteration: (1) run a FRESH audit pass over the codebase — spawn Explore subagents for breadth — hunting real issues: bugs, broken flows, regressions, drift between docs and code, dead code, security holes. Not style nits, not speculative refactors. (2) Append every NEW finding as one checkbox line "- [ ] SEVERITY: short description (file:line)" to ${AUDIT_FINDINGS_REL} (create the file on the first finding; append-only — never delete, rewrite, or reorder existing lines; never re-report a finding already listed). (3) Fix the highest-severity OPEN finding(s) — real fixes, committed — then check the box: "- [x] … — fixed in <commit>". (4) Honesty law: never fabricate findings to look busy; never mark a finding fixed without the fix commit existing. When a full audit pass surfaces nothing new AND no open findings remain, say so plainly — the orchestrator counts open findings every iteration and the plateau stop ends the loop when the well is dry.`;
|
|
425
425
|
}
|
|
426
|
+
|
|
427
|
+
// ---- /goal audit-project (v0.29.8) ----
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* The one-shot project audit (user design 2026-07-30): "/loop audit keeps
|
|
431
|
+
* firing — this would be fire and address what you can, present what is to
|
|
432
|
+
* be decided; whether to fix a bug is not a decision." Same findings file
|
|
433
|
+
* as the audit loop (one ledger per project — the loop can keep working
|
|
434
|
+
* what the one-shot surfaced), but exactly ONE pass with a finish line the
|
|
435
|
+
* isolated auditor verifies, and the triage law the loop doesn't have:
|
|
436
|
+
* FIX findings (bugs, polish — nobody would say "leave that bug in") are
|
|
437
|
+
* fixed autonomously; DECIDE findings (direction, trade-offs — two
|
|
438
|
+
* reasonable answers exist) are presented, never touched. DECIDE lines use
|
|
439
|
+
* "- [?]" so they never inflate the loop's open-findings measure.
|
|
440
|
+
*/
|
|
441
|
+
export function projectAuditTarget(focus?: string): string {
|
|
442
|
+
const scope = focus && focus.trim() ? focus.trim() : "the whole project";
|
|
443
|
+
return `Run ONE project audit pass and leave the project in a known state. Scope: ${scope}. (1) Run a FRESH audit pass over the codebase — spawn Explore subagents for breadth — hunting real problems: bugs, broken flows, regressions, drift between docs and code, dead code, security holes. Not style nits, not speculative refactors. (2) Append every NEW finding to ${AUDIT_FINDINGS_REL} (create the file on the first finding; append-only — never delete, rewrite, or reorder existing lines; never re-report a finding already listed), classified: "- [ ] FIX: SEVERITY: short description (file:line)" for bugs and polish — whether to fix these is NOT a decision — and "- [?] DECIDE: short description (what the choice is, what each side costs)" for direction, trade-offs, and scope questions where two reasonable answers exist. (3) Fix every NEW FIX finding from this pass — real fixes, committed with the repo's configured identity on the current branch (no invented identities or branches) — then check the box: "- [x] … — fixed in <commit>". (4) Change NOTHING for DECIDE findings — present them in the completion report instead. (5) Honesty law: never fabricate findings to look busy; never check a box without the fix commit existing; never silently turn a DECIDE into a fix. Done when: the audit pass is complete, every new FIX finding has a fix commit and a checked box in ${AUDIT_FINDINGS_REL}, and every DECIDE finding is listed in the file and presented in the completion report.`;
|
|
444
|
+
}
|
package/extensions/loops/goal.ts
CHANGED
|
@@ -165,6 +165,7 @@ import {
|
|
|
165
165
|
respecTarget,
|
|
166
166
|
auditMeasureCmd,
|
|
167
167
|
auditTarget,
|
|
168
|
+
projectAuditTarget,
|
|
168
169
|
HELD_ON_RESTORE,
|
|
169
170
|
type LoopState,
|
|
170
171
|
} from "../goal-loop-forever.js";
|
|
@@ -1106,7 +1107,7 @@ async function retryStoredCompletionAudit(ctx: ExtensionContext, origin: "quota-
|
|
|
1106
1107
|
updateGoal({ status: "auditing" }, liveCtx);
|
|
1107
1108
|
appendLedger(liveCtx.cwd, "goal_resumed", { via: origin === "manual" ? "manual-audit" : "quota-retry-direct-audit" });
|
|
1108
1109
|
liveCtx.ui.notify(origin === "manual"
|
|
1109
|
-
? "Manual /goal
|
|
1110
|
+
? "Manual /goal verify — running the isolated auditor now (no agent turn needed)."
|
|
1110
1111
|
: "Auditor quota window elapsed — retrying the audit with your stored completion claim (no agent turn needed).", "info");
|
|
1111
1112
|
const settings = loadSettings(liveCtx.cwd);
|
|
1112
1113
|
const { model: auditorModel, error: modelError, via } = resolveAuditorModel(liveCtx, settings.auditorModel);
|
|
@@ -1164,7 +1165,7 @@ async function retryStoredCompletionAudit(ctx: ExtensionContext, origin: "quota-
|
|
|
1164
1165
|
updateGoal({ auditHistory: history, pendingCompletion: undefined }, liveCtx);
|
|
1165
1166
|
const objective = state.goal.objective;
|
|
1166
1167
|
archiveCurrentGoal(liveCtx, "complete", `auditor ${result.model} approved (${origin})`);
|
|
1167
|
-
liveCtx.ui.notify(`Goal complete — auditor ${result.model} approved${origin === "manual" ? " on /goal
|
|
1168
|
+
liveCtx.ui.notify(`Goal complete — auditor ${result.model} approved${origin === "manual" ? " on /goal verify" : " on the quota retry"}.`, "info");
|
|
1168
1169
|
notifyExternal(liveCtx, `Goal complete (auditor approved, ${origin}): ${objective.slice(0, 120)}`);
|
|
1169
1170
|
return;
|
|
1170
1171
|
}
|
|
@@ -1445,14 +1446,24 @@ async function cmdGoal(args: string, ctx: ExtensionContext): Promise<void> {
|
|
|
1445
1446
|
if (!shown) ctx.ui.notify("No pending decision — the goal isn't paused on a choice (or no UI).", "info");
|
|
1446
1447
|
return;
|
|
1447
1448
|
}
|
|
1448
|
-
// v0.
|
|
1449
|
+
// v0.29.8: /goal audit [focus] — the ONE-SHOT project audit (user:
|
|
1450
|
+
// "/goal audit IS the audit goal — we are not auditing the current
|
|
1451
|
+
// goal, that happens automatically"). Fire-and-address: one audit
|
|
1452
|
+
// pass, FIX findings fixed autonomously (a bug is not a decision),
|
|
1453
|
+
// DECIDE findings presented, untouched. Runs as a normal goal through
|
|
1454
|
+
// cmdSet — the isolated auditor verifies the finish line.
|
|
1455
|
+
if (route.name === "audit") {
|
|
1456
|
+
return cmdSet(projectAuditTarget(route.rest || undefined), ctx, true);
|
|
1457
|
+
}
|
|
1458
|
+
// v0.28.27 (renamed /goal audit → /goal verify in v0.29.8): run the
|
|
1459
|
+
// isolated auditor on the current goal
|
|
1449
1460
|
// RIGHT NOW, without engaging the agent. The user's "the work looks
|
|
1450
1461
|
// done — just verify it" handle (and the manual counterpart of the
|
|
1451
1462
|
// v0.28.26 stored-claim quota retry). Seeds a synthesized claim so a
|
|
1452
1463
|
// quota block falls into the same pendingCompletion retry machinery.
|
|
1453
|
-
if (route.name === "
|
|
1464
|
+
if (route.name === "verify") {
|
|
1454
1465
|
if (!state.goal) {
|
|
1455
|
-
ctx.ui.notify("No active goal — /goal
|
|
1466
|
+
ctx.ui.notify("No active goal — /goal verify needs a goal to verify.", "warning");
|
|
1456
1467
|
return;
|
|
1457
1468
|
}
|
|
1458
1469
|
if (completionAuditInFlight) {
|
|
@@ -1461,7 +1472,7 @@ async function cmdGoal(args: string, ctx: ExtensionContext): Promise<void> {
|
|
|
1461
1472
|
}
|
|
1462
1473
|
updateGoal({
|
|
1463
1474
|
pendingCompletion: {
|
|
1464
|
-
completionSummary: "Manual audit requested by the user via /goal
|
|
1475
|
+
completionSummary: "Manual audit requested by the user via /goal verify (no agent completion claim). Verify the objective against the repo directly.",
|
|
1465
1476
|
at: nowIso(),
|
|
1466
1477
|
},
|
|
1467
1478
|
}, ctx);
|
|
@@ -4551,6 +4562,37 @@ function cmdAudits(args: string, ctx: ExtensionContext): void {
|
|
|
4551
4562
|
ctx.ui.notify(`glla audits — last ${entries.length} verdict(s) in ${ctx.cwd}\n${formatAuditLog(entries)}`, "info");
|
|
4552
4563
|
}
|
|
4553
4564
|
|
|
4565
|
+
// v0.29.8: /glla status — the unified "what's running" surface (user: "we
|
|
4566
|
+
// need to type goal status [to check], so that command at least is missing
|
|
4567
|
+
// for checking on whatever active process we have"). Read-only aggregate of
|
|
4568
|
+
// the ONE state — goal, list queue, loop, pending decisions — with pointers
|
|
4569
|
+
// to the deep surfaces.
|
|
4570
|
+
function cmdGllaStatus(ctx: ExtensionContext): void {
|
|
4571
|
+
const lines: string[] = [];
|
|
4572
|
+
const g = state.goal;
|
|
4573
|
+
if (g) {
|
|
4574
|
+
const tok = (g.usage?.tokensUsed ?? 0) > 0 ? ` · ${g.usage!.tokensUsed} tok` : "";
|
|
4575
|
+
const audit = g.status === "auditing" ? " (auditor running…)" : "";
|
|
4576
|
+
const pause = g.status === "paused" && g.pauseReason ? ` — ${g.pauseReason.slice(0, 90)}` : "";
|
|
4577
|
+
lines.push(`goal [${g.policy}] ${g.status}${audit}${tok}: ${g.objective.slice(0, 90)}${pause}`);
|
|
4578
|
+
} else {
|
|
4579
|
+
lines.push("goal: none");
|
|
4580
|
+
}
|
|
4581
|
+
const q = listQueue();
|
|
4582
|
+
lines.push(`list: ${q.length === 0 ? "empty" : `${q.length} queued — head: ${(q[0]?.objective ?? "").slice(0, 70)}`}`);
|
|
4583
|
+
const l = state.loop;
|
|
4584
|
+
if (l) {
|
|
4585
|
+
lines.push(`loop: ${l.active ? "ACTIVE" : `held/stopped — ${l.stopReason ?? "n/a"}`} · iter ${l.iteration}/${l.maxIterations > 0 ? l.maxIterations : "∞"} · best ${l.bestValue ?? "n/a"} · stall ${l.stallCount} — ${l.target.slice(0, 60)}`);
|
|
4586
|
+
} else {
|
|
4587
|
+
lines.push("loop: none");
|
|
4588
|
+
}
|
|
4589
|
+
if (g?.status === "paused" && g.pauseKind === "decision" && g.pauseOptions?.length) {
|
|
4590
|
+
lines.push(`decision pending (${g.pauseOptions.length} options) — /goal decide`);
|
|
4591
|
+
}
|
|
4592
|
+
lines.push("deep: /goal status · /list · /loop status · /glla stats · /glla audits · /glla log");
|
|
4593
|
+
ctx.ui.notify(`glla status\n${lines.join("\n")}`, "info");
|
|
4594
|
+
}
|
|
4595
|
+
|
|
4554
4596
|
async function cmdSettings(args: string, ctx: ExtensionContext): Promise<void> {
|
|
4555
4597
|
// The plugin's ONE config surface — global by default, rarely opened.
|
|
4556
4598
|
// /glla show effective values + where each comes from
|
|
@@ -4573,6 +4615,11 @@ async function cmdSettings(args: string, ctx: ExtensionContext): Promise<void> {
|
|
|
4573
4615
|
cmdAudits(trimmed.slice("audits".length).trim(), ctx);
|
|
4574
4616
|
return;
|
|
4575
4617
|
}
|
|
4618
|
+
// v0.29.8: /glla status — the unified what's-running view.
|
|
4619
|
+
if (/^status\b/.test(trimmed)) {
|
|
4620
|
+
cmdGllaStatus(ctx);
|
|
4621
|
+
return;
|
|
4622
|
+
}
|
|
4576
4623
|
// v0.28.28: /glla log [N] — the raw event trail, human-readable. "Log it
|
|
4577
4624
|
// so we can look back and see where we are doing things wrong."
|
|
4578
4625
|
if (/^log\b/.test(trimmed)) {
|
|
@@ -4970,10 +5017,13 @@ export default function (pi: ExtensionAPI): void {
|
|
|
4970
5017
|
description: "Set/draft a goal, or /goal status|pause|resume|cancel|tweak <text>|archive|start <objective>. Objectives without a 'Done when:' clause are grilled into a contract first; include the clause or use /goal start to skip the interview and activate instantly.",
|
|
4971
5018
|
getArgumentCompletions: completions([
|
|
4972
5019
|
["start", "skip drafting — /goal start <objective> activates immediately"],
|
|
5020
|
+
["audit", "one-shot project audit goal: /goal audit [focus] — fix the non-decisions, present the decisions (v0.29.8)"],
|
|
5021
|
+
["verify", "run the isolated auditor on the current goal NOW (v0.28.27, renamed from /goal audit)"],
|
|
4973
5022
|
["status", "show the active goal and its task list"],
|
|
4974
5023
|
["pause", "pause the active goal"],
|
|
4975
5024
|
["resume", "resume a paused goal (and the list, when items are queued)"],
|
|
4976
5025
|
["cancel", "abort the active goal"],
|
|
5026
|
+
["decide", "re-open the decision picker for a decision pause"],
|
|
4977
5027
|
["tweak", "change the objective: /goal tweak <text>"],
|
|
4978
5028
|
["archive", "list archived goals"],
|
|
4979
5029
|
]),
|
|
@@ -4990,6 +5040,7 @@ export default function (pi: ExtensionAPI): void {
|
|
|
4990
5040
|
["autoresume=", "default: hold when a session is loaded, auto-resume on reload/fork; on: always auto-resume; off: never"],
|
|
4991
5041
|
["decisionpopup=", "on|off: decision pauses pop the select() picker (default on; the widget card always lists the options, /goal decide reopens the picker)"],
|
|
4992
5042
|
["auditcap=", "N: pause goal after N consecutive auditor disapprovals (default 5, 0 = unlimited)"],
|
|
5043
|
+
["status", "unified what's-running view: goal + list queue + loop + pending decisions (v0.29.8)"],
|
|
4993
5044
|
["log", "event-trail tail: /glla log [N] — who created/resumed/paused what, from where (v0.28.28)"],
|
|
4994
5045
|
["wipe", "WIPE live glla state (goal archived, list cleared, loop stopped) — one-shot cleanup for leftover-laden projects"],
|
|
4995
5046
|
["resume", "resume WHATEVER is paused/held (goal, list item, or held loop) — no need to know the type"],
|
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.8",
|
|
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",
|