pi-goal-list-loop-audit 0.28.34 → 0.29.0

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 CHANGED
@@ -66,6 +66,7 @@ matches `/list show`.
66
66
  /loop # draft the loop (agent grills; measure is test-run before you confirm)
67
67
  /loop start "keep polishing the UI" # infinite metricless loop (v0.23.6): no plateau, no cap — ends at time=/tokens= or /loop stop
68
68
  /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
69
70
  /loop start "reduce TODOs" measure="grep -c TODO src.txt | head -1" direction=min
70
71
  /loop start "shrink the bundle" measure="..." direction=min time=4 tokens=500000 # arbitrary bounds
71
72
  /loop start "reduce TODOs" measure="..." direction=min branch=1 # scratch-branch mode
@@ -389,3 +389,36 @@ export function resolveSpecFile(cwd: string): string | null {
389
389
  export function respecTarget(specName: string): string {
390
390
  return `Reconcile the codebase against ${specName} (the project spec in the root). Read the spec critically first: if a requirement is stale, contradictory, or wrong for the current codebase, report the discrepancy and move on — never force the code to match a bad spec. Otherwise pick the next gap between spec and code and close it. Rotate: one iteration implements a missing or outdated spec item, the next audits something already "implemented" against the spec and fixes what drifted.`;
391
391
  }
392
+
393
+ // ---- /loop audit (v0.29.0) ----
394
+
395
+ /**
396
+ * The audit loop's findings file — checkbox lines, append-only. The agent
397
+ * appends new findings and checks off fixed ones; the ORCHESTRATOR counts
398
+ * open boxes every iteration. The agent never self-reports progress.
399
+ */
400
+ export const AUDIT_FINDINGS_REL = ".pi-glla/audit-loop/findings.md";
401
+
402
+ /**
403
+ * The audit-loop measure command: count open findings. Prints exactly one
404
+ * number in every file state (missing file / zero matches → 0). This is
405
+ * what respec (metricless) and the reviewer cascade (no termination) both
406
+ * lacked: an honest metric the plateau stop can believe — audits that stop
407
+ * surfacing new findings = the well is dry = the loop ends.
408
+ */
409
+ export function auditMeasureCmd(): string {
410
+ return `c=$(grep -cE '^- \\[ \\]' ${AUDIT_FINDINGS_REL} 2>/dev/null); echo \${c:-0}`;
411
+ }
412
+
413
+ /**
414
+ * The audit target. User's design (2026-07-29): "the looper running audits
415
+ * to see where to progress and what to fix" — the thing that fires at the
416
+ * end of goals and lists, finds the next batch of work, and works it.
417
+ * Each iteration: fresh audit pass → append NEW findings → fix the top
418
+ * open ones → check them off with the fix commit. Honesty laws: never
419
+ * fabricate findings, never rewrite the file's history, never check a box
420
+ * without the fix commit existing.
421
+ */
422
+ export function auditTarget(): string {
423
+ 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.`;
424
+ }
@@ -161,6 +161,8 @@ import {
161
161
  LOOP_DEFAULTS,
162
162
  resolveSpecFiles,
163
163
  respecTarget,
164
+ auditMeasureCmd,
165
+ auditTarget,
164
166
  HELD_ON_RESTORE,
165
167
  type LoopState,
166
168
  } from "../goal-loop-forever.js";
@@ -978,7 +980,12 @@ function archiveCurrentGoal(ctx: ExtensionContext, status: Status, stopReason?:
978
980
  if (goal.policy === "list" && status === "complete") {
979
981
  const advanced = activateNextListItem(ctx);
980
982
  // v0.26.0: the queue just EMPTIED on a completion → list-complete.
981
- if (!advanced) fireReviewer(ctx, { kind: "list", goalId: goal.id, objective: goal.objective, terminal: "goal-complete" });
983
+ if (!advanced) {
984
+ fireReviewer(ctx, { kind: "list", goalId: goal.id, objective: goal.objective, terminal: "goal-complete" });
985
+ // v0.29.0: the well ran dry — point at the project-audit loop. A
986
+ // suggestion, not an action: consent, never auto-start (v0.28.28).
987
+ ctx.ui.notify("List complete. /loop audit to sweep the project for the next batch of work.", "info");
988
+ }
982
989
  return;
983
990
  }
984
991
  // v0.26.0: a /goal (non-list) reached a terminal state → maybe fire.
@@ -2510,6 +2517,34 @@ async function cmdLoop(args: string, ctx: ExtensionContext): Promise<void> {
2510
2517
  return;
2511
2518
  }
2512
2519
 
2520
+ if (sub === "audit") {
2521
+ // v0.29.0: the project-audit loop (user design: "the looper running
2522
+ // audits to see where to progress and what to fix — the thing that
2523
+ // fires at the end of goals and lists"). Unlike respec this is a
2524
+ // METRIC loop: the orchestrator counts open findings every iteration,
2525
+ // direction=min, and the plateau stop is the termination — audits that
2526
+ // stop surfacing new findings = the well is dry. User typed the
2527
+ // command = the act (same auto-start rule as respec).
2528
+ if (state.goal && state.goal.status === "active") {
2529
+ ctx.ui.notify("A goal is active — /goal cancel or /goal pause it before starting a loop.", "warning");
2530
+ return;
2531
+ }
2532
+ if (isLoopActive()) {
2533
+ ctx.ui.notify("A loop is already active. /loop stop first.", "warning");
2534
+ return;
2535
+ }
2536
+ await startLoopFromConfig(ctx, {
2537
+ target: auditTarget(),
2538
+ measureCmd: auditMeasureCmd(),
2539
+ direction: "min",
2540
+ plateauWindow: LOOP_DEFAULTS.plateauWindow,
2541
+ maxIterations: 0,
2542
+ branch: false,
2543
+ force: false,
2544
+ });
2545
+ return;
2546
+ }
2547
+
2513
2548
  if (sub === "respec") {
2514
2549
  // v0.24.3: reconcile the codebase against the root spec, forever.
2515
2550
  // Same auto-start path as /loop start (the user typed the command —
@@ -4850,6 +4885,7 @@ export default function (pi: ExtensionAPI): void {
4850
4885
  getArgumentCompletions: completions([
4851
4886
  ["start", "skip drafting: /loop start \"<target>\" measure=\"<cmd>\" direction=min|max [window=5] [max=50]"],
4852
4887
  ["respec", "infinite metricless loop reconciling the codebase against the root SPEC.md"],
4888
+ ["audit", "project-audit loop: each iteration audits fresh, appends findings, fixes the top ones — plateau stops when the well is dry (v0.29.0)"],
4853
4889
  ["status", "show metric, iteration, best/last values, stall count"],
4854
4890
  ["stop", "end the loop (keeps the best state)"],
4855
4891
  ["cancel", "alias of /loop stop — end the loop"],
@@ -40,7 +40,7 @@ export const DEFAULT_REVIEWER_CONFIG: ReviewerConfig = {
40
40
  mode: "on",
41
41
  fireOn: ["goal-complete", "list-complete"],
42
42
  doNotFireOn: ["goal-aborted", "goal-paused"],
43
- cascade: ["convert-findings-to-list", "queue-leftovers", "fire-audit-on-clean", "notify-and-idle"],
43
+ cascade: ["convert-findings-to-list", "queue-leftovers", "notify-and-idle"],
44
44
  auditCadence: "every-clean-completion",
45
45
  auditScope: "regression-scan",
46
46
  leverageMode: "fix-without-confirm",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-goal-list-loop-audit",
3
- "version": "0.28.34",
3
+ "version": "0.29.0",
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",