pi-goal-list-loop-audit 0.38.41 → 0.38.42

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,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.38.42 — trailer cleanup: model-free folded approval (2026-09-09)
4
+
5
+ ### Fixed
6
+
7
+ - **One canonical approval bullet in chat and transcript (field 20260909_140404):** the `provider/model` slug leaves both surfaces — chat shows `auditor approved on the provider retry (1 verdict).`, via-retry news kept. A lone approval folds with the verdict count; the standalone audit bullet survives only with news (multiple, disapproved, or impossible verdicts). The full model ID stays in the archive record; machine-path layering (chat stripped, transcript full) unchanged.
8
+
9
+ ### Verification
10
+
11
+ - Render-unit pins both ways (fold + survive) and both surfaces (no model ID) plus an archive-keeps-model source pin; full `release:check` 0 failures; `tsc --noEmit` clean.
12
+
3
13
  ## 0.38.41 — grilling standard codified (2026-09-09)
4
14
 
5
15
  ### 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.41 continue through the supervisor freeze (`/glla pause`),
21
+ v0.35.14–v0.38.42 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
@@ -237,7 +237,10 @@ export function withoutStaleNext(details: string[] | undefined): string[] {
237
237
  * Five 120-char label lines scan as soup, not a summary (field
238
238
  * 2026-09-04); the stale Next never reaches the chat.
239
239
  * v0.38.25: optional `counts` audit-goal counts line rides between the
240
- * approval trailer and the record pointer (the pointer stays last). */
240
+ * approval trailer and the record pointer (the pointer stays last).
241
+ * v0.38.42: retained for backward compatibility + direct unit tests —
242
+ * buildTerminalApprovalRender constructs chat lines inline because the
243
+ * fold changes trailer arity, which this fixed-shape helper cannot express. */
241
244
  export function buildApprovalChatLines(notice: {
242
245
  outcome: string;
243
246
  details: string[] | undefined;
@@ -262,7 +265,15 @@ export function buildApprovalChatLines(notice: {
262
265
  /** v0.38.39 (field 20260909_013733): the trailer rides as bullets too —
263
266
  * the Codex close is uniform `•` lines (`• Changed:` … `• record:`),
264
267
  * never a `•` block followed by dangling `—` lines. The `— ` sigil is
265
- * stripped at render; the input strings keep it for non-chat surfaces. */
268
+ * stripped at render; the input strings keep it for non-chat surfaces.
269
+ * v0.38.42 (field 20260909_140404): the chat/transcript approval bullet
270
+ * carries no model ID — the `provider/model` slug is machine trivia
271
+ * outside an audit (the full model ID stays in the archive record).
272
+ * The `auditor <model> approved` shape collapses to `auditor approved`;
273
+ * any other approval voice passes through untouched. */
274
+ function stripApprovalModel(line: string): string {
275
+ return line.replace(/auditor\s+\S+\s+approved/, "auditor approved");
276
+ }
266
277
  function trailerBullet(line: string): string {
267
278
  return `• ${line.replace(/^—\s*/, "")}`;
268
279
  }
@@ -343,19 +354,33 @@ export function buildTerminalApprovalRender(input: TerminalApprovalRenderInput):
343
354
  ? { ...baseBrief, details: [...baseBrief.details, `Left out: ${clipSummaryValue(leftOutContent, 120)}`] }
344
355
  : baseBrief;
345
356
  const countsLine = input.countsLine ?? buildAuditCountsLine(input.goal, input.auditNote);
357
+ // v0.38.42 (field 20260909_140404): one canonical approval bullet in
358
+ // chat and transcript — no model ID in either, via-retry news kept. A
359
+ // lone approval says the same thing as the counts line, so they fold
360
+ // into one bullet carrying the verdict count; the standalone audit
361
+ // bullet survives only with news (multiple, disapproved, or impossible
362
+ // verdicts). The returned `approval` field keeps the full input string
363
+ // for archive/persist consumers — the model ID leaves chat/transcript,
364
+ // never the record.
365
+ const history = input.goal.auditHistory ?? [];
366
+ const chatApproval = stripApprovalModel(input.approval);
367
+ const foldCounts = history.length === 1
368
+ && history[0]?.approved === true
369
+ && /approved/.test(chatApproval);
370
+ const approvalBullet = foldCounts
371
+ ? `• ${chatApproval.replace(/^—\s*/, "").replace(/\.\s*$/, "")} (${history.length} verdict).`
372
+ : trailerBullet(chatApproval);
346
373
  return {
347
374
  chatLines: [
348
- ...buildApprovalChatLines({
349
- outcome: brief.outcome,
350
- details: brief.details,
351
- approval: input.approval,
352
- record: input.record,
353
- counts: countsLine,
354
- }),
375
+ `✓ done — ${brief.outcome}`,
376
+ ...withoutStaleNext(brief.details).map((detail) => `• ${detail}`),
377
+ approvalBullet,
378
+ ...(foldCounts ? [] : [trailerBullet(countsLine)]),
379
+ trailerBullet(input.record),
355
380
  ...(input.extras ?? []),
356
381
  ],
357
382
  recap,
358
- transcriptLines: [...withoutStaleNext(brief.details).map((detail) => `• ${detail}`), trailerBullet(input.approval)],
383
+ transcriptLines: [...withoutStaleNext(brief.details).map((detail) => `• ${detail}`), approvalBullet],
359
384
  countsLine,
360
385
  outcome: brief.outcome,
361
386
  approval: input.approval,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-goal-list-loop-audit",
3
- "version": "0.38.41",
3
+ "version": "0.38.42",
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",