pi-goal-list-loop-audit 0.38.7 → 0.38.9

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.38.9 — over-cap strategy stated and pinned (2026-09-03)
4
+
5
+ ### Added
6
+ Explicit rung order for over-cap + model-can't-compress: always-on checkpoint projection (trim), guarded fallback-chain rotation on compact failure, `/new` + resume from durable state as the backstop — with the viability ranking (switch when a bigger model exists, `/new` when none can compress). Runbook in `audit/OVERCAP-STRATEGY-2026-09-03.md`.
7
+
8
+ ### Fixed
9
+ Stale advice: the ladder no longer advises a `/compact` retry when one already failed inside the 90s grace window (`recentCompact` → step (1) points at (2)/(3)). `tests/overcap-strategy.test.ts` (3 tests) pins the skip shape and both behavioral chain branches (rotation with chain, honest ladder without).
10
+
11
+ ## 0.38.8 — TUI information-density pass (2026-09-03)
12
+
13
+ ### Added
14
+ Widget `audits:` row (verdict tally, width-truncated, silent when empty); verdict tally suffix on all paused status lines via `pausedStatusSuffix`; per-tab row counts in the settings menu (`settingsTabLabel`, pure). Starvation ladder reflowed to one recovery per line, same content and phrases.
15
+
16
+ ### Fixed
17
+ Glance-density gaps: parked sessions read as waiting-with-history instead of dead; ladder recoveries scannable; settings tabs locate content. Display-only — no automation, hold, auditor, or menu-structure changes. `tests/tui-density.test.ts` (5 tests) pins all four surfaces plus an 80-column widget fit; before/after captures in `audit/TUI-DENSITY-2026-09-03.md`.
18
+
3
19
  ## 0.38.7 — session visibility: recovery banner + durable verdict tally (2026-09-03)
4
20
 
5
21
  ### Added
package/docs/INDEX.md CHANGED
@@ -18,7 +18,7 @@ For shipped docs, the relevant entry points are:
18
18
  failback; v0.35.9 hardened cross-version npm tarball checks; v0.35.10
19
19
  handles multi-entry npm dry-run reports; v0.35.11 accepts both npm report
20
20
  shapes; v0.35.12 supports npm 12's keyed pack reports; v0.35.13 fixes stale-API recovery loops.
21
- v0.35.14–v0.38.7 continue through the supervisor freeze (`/glla pause`),
21
+ v0.35.14–v0.38.9 continue through the supervisor freeze (`/glla pause`),
22
22
  load hold, auditor picker parity, Windows launch fix, zombie-watchdog
23
23
  subagent carve-out, due-wait backstop, the `/glla agents` visibility panel,
24
24
  durable state-root selection, blank-until-resume auditor context, frozen
@@ -923,10 +923,14 @@ function pausedStatusSuffix(g: Goal, state: State, extras: WidgetExtras | undefi
923
923
  const queueLabel = (state.list?.length ?? 0) > 0 ? `${state.list!.length} queued` : "queue empty";
924
924
  const lifecycleText = lifecycle.replace(/^lifecycle: /, "");
925
925
  const repair = g.repairTarget ? ` · replan required: ${truncate(g.repairTarget.objective.replace(/\s+/g, " "), 100)}` : "";
926
+ // v0.38.8: parked goals carry their verdict tally — a paused session
927
+ // with 2 disapprovals reads as "waiting with history", not dead.
928
+ const tallyText = formatVerdictTallySegment(auditorVerdictTally(g.auditHistory, now), now);
929
+ const verdict = tallyText ? ` · ${tallyText}` : "";
926
930
  if (queueFirst) {
927
- return ` · ${queueLabel} · ${lifecycleText.replace(` · ${queueLabel}`, "")} · ${transition}${repair}`;
931
+ return ` · ${queueLabel} · ${lifecycleText.replace(` · ${queueLabel}`, "")} · ${transition}${repair}${verdict}`;
928
932
  }
929
- return ` · ${lifecycleText} · ${transition}${repair}`;
933
+ return ` · ${lifecycleText} · ${transition}${repair}${verdict}`;
930
934
  }
931
935
 
932
936
  /**
@@ -1424,6 +1428,13 @@ function goalLines(g: Goal, state: State, audit: AuditDisplayProgress | null | u
1424
1428
  : 48;
1425
1429
  const head = `${icon} ${truncate(g.objective.replace(/\s+/g, " "), objBudget)} ${paint(theme, "dim", "·")} ${segsText}`;
1426
1430
  const lines = [head];
1431
+ // v0.38.8: durable verdict tally as a first-class card row — the widget
1432
+ // is the glance surface, and stored verdicts are the progress evidence
1433
+ // when no auditor is live. Silent when history is empty.
1434
+ const headTally = formatVerdictTallySegment(auditorVerdictTally(g.auditHistory, now), now);
1435
+ if (headTally) {
1436
+ lines.push(`├─ ${paint(theme, "dim", `audits: ${truncate(headTally, Math.max(20, (width ?? 80) - 12))}`)}`);
1437
+ }
1427
1438
  if (g.repairTarget) {
1428
1439
  lines.push(`├─ ${paint(theme, "warning", `REPLAN REQUIRED · original target: ${truncate(g.repairTarget.objective.replace(/\s+/g, " "), Math.max(30, (width ?? 80) - 28))}`)}`);
1429
1440
  const repairStep = g.repairTarget.replanPromptedAt
@@ -2008,11 +2008,8 @@ export function registerGoalRuntime(pi: ExtensionAPI): void {
2008
2008
  return;
2009
2009
  }
2010
2010
  }
2011
- // v0.38.6: the yield now carries the full over-cap ladder (retry
2012
- // /compact after GLLA's deterministic trim, larger-context model,
2013
- // /new + resume from durable state) instead of only the auto-compact
2014
- // pointer — field 2026-09-03: summarization itself was failing.
2015
- ctx.ui.notify(buildStarvationLadderMessage({ percent: typeof contextUsage?.percent === "number" ? contextUsage.percent : null, streak: starved.streak }), "info");
2011
+ // Ladder banner (v0.38.6; v0.38.9 skips stale step 1 after a failed compact-and-retry).
2012
+ ctx.ui.notify(buildStarvationLadderMessage({ percent: typeof contextUsage?.percent === "number" ? contextUsage.percent : null, streak: starved.streak, recentCompact: sinceLastCompactMs < COMPACTION_GRACE_MS }), "info");
2016
2013
  return;
2017
2014
  }
2018
2015
  if (lc.giveUpNow) {
@@ -317,7 +317,7 @@ interface GoalRuntimeDataTypes {
317
317
  lastContextStarvedAt: number;
318
318
  noteContextPercent: (pct: number | null | undefined) => void;
319
319
  shouldCompactFirstNudge: (percent: number | null | undefined) => boolean;
320
- buildStarvationLadderMessage: (input?: { percent?: number | null; streak?: number }) => string;
320
+ buildStarvationLadderMessage: (input?: { percent?: number | null; streak?: number; recentCompact?: boolean }) => string;
321
321
  COMPACT_FIRST_NUDGE_PERCENT: number;
322
322
  lastContextPercent: number | null;
323
323
  postCompactResumeOwed: boolean;
@@ -993,15 +993,22 @@ export function shouldCompactFirstNudge(percent: number | null | undefined): boo
993
993
  /** v0.38.6: the over-cap ladder, user-facing. Three recoveries in order
994
994
  * (retry /compact after GLLA's deterministic trim, larger-context model,
995
995
  * /new + resume from durable state) plus the no-LLM backstop: the
996
- * post-compact resync re-anchors a fresh session with no summarization. */
997
- export function buildStarvationLadderMessage(input: { percent?: number | null; streak?: number } = {}): string {
996
+ * post-compact resync re-anchors a fresh session with no summarization.
997
+ * `recentCompact` skips the stale retry (v0.38.9). */
998
+ export function buildStarvationLadderMessage(input: { percent?: number | null; streak?: number; recentCompact?: boolean } = {}): string {
998
999
  const at = typeof input.percent === "number" && Number.isFinite(input.percent)
999
1000
  ? `${input.percent.toFixed(1)}%` : "nearly full";
1000
- return `glla: output-token stop was context starvation (tiny output at ${at} context) — yielding to pi auto-compaction instead of re-sending. ` +
1001
- `If compaction fails or context is already over cap, in order: (1) run /compact again — GLLA already trimmed repeat payloads to a checkpoint, so the retry may now fit; ` +
1002
- `(2) switch to a larger-context model, then /compact (GLLA auto-rotates its fallback chain after a failed compact-and-retry); ` +
1003
- `(3) /new, then /goal resume — the goal, tasks, ledger and audits are durable on disk, and the post-compact resync re-anchors the fresh session with no summarization needed. ` +
1004
- `Automatic turns stay parked until a real compaction lands.`;
1001
+ // One recovery per line (v0.38.8) — same content, scannable shape.
1002
+ return [
1003
+ `glla: output-token stop was context starvation (tiny output at ${at} context) — yielding to pi auto-compaction instead of re-sending.`,
1004
+ `If compaction fails or context is already over cap, in order:`,
1005
+ input.recentCompact === true
1006
+ ? `(1) skip the /compact retry — one already failed within the last 90s; the trim below already ran, so go straight to (2)/(3);`
1007
+ : `(1) run /compact again — GLLA already trimmed repeat payloads to a checkpoint, so the retry may now fit;`,
1008
+ `(2) switch to a larger-context model, then /compact (GLLA auto-rotates its fallback chain after a failed compact-and-retry);`,
1009
+ `(3) /new, then /goal resume — the goal, tasks, ledger and audits are durable on disk, and the post-compact resync re-anchors the fresh session with no summarization needed.`,
1010
+ `Automatic turns stay parked until a real compaction lands.`,
1011
+ ].join("\n");
1005
1012
  }
1006
1013
  function noteContextStarvedYield(): { streak: number; shouldRefuse: boolean } {
1007
1014
  const now = Date.now();
@@ -58,6 +58,10 @@ export type SettingsSectionId =
58
58
  | "stall-brakes"
59
59
  | "other";
60
60
 
61
+ /** v0.38.8: tab label with its row count — pure so tests pin the shape. */
62
+ export function settingsTabLabel(label: string, rowCount: number): string {
63
+ return rowCount > 0 ? `${label} (${rowCount})` : label;
64
+ }
61
65
  export const SETTINGS_SECTIONS: readonly { id: SettingsSectionId; label: string }[] = [
62
66
  { id: "keep-going", label: "Keep-going" },
63
67
  { id: "main-agent", label: "Main agent" },
@@ -766,11 +770,15 @@ export class SettingsMenuComponent implements Component {
766
770
 
767
771
  // v0.28.19: color-only tabs (user call: "dropping the brackets") —
768
772
  // active = accent + bold, inactive = dim. No bracket chrome.
773
+ // v0.38.8: per-tab row counts — the menu holds 7 sections and the
774
+ // count says where the settings live at a glance.
775
+ const tabLabel = (s: { id: SettingsSectionId; label: string }): string =>
776
+ settingsTabLabel(s.label, this.rows.filter((r) => r.section === s.id).length);
769
777
  lines.push(
770
778
  SETTINGS_SECTIONS.map((s, i) =>
771
779
  i === this.activeSectionIdx
772
- ? this.theme.fg("accent", this.theme.bold(s.label))
773
- : this.theme.fg("dim", s.label),
780
+ ? this.theme.fg("accent", this.theme.bold(tabLabel(s)))
781
+ : this.theme.fg("dim", tabLabel(s)),
774
782
  ).join(" "),
775
783
  );
776
784
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-goal-list-loop-audit",
3
- "version": "0.38.7",
3
+ "version": "0.38.9",
4
4
  "description": "Mission control for autonomous pi: interview-drafted goals, an audited task queue, and forever-loops (metric, spec, project-audit) that run for hours. A detached extension-less auditor process re-verifies every completion with raw evidence without holding the main pi turn; confirmed drafts, decision pauses and consent gates keep you in charge.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "author": "dracon",