pi-goal-list-loop-audit 0.38.21 → 0.38.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/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.38.22 — subagent display unification: richness ladder + upstream triple-render report (2026-09-05)
4
+
5
+ ### Fixed
6
+ - Subagent display unification (field: triple-rendered run panels swapping order with agent prose, 2026-09-05 screenshot). New `subagentDisplayRichness` setting (`/glla` → Subagents): `rich` (default — detailed worker rows + the task-linkage header `→ <objective>` native UI can never show), `compact` (today's count line), `quiet` (hung/aborting workers only — HUNG is never silent at any level). Rich is safe against the v0.37.1 jumping because `renderAgentsWidgetLines` now buckets silence ages exactly like the compact line, so the widget key only moves on genuine state transitions. Status-bar worker count follows the same ladder automatically. `/glla agents` keeps full detail regardless. Upstream triple-render + order-swap filed as nicobailon/pi-subagents#1931 (read-only diagnosis; GLLA cannot suppress/reorder/merge native panels — no ordering API, transcript components order by arrival); README documents the coexistence escapes (`inlineToolDisplay: "summary"` + `fleetViewPlacement` pin). Coverage: `tests/subagent-display-richness.test.ts` (5 tests: default/normalization, ladder assembly + linkage header, bucket stability, hung invariant, width safety).
7
+
3
8
  ## 0.38.21 — objection-attached retries + PR #43 auditor observability (2026-09-04)
4
9
 
5
10
  ### Fixed
package/README.md CHANGED
@@ -298,6 +298,16 @@ GLLA is the supervisor. These companions add capabilities around it:
298
298
  sequential goal can still run cleanly without workers — install when
299
299
  parallelism will pay for its coordination and model usage.
300
300
 
301
+ Display coexistence: pi-subagents renders its own inline run panels +
302
+ FleetView, GLLA renders one compact widget line + the status-bar worker
303
+ count + `/glla agents`. If you see the same run stacked 3× or panels
304
+ swapping order, set pi-subagents `inlineToolDisplay: "summary"` (one
305
+ stable row per run) and pin `fleetViewPlacement`; GLLA's own richness is
306
+ the `subagentDisplayRichness` setting (`/glla` → Subagents): `rich`
307
+ (default — worker rows + task linkage), `compact` (count line), `quiet`
308
+ (hung/aborting workers only). Upstream triple-render report:
309
+ nicobailon/pi-subagents#1931.
310
+
301
311
  Install (or keep pinned):
302
312
 
303
313
  ```bash
@@ -74,3 +74,17 @@ children so idle rigs see no change.
74
74
  pin hung classification, cap behavior, loud-missing-file behavior for
75
75
  --tail, and widget hide-at-zero.
76
76
  - Version + CHANGELOG + README at ship time; full release gate.
77
+
78
+ ## v0.38.22 supersede — display unification (2026-09-05)
79
+
80
+ The compact-only doctrine above was the v0.37.1 jitter fix (raw per-second
81
+ silence ages re-laid out the editor every tick). v0.38.22 keeps the doctrine's
82
+ safety property by other means — `renderAgentsWidgetLines` buckets silence
83
+ ages exactly like the compact line, so the widget key only moves on genuine
84
+ state transitions — and restores rich ambient rows behind the
85
+ `subagentDisplayRichness` ladder (`rich` default / `compact` / `quiet`, HUNG
86
+ never silent), plus the task-linkage header (`→ <objective>`) only GLLA can
87
+ show. Triplication/ordering against pi-subagents native panels is upstream
88
+ (nicobailon/pi-subagents#1931, read-only); GLLA owns its slot only and
89
+ documents the native escapes. Assembly is the pure `assembleAgentsExtras`
90
+ (pinned in `tests/subagent-display-richness.test.ts`).
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.21 continue through the supervisor freeze (`/glla pause`),
21
+ v0.35.14–v0.38.22 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
@@ -159,12 +159,45 @@ export function renderAgentsWidgetLines(rows: AgentsPanelRow[], now = Date.now()
159
159
  lines.push(`${rowLabel(row)} · id ${cleanField(row.recordId, 10)}`);
160
160
  const evidence = row.evidence !== "live" ? ` · ${row.evidence}` : "";
161
161
  const action = row.action === "abort-requested" ? " · aborting" : row.action === "unavailable" ? " · abort unavailable" : row.action === "failed" ? " · abort failed" : "";
162
- lines.push(` ${rowStateWord(row, now)} · silent ${fmtDuration(row.silentMs)}${evidence}${action}`);
162
+ // v0.38.22 (display unification): bucket the silence age like the
163
+ // compact line — raw per-second values churn the widget key and
164
+ // re-layout the editor every tick (the v0.37.1 jumping, reintroduced
165
+ // the moment rich lines render ambiently).
166
+ lines.push(` ${rowStateWord(row, now)} · silent ${fmtDuration(bucketSilentMs(row.silentMs))}${evidence}${action}`);
163
167
  }
164
168
  if (active.length > shown.length) lines.push(`… ${active.length - shown.length} more agents · /glla agents`);
165
169
  return lines;
166
170
  }
167
171
 
172
+ /** v0.38.22: safety invariant for the richness ladder — HUNG/aborting
173
+ * workers are never silent, so `quiet` still surfaces them. */
174
+ export function hasHungWorker(rows: AgentsPanelRow[]): boolean {
175
+ return rows.some((r) => r.status !== "ended" && (r.status === "hung" || r.action === "abort-requested"));
176
+ }
177
+
178
+ export type AgentsExtras = { line: string; lines: string[] };
179
+
180
+ /** v0.38.22 (display unification): the pure richness switch behind the
181
+ * widget/status worker presence. Rich restores detailed rows (capped,
182
+ * bucketed — the widget key only moves on genuine state transitions)
183
+ * plus the task-linkage header native UI can never show; compact keeps
184
+ * the count line; quiet surfaces hung/aborting workers only. Pure and
185
+ * hermetic for tests; the caller supplies rows + richness + objective. */
186
+ export function assembleAgentsExtras(
187
+ rows: AgentsPanelRow[],
188
+ richness: "rich" | "compact" | "quiet",
189
+ objective: string,
190
+ now = Date.now(),
191
+ ): AgentsExtras | undefined {
192
+ const line = renderAgentsWidgetLine(rows);
193
+ if (!line) return undefined;
194
+ if (richness === "quiet" && !hasHungWorker(rows)) return undefined;
195
+ if (richness !== "rich") return { line, lines: [] };
196
+ const clean = objective.replace(/\s+/g, " ").trim();
197
+ const header = clean ? [`→ ${truncate(clean, 60)}`] : [];
198
+ return { line, lines: [...header, ...renderAgentsWidgetLines(rows, now)] };
199
+ }
200
+
168
201
  /** The compact footer summary: count + the least-live child.
169
202
  * v0.37.1 (ui-jitter fix): bucket the silent age so the status/widget
170
203
  * text stays stable between ticks — a per-second change made the footer
@@ -26,6 +26,8 @@ import {
26
26
  piGlaDir,
27
27
  } from "./goal-loop-core.ts";
28
28
  import type { SubagentModelStrategy } from "./goal-loop-subagents.js";
29
+ /** v0.38.22: ambient worker display richness (see subagentDisplayRichness). */
30
+ export type SubagentDisplayRichness = "rich" | "compact" | "quiet";
29
31
  import {
30
32
  DEFAULT_MAIN_MODEL_PRIMARY_PROBE_MINUTES,
31
33
  normalizeMainModelFallbackRefs,
@@ -243,6 +245,12 @@ export interface Settings {
243
245
  /** v0.27.5: post-completion audit config. Same shape as `reviewer`. */
244
246
  postaudit?: Record<string, unknown>;
245
247
  subagentModelStrategy?: SubagentModelStrategy;
248
+ /** v0.38.22 (display unification): ambient worker richness. `rich`
249
+ * (default) shows detailed worker rows + the task-linkage header;
250
+ * `compact` shows the single count line; `quiet` shows worker presence
251
+ * only when a child is hung/aborting — HUNG is never silent at any
252
+ * level. `/glla agents` keeps full detail regardless. */
253
+ subagentDisplayRichness?: SubagentDisplayRichness;
246
254
  /** Per-agent-type model pin, e.g. { "scout": "minimax/MiniMax-M3" }.
247
255
  * Always wins over subagentModelStrategy — the managed override is written
248
256
  * WITH this pin regardless of strategy. */
@@ -345,6 +353,9 @@ export const DEFAULT_SETTINGS: Settings = {
345
353
  // v0.24.6: subagents inherit the session model by default, avoiding a
346
354
  // surprise provider/model pin from the upstream default agent.
347
355
  subagentModelStrategy: "inherit-parent",
356
+ // v0.38.22 (display unification): rich by default — full worker rows +
357
+ // task linkage; trimmable to compact/quiet, never silent on hangs.
358
+ subagentDisplayRichness: "rich",
348
359
  auditFeedbackChars: DEFAULT_AUDIT_FEEDBACK_CHARS,
349
360
  // v0.34.141: keep-going is the production default. Set false explicitly
350
361
  // for the conservative pause-first policy; the dial flips DEFAULTS, never
@@ -376,7 +387,7 @@ export function readSettingsFile(file: string): Partial<Settings> {
376
387
  }
377
388
  }
378
389
 
379
- function normalizeLoadedSettings(settings: Settings): Settings {
390
+ export function normalizeLoadedSettings(settings: Settings): Settings {
380
391
  // Settings files can be edited by hand or survive an older UI. Normalize
381
392
  // the main fallback chain at every read so runtime, display, and persistence
382
393
  // all see the same bounded value.
@@ -402,6 +413,13 @@ function normalizeLoadedSettings(settings: Settings): Settings {
402
413
  if (settings.stateRoot !== "sessionDir" && settings.stateRoot !== "workingDir") {
403
414
  settings.stateRoot = "workingDir";
404
415
  }
416
+ // v0.38.22: hand-edited richness falls back to rich (the default) —
417
+ // unknown values must not blank the worker display.
418
+ if (settings.subagentDisplayRichness !== "rich"
419
+ && settings.subagentDisplayRichness !== "compact"
420
+ && settings.subagentDisplayRichness !== "quiet") {
421
+ settings.subagentDisplayRichness = "rich";
422
+ }
405
423
  if (settings.mainModelFailback !== "auto" && settings.mainModelFailback !== "sticky") {
406
424
  settings.mainModelFailback = "auto";
407
425
  }
@@ -293,6 +293,7 @@ import {
293
293
  syncSubagentModelOverrides,
294
294
  type SubagentModelStrategy,
295
295
  } from "../goal-loop-subagents.js";
296
+ import type { SubagentDisplayRichness } from "../goal-settings.js";
296
297
  import {
297
298
  buildSettingsRows,
298
299
  SettingsMenuComponent,
@@ -1578,6 +1579,19 @@ export async function handleSettingChoice(id: string, ctx: ExtensionContext): Pr
1578
1579
  }
1579
1580
  return;
1580
1581
  }
1582
+ case "subagentDisplayRichness": {
1583
+ const v = await ctx.ui.select("Subagent display richness (ambient worker UI)", [
1584
+ "rich — worker rows + task linkage (recommended)",
1585
+ "compact — the count line only",
1586
+ "quiet — hung/aborting workers only (HUNG is never silent)",
1587
+ ]);
1588
+ if (v) {
1589
+ const richness: SubagentDisplayRichness = v.startsWith("compact") ? "compact" : v.startsWith("quiet") ? "quiet" : "rich";
1590
+ saveSettings("global", ctx.cwd, { subagentDisplayRichness: richness });
1591
+ ctx.ui.notify(`Subagent display richness saved (${richness}) — applies on the next UI refresh.`, "info");
1592
+ }
1593
+ return;
1594
+ }
1581
1595
  case "subagentResolved":
1582
1596
  // Read-only (effective resolution row) — no editor; row just shows the
1583
1597
  // current effective subagent models. Treat as no-op.
@@ -265,7 +265,7 @@ import {
265
265
  type HeartbeatFlags,
266
266
  } from "../goal-heartbeat.js"; // decomposition step 4 (v0.34.112)
267
267
  import { getSubagentAgentsSnapshot } from "../goal-heartbeat.js";
268
- import { renderAgentsWidgetLine, type AgentsPanelRow } from "../goal-agents-panel.js";
268
+ import { assembleAgentsExtras, type AgentsPanelRow } from "../goal-agents-panel.js";
269
269
  import {
270
270
  clearMainModelRecoveryTimer,
271
271
  createGoalRecovery,
@@ -797,18 +797,19 @@ function refreshUI(ctx: ExtensionContext, force = false): void {
797
797
  const extras = {
798
798
  stalls: consecutiveStalls,
799
799
  recent: recentActions,
800
- // v0.37.1 (ui-jitter fix): compact-only widget — one stable footer
801
- // line "● N agents · scout silent Xm". Detailed per-agent rows live
802
- // in `/glla agents` / `--tail` (DESIGN intent); splicing 2 lines per
803
- // scout into the above-editor card made height swing 4→10 lines and
804
- // re-laid out the editor every 2–5s. Keep lines empty so
805
- // buildWidgetLines does not splice.
800
+ // v0.38.22 (display unification): richness ladder for ambient
801
+ // workers — `rich` (default) restores the detailed rows the v0.37.1
802
+ // jitter fix removed, now safe because silence ages are bucketed
803
+ // (widget key only changes on genuine state transitions, not every
804
+ // tick) plus the task-linkage header native UI can never show.
805
+ // `compact` keeps the single line; `quiet` surfaces hung/aborting
806
+ // workers only (HUNG is never silent at any level).
806
807
  ...(() => {
807
808
  try {
808
809
  const { agents } = getSubagentAgentsSnapshot();
809
810
  const rows = agents as AgentsPanelRow[];
810
- const line = renderAgentsWidgetLine(rows);
811
- return line ? { agents: { line, lines: [] } } : {};
811
+ const extras = assembleAgentsExtras(rows, settings.subagentDisplayRichness ?? "rich", state.goal?.objective ?? "", now);
812
+ return extras ? { agents: extras } : {};
812
813
  } catch { return {}; }
813
814
  })(),
814
815
  ...activity,
@@ -557,6 +557,15 @@ export function buildSettingsRows(
557
557
  description:
558
558
  "inherit-parent shares your session model; agent-default uses upstream defaults; Designer remains available as a glla role",
559
559
  });
560
+ rows.push({
561
+ id: "subagentDisplayRichness",
562
+ section: "subagents",
563
+ label: "Subagent display richness",
564
+ valueText: show("subagentDisplayRichness", "rich"),
565
+ sourceText: src("subagentDisplayRichness"),
566
+ description:
567
+ "rich shows worker rows + task linkage (default); compact shows the count line; quiet shows hung/aborting workers only — HUNG is never silent",
568
+ });
560
569
  for (const name of OVERRIDABLE_AGENT_TYPES) {
561
570
  rows.push({
562
571
  id: `subagentModelOverrides.${name}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-goal-list-loop-audit",
3
- "version": "0.38.21",
3
+ "version": "0.38.22",
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",