pi-goal-list-loop-audit 0.36.0 → 0.37.1

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/INSTALL.md +11 -8
  3. package/LIST-PHILOSOPHY.md +1 -1
  4. package/README.md +44 -22
  5. package/docs/DESIGN-long-running-supervision.md +5 -0
  6. package/docs/DESIGN.md +40 -0
  7. package/docs/INDEX.md +11 -10
  8. package/extensions/goal-agents-panel.ts +32 -5
  9. package/extensions/goal-commands.ts +69 -25
  10. package/extensions/goal-continuation.ts +1 -1
  11. package/extensions/goal-heartbeat.ts +259 -14
  12. package/extensions/goal-loop-auditor-process.ts +160 -8
  13. package/extensions/goal-loop-auditor.ts +18 -5
  14. package/extensions/goal-loop-core.ts +650 -53
  15. package/extensions/goal-loop-display.ts +59 -9
  16. package/extensions/goal-loop-forever.ts +5 -5
  17. package/extensions/goal-loop-shield.ts +358 -40
  18. package/extensions/goal-loop-stats.ts +35 -20
  19. package/extensions/goal-loop-subagents.ts +177 -201
  20. package/extensions/goal-loop.ts +14 -10
  21. package/extensions/goal-recovery.ts +35 -10
  22. package/extensions/goal-settings.ts +66 -11
  23. package/extensions/goal-state.ts +2 -20
  24. package/extensions/loops/goal-activation.ts +105 -15
  25. package/extensions/loops/goal-auditor-hooks.ts +93 -26
  26. package/extensions/loops/goal-list-queue.ts +6 -6
  27. package/extensions/loops/goal-orchestrator.ts +113 -29
  28. package/extensions/loops/goal-runtime-globals.ts +564 -221
  29. package/extensions/loops/goal-session.ts +35 -21
  30. package/extensions/loops/goal-settings-ui.ts +85 -34
  31. package/extensions/loops/goal-tools.ts +91 -17
  32. package/extensions/loops/goal-ui.ts +163 -20
  33. package/extensions/loops/goal.ts +1 -1
  34. package/extensions/model-selector.ts +3 -2
  35. package/extensions/settings-menu.ts +28 -2
  36. package/package.json +3 -3
  37. package/prompts/goal-loop-continuation.md +3 -3
  38. package/prompts/goal-loop-draft.md +2 -2
  39. package/prompts/goal-loop-forever-metricless.md +3 -3
  40. package/prompts/goal-loop-forever.md +3 -3
  41. package/prompts/goal-loop-plan-loop.md +1 -1
  42. package/prompts/goal-loop-plan.md +1 -1
  43. package/scripts/goal-auditor-worker.mjs +49 -0
  44. package/scripts/release-pack-smoke.mjs +97 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,106 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.37.1 — auditor watchdogs, continuous list handoff, and audit hardening (2026-09-01)
4
+
5
+ ### Added
6
+ Configurable detached-auditor watchdog budgets (`auditorToolTimeoutMs` and
7
+ `auditorStallMs`, global-scope settings edited via `/glla` with plain-ms or
8
+ s/m/h duration input) replace the hardcoded 5-minute per-tool and 10-minute
9
+ no-progress defaults. Both dispatch sites now thread the configured values
10
+ into the parent watchdogs AND into the worker environment
11
+ (`GLLA_AUDITOR_TOOL_TIMEOUT_MS` / `GLLA_AUDITOR_STALL_MS`), so parent and
12
+ worker can never disagree about who kills first.
13
+
14
+ Adaptive timeout escalation for stalled auditor attempts: each consecutive
15
+ kill-and-restart of the same claim doubles the per-tool and first-event
16
+ budgets (capped at 4x the configured base), persisted on the durable claim
17
+ as `timeoutEscalation` so slow local models get a growing budget instead of
18
+ an identical kill-and-restart loop on every restart.
19
+
20
+ Progress-aware watchdog: the parent progress signature now includes streamed
21
+ report bytes, so an actively-streaming model (including extended thinking
22
+ between tool calls) registers as live progress instead of tripping the
23
+ no-progress kill; the quiet-phase UI warning is suppressed while a tool is
24
+ legitimately running inside its effective budget and shows the budget on
25
+ the live tool line.
26
+
27
+ ### Changed
28
+ The recommended parallel-orchestration companion is now **pinned**
29
+ `pi-subagents@0.62.0` — the power-max choice for GLLA. GLLA tracks its
30
+ versioned `subagent:*` lifecycle, durable async status artifacts, and v1
31
+ stop RPC while retaining a bounded compatibility path for older providers.
32
+ The model settings surface now uses the current `scout`/`researcher`/
33
+ `worker`/`reviewer`/`oracle`/`delegate` roles; current built-ins inherit
34
+ the parent model by default. Do not stack `@tintinweb/pi-subagents` or
35
+ `@quintinshaw/pi-dynamic-workflows` as a second orchestrator alongside it.
36
+ See `audit/SUBAGENT-PACKAGE-SELECTION-2026-09-01.md` (five-package power audit).
37
+
38
+ ### Fixed
39
+ Completed standalone goals now hand off to an already-waiting list and arm
40
+ the same bounded completion-settle window used by list-item cascades. The
41
+ explicit `/glla resume` surface now hydrates and starts a waiting-only queue,
42
+ while aborts, loop ownership, suspicious-objective, sidecar, and persistence
43
+ fences remain intact. Waiting-list cards name `/glla resume` as the recovery
44
+ action and retain `/list next` for deliberate skip/selection.
45
+
46
+ Durable state transitions and deferred settle repaints now bypass the
47
+ periodic UI throttle, while unchanged activity/ticker updates remain
48
+ cadence-limited. A replacement host therefore gets its first paint and
49
+ meaningful durable status changes cannot remain visually stale.
50
+
51
+ Detached-auditor payload blocks now escape XML-like delimiters in goal,
52
+ completion, verification, and shield data so untrusted text cannot close a
53
+ prompt boundary or impersonate prompt structure.
54
+
55
+ TUI jitter under scout fan-out is fixed: the above-editor widget now shows
56
+ only the compact one-line summary `● N agents · <busiest> silent Xm`
57
+ (bucketed 5s/<1m, 15s/<5m, 30s otherwise) instead of splicing 2 lines per
58
+ scout into the card. Detailed per-agent rows remain in `/glla agents` and
59
+ `--tail` as designed (docs/DESIGN-subagent-visibility.md), so height no
60
+ longer swings 4→10 lines and the editor layout stays stable under
61
+ `scout x3` / 150+ tool-use fan-outs.
62
+
63
+ Recovery and session-handoff freshness now rejects future-dated sidecars,
64
+ preventing an edited or clock-skewed marker from triggering an unexpected
65
+ resume or deferred-list replay.
66
+
67
+ Tracked child transcript tails use the persisted session id for direct
68
+ lookup, so older children remain inspectable without an unbounded directory
69
+ scan. List-audit fan-out now reads the configured state root, including
70
+ `sessionDir`, instead of assuming `<cwd>/.pi-glla`.
71
+
72
+ ## 0.36.1 — crash-safe persistence and packed-release verification (2026-08-31)
73
+
74
+ ### Fixed
75
+ Terminal archival now records a durable intent before publication and
76
+ reconciles interrupted archive/state commits on startup, preventing a
77
+ published archive from resurrecting an active goal or permanently fencing
78
+ the next archive attempt.
79
+
80
+ Destructive queue operations now fail closed when sidecar cleanup cannot be
81
+ proven successful. List clear/cancel/remove, group close, carryover, wipe,
82
+ and repair-source consumption preserve recoverable durable work instead of
83
+ mutating memory and allowing a failed deletion to reappear after restart.
84
+
85
+ The active ledger now rotates into immutable, ownership-fenced segments and
86
+ keeps a complete current-state snapshot in the active file. Startup recovery
87
+ handles the rename-before-rewrite interruption window while forensic history
88
+ remains available.
89
+
90
+ Bounded scanners and streaming reducers now back list depth, log tails,
91
+ switch logs, postaudit cadence, and multi-project statistics. Detached
92
+ auditor scratch now has a read-only health report plus age-bounded cleanup
93
+ limited to worker identities proven dead; ambiguous directories remain
94
+ untouched.
95
+
96
+ The runtime-global bridge now has one compile-checked registration registry
97
+ and typed high-risk lifecycle fields, reducing silent name and shape drift.
98
+
99
+ ### Changed
100
+ `release:check` now packs, installs, and imports the actual npm tarball in a
101
+ temporary directory, including the shipped goal entry point and auditor
102
+ launcher/worker paths. No registry publish is performed by the smoke.
103
+
3
104
  ## 0.36.0 — event-driven long-running supervision (2026-08-28)
4
105
 
5
106
  ### Added
package/INSTALL.md CHANGED
@@ -38,19 +38,22 @@ and confirmation UX:
38
38
  pi install npm:@juicesharp/rpiv-ask-user-question
39
39
  ```
40
40
 
41
- When a goal has independent repository research or focused worker tasks,
42
- add the optional parallel-worker companion:
41
+ For best automation and quality, add the **pinned parallel-orchestration companion** (`pi-subagents` 0.62.0) — GLLA's power-max choice for `runs.all` fan-out, `runs.lanes` worker→review→fix chains, structured verification, worktree isolation, and durable recovery:
43
42
 
44
43
  ```bash
45
- pi install npm:@tintinweb/pi-subagents
44
+ pi install npm:pi-subagents@0.62.0
46
45
  ```
47
46
 
48
47
  GLLA's main continuation, queue, recovery, and detached auditor work without
49
- it. Other companions are optional: `@pi-unipi/notify` sends remote
50
- notifications, and `pi-chrome` enables logged-in browser research. For a deeper
51
- completion check, choose a stronger auditor model in `/glla`; a separate advisor
52
- extension is not required. None of these companions is required for a basic
53
- GLLA goal.
48
+ it, but parallelism pays for its coordination when a goal has independent
49
+ research or implementation. Other companions are optional: `@pi-unipi/notify`
50
+ sends remote notifications, and `pi-chrome` enables logged-in browser research.
51
+ For a deeper completion check, choose a stronger auditor model in `/glla`;
52
+ a separate advisor extension is not required. Do not run `@tintinweb/pi-subagents`
53
+ or `@quintinshaw/pi-dynamic-workflows` as a second orchestrator alongside GLLA +
54
+ `pi-subagents` in the same session.
55
+
56
+ None of these companions is required for a basic GLLA goal.
54
57
 
55
58
  Do not run another extension that drives agent turns at the same time as GLLA.
56
59
  Likewise, avoid a second task queue or overlapping retry/compaction supervisor
@@ -85,6 +85,6 @@ Speculative feature branching across autonomous subagents creates **stale contex
85
85
  ### The Single-Trunk Operating Rule:
86
86
  * **Serial Queue on `main`**: All queue items drain sequentially on the single primary working tree. Item $N+1$ always executes with 100% truthful, up-to-date context left by item $N$.
87
87
  * **Transactional Green-or-Revert**: Every task either lands green (verified by tests and the detached auditor) and commits, or cleanly rolls back on `main` before the next backlog item is touched.
88
- * **Safe Subagent Parallelism**: Subagents are used for **read-only research fan-out** (e.g. concurrent `Explore` queries across subsystems in a single turn) or standalone verification, rather than speculative mutating branches.
88
+ * **Safe Subagent Parallelism**: Subagents are used for **read-only research fan-out** (e.g. concurrent `scout` queries across subsystems in a single turn) or standalone verification, rather than speculative mutating branches.
89
89
 
90
90
  See `INSTALL.md` for the command surface.
package/README.md CHANGED
@@ -37,7 +37,9 @@ the long-running policy.
37
37
 
38
38
  Use `/glla version` to inspect the installed version and compare it with the
39
39
  registry. This checkout may contain unreleased changes; npm is authoritative
40
- for published versions.
40
+ for published versions. The npm/Pi package listing displays this README from
41
+ the published tarball, so release the package after updating it when store
42
+ readers need the latest guidance.
41
43
 
42
44
  ## Is GLLA the right tool?
43
45
 
@@ -157,8 +159,8 @@ quietly inventing an unbounded backlog.
157
159
  /list plan.md # import a checklist or plan file
158
160
  /list # show active and waiting items
159
161
  /list start # activate the queued head, or draft one clear recent request
160
- /list next # intentionally activate the next item
161
- /list next <n> # choose a specific item
162
+ /list next # explicitly skip/activate the next item
163
+ /list next <n> # explicitly choose a specific item
162
164
  /list resume # explicitly retry/resume the list
163
165
  /list remove <n>
164
166
  /list clear
@@ -167,13 +169,16 @@ quietly inventing an unbounded backlog.
167
169
 
168
170
  Order is the default, not the law. Automatic advance normally uses the head of
169
171
  the queue, while `/list next <n>` or the agent's `list_activate` tool can choose
170
- another item. Numbering always matches `/list` output.
172
+ another item. Numbering always matches `/list` output. After a list item is
173
+ approved and archived, the next queued item starts automatically; no manual
174
+ `/list next` is needed between items.
171
175
 
172
176
  If a saved item is malformed or needs a repair, the repair card preserves the
173
177
  full original target, explains the concrete recovery action, and permits one
174
178
  bounded bootstrap turn containing `propose_task_list`. Confirm the redraft;
175
- automatic repeats are fenced. Use `/list resume` for an intentional retry and
176
- `/list next` when you intentionally want another queued item. `/list start` is
179
+ automatic repeats are fenced. Use `/list resume` or `/glla resume` for an
180
+ intentional retry of a waiting/restored queue, and `/list next` when you
181
+ intentionally want to skip or choose another queued item. `/list start` is
177
182
  also explicit: it activates the queued head, or—when the queue is empty—uses
178
183
  one clear recent user request as a seed for the normal Confirm-gated list
179
184
  drafting flow. Ambiguous context is never queued automatically.
@@ -259,6 +264,9 @@ templates, themes, or context files, so its model must be usable in a plain pi
259
264
  session. It is independent verification, not an OS sandbox: the auditor's
260
265
  `bash` tool can still change files if a prompt or verifier tells it to. Keep
261
266
  verification commands bounded and treat repository permissions accordingly.
267
+ On Linux, both direct contract checks and the detached auditor enforce a
268
+ 256-process process-group ceiling to contain recursive helper/test launches;
269
+ cross-platform timeout and process-tree cleanup remain in place as well.
262
270
 
263
271
  ## Recommended pi extensions
264
272
 
@@ -270,28 +278,40 @@ GLLA is the supervisor. These companions add capabilities around it:
270
278
  previews, and Confirm dialogs for drafting and decisions. GLLA has a prose
271
279
  fallback, but this is the intended UX.
272
280
 
273
- ### Optional parallel workers
274
-
275
- - **`@tintinweb/pi-subagents`**recommended when a goal has independent work
276
- that can genuinely run in parallel. It gives the main agent Explore, Plan,
277
- and general-purpose workers for research and focused implementation. It is
278
- not required for GLLA's main continuation, queue, recovery, or detached
279
- auditor; a short or mostly sequential goal is often better without the
280
- extra worker overhead.
281
+ ### Recommended for power — parallel orchestration (`pi-subagents`)
282
+
283
+ - **`pi-subagents` 0.62.0 (pinned) the power-max choice for GLLA.** Use it
284
+ when you want the best automation and quality: `runs.all` parallel fan-out,
285
+ `runs.lanes` worker→review→fix chains, `outputSchema` + `acceptance` structured
286
+ verification, `runs.host` gated shell, worktree isolation, model routing
287
+ (`subagents.defaultModel` / `subagentModelOverrides` / `modelScope`), durable
288
+ missions/schedules/recovery, and versioned control RPC. Built-ins are `scout`,
289
+ `researcher`, `worker`, `reviewer`, `oracle`, `delegate` plus external-CLI
290
+ writers (`claude-code-writer` etc.); all inherit the parent model by default
291
+ so there is no hidden Explore/Plan quota pool. This is the companion GLLA
292
+ supervises via `subagent:*` lifecycle events + durable `status.json` + versioned
293
+ stop RPC (ownership/generation-checked). GLLA's `subagentModelOverrides`
294
+ can still pin an individual role.
281
295
 
282
296
  The main pi session remains the owner of the goal/list/loop; subagents are
283
- workers and cannot silently replace the parent's objective.
297
+ workers and cannot silently replace the parent's objective. A short or mostly
298
+ sequential goal can still run cleanly without workers — install when
299
+ parallelism will pay for its coordination and model usage.
284
300
 
285
- Install it when parallelism will pay for its coordination and model usage:
301
+ Install (or keep pinned):
286
302
 
287
303
  ```bash
288
- pi install npm:@tintinweb/pi-subagents
304
+ pi install npm:pi-subagents@0.62.0
289
305
  ```
290
306
 
291
- GLLA supervises the parent and tracks worker activity, partial output, and
292
- confirmed frozen-child recovery. It also defaults Explore agents toward the
293
- parent model strategy so a hidden provider pin does not unexpectedly consume a
294
- different quota pool.
307
+ Do not install the older `@tintinweb/pi-subagents` provider alongside this
308
+ recommendation in the same session. Existing Tintin-era agent files are
309
+ cleaned only when GLLA's management marker proves that GLLA owns them; old
310
+ settings are not silently remapped to a different role. Do not stack
311
+ `@quintinshaw/pi-dynamic-workflows` as a competing orchestrator alongside
312
+ GLLA + `pi-subagents` in the same session — duplicate tools and competing
313
+ orchestration events create ambiguous ownership. Use its quality helpers
314
+ (`verify`/`judgePanel`/`loopUntilDry`) only as isolated complements if needed.
295
315
 
296
316
  ### Useful, but optional
297
317
 
@@ -339,7 +359,9 @@ tree.
339
359
  The state is inspectable: active JSONL, goal markdown, queue state, audit jobs,
340
360
  ledger history, and archived goals are kept under `.pi-glla/` (or the selected
341
361
  session root). Repository audit findings remain repository-only; the npm package
342
- ships the user-facing docs, not local audit history.
362
+ ships the user-facing docs, not local audit history. The list-audit findings
363
+ file and its fan-out follow the same selected state root, including the
364
+ opt-in `sessionDir` root.
343
365
 
344
366
  ### Recovery behavior
345
367
 
@@ -22,6 +22,11 @@ GLLA automation is **event-driven and progress-aware**, not duration-guessed.
22
22
  Detached auditors have no unconditional wall-clock expiry: legacy wall
23
23
  metadata is ignored, while confirmed silence and an individual tool timeout
24
24
  remain the bounded safety mechanisms.
25
+ - Project verification commands run in an owned process group. On Linux, GLLA
26
+ also counts that group every 100ms and aborts it above 256 processes; this
27
+ catches recursive test/helper launches before a long wall timeout can become
28
+ a host-wide process or swap storm. The limit is a containment result, never
29
+ an automatic retry.
25
30
  - Timers remain useful for per-attempt backoff, watchdogs, and host safety. A
26
31
  timer is never evidence that work completed and is not the definition of a
27
32
  long-running process's lifetime. Detached-auditor first-event silence starts
package/docs/DESIGN.md CHANGED
@@ -633,6 +633,46 @@ shapes (details in CHANGELOG.md; each is pinned by tests):
633
633
  that NEVER moves gets its own loud bounded stop. Audit loops keep their
634
634
  purpose-built deferred-baseline + reprieve semantics verbatim.
635
635
 
636
+ ## Addendum v0.36.3 (subagent orchestration — power-max pin)
637
+
638
+ - **One pinned orchestrator**: `pi-subagents@0.62.0` is the power-max companion
639
+ for GLLA. Capability ceiling chosen over minimalism: `runs.all` parallel
640
+ fan-out, `runs.lanes` worker→review→fix chains, `outputSchema` +
641
+ `acceptance` structured verification, `runs.host` gated shell, worktree
642
+ isolation, model routing (`subagents.defaultModel` / `subagentModelOverrides`
643
+ / `modelScope`), missions/schedules, and durable recovery. GLLA supervises
644
+ via `subagent:async-started` + durable `status.json` + versioned stop RPC
645
+ (ownership/generation-checked). The 0.x pin is exact because the 93k-line
646
+ surface moves fast; upgrades run a compatibility canary.
647
+ - **One owner, no stacking**: `@tintinweb/pi-subagents` (legacy),
648
+ `@narumitw/pi-subagents` (minimal without durable status/workflow), and
649
+ `@quintinshaw/pi-dynamic-workflows` (complement-only LLM-vote helpers) are
650
+ not stacked as second orchestrators in the same session — duplicate tools and
651
+ competing events create ambiguous ownership. `@juicesharp/rpiv-advisor`
652
+ remains a composable second-opinion reviewer.
653
+
654
+ ## Addendum v0.36.2 (continuous list handoff)
655
+
656
+ - **A list is a continuous work plan**: after a standalone goal reaches a
657
+ successful terminal archive, an already-waiting queue is handed to the same
658
+ activation choke point used by list-item completion. The bounded
659
+ `LIST_COMPLETION_SETTLE_MS` window still protects the first successor
660
+ continuation from the host's completion acknowledgement settling. User
661
+ aborts do not auto-advance, and one-active-thing, suspicious-objective,
662
+ sidecar, persistence, carryover, and loop-owner fences remain authoritative.
663
+ - **Resume repairs waiting queues**: `/glla resume` hydrates durable queue
664
+ sidecars, records `list_queue_resume`, and explicitly activates the waiting
665
+ head when no higher-priority goal, loop, auditor, or provider-recovery plane
666
+ owns the surface. Cold-load automation remains consent-gated; this command
667
+ is the consent boundary.
668
+ - **Selection remains explicit**: `/list next` is still available for a
669
+ deliberate skip or non-head choice. It is no longer required between
670
+ successful list items.
671
+
672
+ ## Addendum v0.37.1 (folder-scoped audits)
673
+
674
+ - **Primary scope is the cwd project**: `listAuditCollectTarget`, `projectAuditTarget`, and `auditTarget` now state "current project rooted at the cwd where pi was opened (treat any nested .git as a separate project boundary — do not walk into parent or sibling projects)". The TIGHT scout brief is "named directories under cwd" — external code outside cwd may be READ only to diagnose a failure that blocks the current project, and a finding about external code is valid only when it affects the current project (a typo in an unrelated sibling project is out of scope and never auto-queued). This closes the "audit the parent when you opened a subproject" leak observed when hellhunter was audited from the dracon-platform root and vice-versa.
675
+
636
676
  ## Files
637
677
 
638
678
  - `docs/DESIGN.md` — **this file**
package/docs/INDEX.md CHANGED
@@ -10,34 +10,35 @@ shipped in the npm tarball (see "Repository-only material" below).
10
10
 
11
11
  For shipped docs, the relevant entry points are:
12
12
 
13
- - `../CHANGELOG.md` — user-facing changelog; the top of the file is the
14
- current package version. v0.35.5 adopted the six-label completion
13
+ - `../CHANGELOG.md` — user-facing changelog; an `Unreleased` section may lead
14
+ the file, followed by the current released version. v0.35.5 adopted the six-label completion
15
15
  recap; v0.35.6 added typed-boundary regression pins; v0.35.7 added
16
16
  deterministic fast-fail pre-audits, zero-pause autonomous execution, and
17
17
  task milestone gating; v0.35.8 added main-model preferred-primary
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.36.0 continue through the supervisor freeze (`/glla pause`),
21
+ v0.35.14–v0.37.1 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
25
25
  subagent recovery, bounded repair/replan recovery, production RPC child
26
26
  stopping, mandatory hermetic auditor-extension validation, optional provider
27
- extensions, and bounded zero-stream retry containment see CHANGELOG.md for
28
- the full trail.
27
+ extensions, bounded zero-stream retry containment, crash-safe persistence,
28
+ and packed-artifact release verification — see CHANGELOG.md for the full
29
+ trail.
29
30
  - `../README.md` — what the plugin is, install, quickstart, and the
30
31
  architectural guarantee (drafting + confirm + detached auditor).
31
- - `../INSTALL.md` — manual install / symlink setup; the recommended
32
+ - `../INSTALL.md` — source install / local development setup; the recommended
32
33
  companion plugins and the `auditor reads / writes are path-checked`
33
34
  note.
34
35
 
35
36
  ## Entry points
36
37
  - `../README.md` — what the plugin is, install, quickstart
37
- - `../INSTALL.md` — manual install / symlink setup
38
- - `../CHANGELOG.md` — user-facing changelog; current package version is
39
- at the top of the file (use `/glla version` to compare with the
40
- registry).
38
+ - `../INSTALL.md` — source install / local development setup
39
+ - `../CHANGELOG.md` — user-facing changelog; the first versioned heading is
40
+ the current released package version (use `/glla version` to compare with
41
+ the registry); post-release work may appear in `Unreleased` above it.
41
42
 
42
43
  ## Architecture
43
44
  - `DESIGN.md` — plugin design (types, state, extension lifecycle)
@@ -29,6 +29,8 @@ export type AgentPhase = "queued" | "active" | "hung" | "ended" | "unknown";
29
29
 
30
30
  export interface AgentsPanelRow {
31
31
  recordId: string;
32
+ /** Persisted pi session id, when the subagent runtime exposes it. */
33
+ sessionId?: string;
32
34
  agentType?: string;
33
35
  summary?: string;
34
36
  status: AgentStatus;
@@ -163,7 +165,11 @@ export function renderAgentsWidgetLines(rows: AgentsPanelRow[], now = Date.now()
163
165
  return lines;
164
166
  }
165
167
 
166
- /** The compact footer summary: count + the least-live child. */
168
+ /** The compact footer summary: count + the least-live child.
169
+ * v0.37.1 (ui-jitter fix): bucket the silent age so the status/widget
170
+ * text stays stable between ticks — a per-second change made the footer
171
+ * and widget keys differ every 2s, forcing a TUI re-layout that looked
172
+ * like "jumping" under heavy scout fan-out. */
167
173
  export function renderAgentsWidgetLine(rows: AgentsPanelRow[]): string | undefined {
168
174
  const active = rows.filter((r) => r.status !== "ended");
169
175
  if (active.length === 0) return undefined;
@@ -173,7 +179,16 @@ export function renderAgentsWidgetLine(rows: AgentsPanelRow[]): string | undefin
173
179
  : busiest.status === "hung"
174
180
  ? " ⚠"
175
181
  : "";
176
- return `● ${active.length} agent${active.length === 1 ? "" : "s"} · ${cleanField(busiest.agentType ?? "subagent", 18)} silent ${fmtDuration(busiest.silentMs)}${hung}`;
182
+ return `● ${active.length} agent${active.length === 1 ? "" : "s"} · ${cleanField(busiest.agentType ?? "subagent", 18)} silent ${fmtDuration(bucketSilentMs(busiest.silentMs))}${hung}`;
183
+ }
184
+
185
+ /** Bucket silentMs to coarser granularity for display stability:
186
+ * <1m → 5s buckets, <5m → 15s, otherwise 30s. The underlying
187
+ * hung classification still uses the exact value. */
188
+ function bucketSilentMs(ms: number): number {
189
+ if (ms < 60_000) return Math.floor(ms / 5000) * 5000;
190
+ if (ms < 300_000) return Math.floor(ms / 15_000) * 15_000;
191
+ return Math.floor(ms / 30_000) * 30_000;
177
192
  }
178
193
 
179
194
  export interface TranscriptTailResult {
@@ -206,7 +221,7 @@ function parsedSessionInfoName(content: Buffer): string | undefined {
206
221
  * tail/head readers. */
207
222
  export function tailChildTranscript(
208
223
  sessionsDir: string,
209
- row: { recordId: string; agentType?: string; summary?: string },
224
+ row: { recordId: string; sessionId?: string; agentType?: string; summary?: string },
210
225
  opts: {
211
226
  lines?: number;
212
227
  readFile?: (file: string, maxBytes?: number) => Buffer;
@@ -246,7 +261,19 @@ export function tailChildTranscript(
246
261
  .map((f) => ({ f, mtime: statMtime(f) }))
247
262
  .sort((a, b) => b.mtime - a.mtime);
248
263
  let matched: string | undefined;
249
- const candidatesToScan = candidates.slice(0, 25);
264
+ // Pi names session files `<timestamp>_<sessionId>.jsonl`. Prefer the exact
265
+ // session id from the manager/event record so an old tracked child remains
266
+ // discoverable without turning the main-thread fallback into an unbounded
267
+ // full-directory scan. Identity in session_info.name remains authoritative.
268
+ const sessionId = row.sessionId?.trim();
269
+ const directCandidates = sessionId
270
+ ? candidates.filter(({ f }) => {
271
+ const base = path.basename(f);
272
+ return base === `${sessionId}.jsonl` || base.endsWith(`_${sessionId}.jsonl`);
273
+ })
274
+ : [];
275
+ const recentCandidates = candidates.filter((candidate) => !directCandidates.includes(candidate)).slice(0, 25);
276
+ const candidatesToScan = [...directCandidates, ...recentCandidates];
250
277
  if (expectedSessionName) for (const candidate of candidatesToScan) {
251
278
  try {
252
279
  // Check the bounded tail first so the existing scan remains the first
@@ -266,7 +293,7 @@ export function tailChildTranscript(
266
293
  return {
267
294
  ok: false,
268
295
  lines: [],
269
- detail: `no session file in ${sessionsDir} matches this child (searched ${candidatesToScan.length}${candidates.length > candidatesToScan.length ? ` of ${candidates.length}` : ""} transcripts for exact identity in session_info.name: ${expectedSessionName ? `"${truncate(expectedSessionName, 32)}"` : "none"}) — the child may not persist a session, or it lives under another working directory`,
296
+ detail: `no session file in ${sessionsDir} matches this child (searched ${candidatesToScan.length}${candidatesToScan.length < candidates.length ? ` of ${candidates.length}` : ""} transcripts for exact identity in session_info.name: ${expectedSessionName ? `"${truncate(expectedSessionName, 32)}"` : "none"}) — the child may not persist a session, or it lives under another working directory`,
270
297
  };
271
298
  }
272
299
  try {