pi-goal-list-loop-audit 0.38.34 → 0.38.35
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 +12 -0
- package/docs/INDEX.md +1 -1
- package/extensions/goal-loop-display.ts +54 -14
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.38.35 — closed card + smart summary (2026-09-08)
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **Card no longer reads cut off (field 2026-09-08 220808):** the head objective now cuts at the last clause boundary inside the budget instead of mid-word (`truncateObjective`; character cut remains the fallback); the steady-state `model: primary … · inherited from session` row is dropped — it restated pi's own status line two rows below; and every card closes — the final `├─`/`│` row becomes `└─` whatever built it (active action row, lone orphan worker row). Provenance still renders on any news (pin, fallbacks, skips, failover); `/goal status` keeps the full chain.
|
|
8
|
+
- **Stale card tests updated deliberately, purpose preserved:** the v0.33.0 slim-card `├─` tail, the v0.38.28 lone-row close, the loop-kind test's incidental model assertion, the narrow-width truncation fixture (now on a pinned row), and the worker-before-footer invariant (detail never lands *after* a footer).
|
|
9
|
+
|
|
10
|
+
### Verification
|
|
11
|
+
|
|
12
|
+
- Full `release:check`: 2037 pass / 2 skip / 0 fail across 204 files; `tsc --noEmit` clean.
|
|
13
|
+
- Evidence: `audit/UI-CARD-CLOSED-2026-09-08.md`.
|
|
14
|
+
|
|
3
15
|
## 0.38.34 — completion communication: fair replay rotation + stale-test refresh (2026-09-08)
|
|
4
16
|
|
|
5
17
|
### Fixed
|
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
|
+
v0.35.14–v0.38.35 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
|
|
@@ -83,6 +83,35 @@ export function truncateCells(s: string, max: number): string {
|
|
|
83
83
|
return `${out}…`;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
/** Clause-aware objective shortening for the card head. A raw character cut
|
|
87
|
+
* ends objectives mid-word ("…restyle the …") which reads as a clipped
|
|
88
|
+
* card rather than a summary (field 2026-09-08 220808). When the text
|
|
89
|
+
* overruns, prefer cutting at the last clause boundary (: ; · — – ( [)
|
|
90
|
+
* inside the budget so the head reads as an intentional summary; fall back
|
|
91
|
+
* to the character cut when no boundary clears the floor. Display-only. */
|
|
92
|
+
export function truncateObjective(s: string, max: number): string {
|
|
93
|
+
const clean = compactDisplayText(s);
|
|
94
|
+
if (tuiVisibleWidth(clean) <= max) return clean;
|
|
95
|
+
if (max <= 1) return truncateCells(clean, max);
|
|
96
|
+
const budget = max - 1;
|
|
97
|
+
const floor = Math.max(16, Math.floor(budget * 0.4));
|
|
98
|
+
let out = "";
|
|
99
|
+
let w = 0;
|
|
100
|
+
let boundaryLen = -1;
|
|
101
|
+
for (const ch of clean) {
|
|
102
|
+
const cw = tuiVisibleWidth(ch);
|
|
103
|
+
if (w + cw > budget) break;
|
|
104
|
+
out += ch;
|
|
105
|
+
w += cw;
|
|
106
|
+
if (/[:;·—–(\[]/.test(ch)) boundaryLen = out.length;
|
|
107
|
+
}
|
|
108
|
+
if (boundaryLen > 0) {
|
|
109
|
+
const cut = [...out].slice(0, boundaryLen).join("").replace(/[:;·—–(\[\s]+$/u, "");
|
|
110
|
+
if (tuiVisibleWidth(cut) >= Math.min(floor, 16)) return `${cut}…`;
|
|
111
|
+
}
|
|
112
|
+
return `${out}…`;
|
|
113
|
+
}
|
|
114
|
+
|
|
86
115
|
function displayPauseReason(reason: string): string {
|
|
87
116
|
return compactDisplayText(sanitizeProviderDisplayText(reason));
|
|
88
117
|
}
|
|
@@ -353,26 +382,34 @@ function compactMainModelRecoveryLine(recovery: MainModelRecovery | undefined, c
|
|
|
353
382
|
|
|
354
383
|
function modelProvenanceLines(provenance: ModelProvenanceDisplay | undefined, width?: number): string[] {
|
|
355
384
|
if (!provenance) return [];
|
|
385
|
+
const primary = typeof provenance.primary === "string" ? provenance.primary.trim() : "";
|
|
386
|
+
const fallbacks = uniqueModelRefs(provenance.fallbackRefs);
|
|
387
|
+
const skipped = uniqueModelRefs(provenance.skippedForbiddenRefs);
|
|
388
|
+
const handledTurn = typeof provenance.handledTurn === "string" ? provenance.handledTurn.trim() : "";
|
|
389
|
+
const handledTurnNews = !!handledTurn && handledTurn.toLowerCase() !== (primary || "").toLowerCase();
|
|
390
|
+
const handledAudit = typeof provenance.handledAudit === "string" ? provenance.handledAudit.trim() : "";
|
|
391
|
+
// The card sits just above pi's own status line, which already names the
|
|
392
|
+
// session model. A lone `model: primary X · inherited from session` row
|
|
393
|
+
// restates that indicator for zero new information while deepening the
|
|
394
|
+
// tree (field 2026-09-08 220808). Show the block only when it carries
|
|
395
|
+
// news: a pinned selection, fallbacks, skips, or a failover that
|
|
396
|
+
// handled work. `/goal status` keeps the full chain regardless.
|
|
397
|
+
if (primary && provenance.primarySource !== "pinned" && fallbacks.length === 0 && skipped.length === 0 && !handledTurnNews && !handledAudit) return [];
|
|
356
398
|
const budget = budgetFor(width, 3, 60);
|
|
357
399
|
const lines: string[] = [];
|
|
358
|
-
const primary = typeof provenance.primary === "string" ? provenance.primary.trim() : "";
|
|
359
400
|
if (primary) {
|
|
360
401
|
const source = provenance.primarySource === "pinned" ? "pinned" : "inherited from session";
|
|
361
402
|
lines.push(`model: primary ${truncate(primary, budget)} · ${source}`);
|
|
362
403
|
}
|
|
363
|
-
const fallbacks = uniqueModelRefs(provenance.fallbackRefs);
|
|
364
404
|
if (fallbacks.length > 0) lines.push(`fallbacks: ${truncate(fallbacks.join(" → "), budget)}`);
|
|
365
|
-
const skipped = uniqueModelRefs(provenance.skippedForbiddenRefs);
|
|
366
405
|
if (skipped.length > 0) lines.push(`skipped forbidden: ${truncate(skipped.join(", "), budget)}`);
|
|
367
|
-
const handledTurn = typeof provenance.handledTurn === "string" ? provenance.handledTurn.trim() : "";
|
|
368
406
|
// A normal turn is handled by the configured primary model. Repeating the
|
|
369
407
|
// same ref immediately below it adds no information and, when it is the
|
|
370
408
|
// last row, leaves a misleading continuation glyph in the card. Keep the
|
|
371
409
|
// row only when a recovery/failover actually handled the turn.
|
|
372
|
-
if (
|
|
410
|
+
if (handledTurnNews) {
|
|
373
411
|
lines.push(`handled turn: ${truncate(handledTurn, budget)}`);
|
|
374
412
|
}
|
|
375
|
-
const handledAudit = typeof provenance.handledAudit === "string" ? provenance.handledAudit.trim() : "";
|
|
376
413
|
if (handledAudit) {
|
|
377
414
|
const source = provenance.handledAuditSource?.trim() ? modelSourceLabel(provenance.handledAuditSource) : "";
|
|
378
415
|
const via = source ? ` · via ${truncate(source, 24)}` : "";
|
|
@@ -1450,15 +1487,18 @@ export function buildWidgetLines(state: State, audit?: AuditDisplayProgress | nu
|
|
|
1450
1487
|
withAgents = orphanHead ? [orphanHead, ...agentLines] : [...agentLines];
|
|
1451
1488
|
}
|
|
1452
1489
|
}
|
|
1453
|
-
//
|
|
1454
|
-
//
|
|
1455
|
-
//
|
|
1456
|
-
|
|
1490
|
+
// The card always reads as a finished block: a final `├─`/`│` row
|
|
1491
|
+
// promises continuation rows that never come (field 2026-09-08 220808 —
|
|
1492
|
+
// the active card ended on its action row, reading as cut off). Close
|
|
1493
|
+
// the tail whatever built it; rows that already close (`└─`, the head,
|
|
1494
|
+
// the spacer) are untouched. Tree prefixes are literal — paint wraps
|
|
1495
|
+
// content, never the glyph — so this holds themed too.
|
|
1496
|
+
if (withAgents && withAgents.length > 0) {
|
|
1457
1497
|
const tailIndex = withAgents.length - 1;
|
|
1458
1498
|
const tail = withAgents[tailIndex]!;
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
}
|
|
1499
|
+
const m = tail.match(/^(├─ |│ |│ )/);
|
|
1500
|
+
const prefix = m?.[1] ?? "";
|
|
1501
|
+
if (prefix) withAgents[tailIndex] = `└─ ${tail.slice(prefix.length)}`;
|
|
1462
1502
|
}
|
|
1463
1503
|
// v0.28.6 (E1): a persistence failure outranks everything — first line,
|
|
1464
1504
|
// on every render, until a write lands again.
|
|
@@ -1663,7 +1703,7 @@ function goalLines(g: Goal, state: State, audit: AuditDisplayProgress | null | u
|
|
|
1663
1703
|
const headIcon = headLive
|
|
1664
1704
|
? paint(theme, headLive.band === "fresh" ? "success" : headLive.band === "aging" ? "warning" : "error", headLive.breath)
|
|
1665
1705
|
: icon;
|
|
1666
|
-
const head = `${headIcon} ${
|
|
1706
|
+
const head = `${headIcon} ${truncateObjective(displayObjective(g.objective), objBudget)} ${paint(theme, "dim", "·")} ${segsText}`;
|
|
1667
1707
|
const lines = [head];
|
|
1668
1708
|
// v0.38.8: durable verdict tally as a first-class card row — the widget
|
|
1669
1709
|
// is the glance surface, and stored verdicts are the progress evidence
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-goal-list-loop-audit",
|
|
3
|
-
"version": "0.38.
|
|
3
|
+
"version": "0.38.35",
|
|
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",
|