pi-goal-list-loop-audit 0.37.2 → 0.37.3

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.37.3 — pi 0.84 loop stall fix — agent_start fallback for continuation start proof (2026-09-02)
4
+
5
+ ### Fixed
6
+ `continuation_start_unacknowledged` stall on every `/loop` iteration under pi >=0.84 — `before_agent_start` is not emitted for `sendMessage({ deliverAs: "followUp" })` continuations, so the start proof never arrived (10/10 `loop_turn_sent` unacknowledged in issue #40). `dispatchStartAcknowledged` now accepts `agent_start`/`turn_start` as fallback while keeping `before_agent_start`+marker as primary; owner/generation/foreign fences still apply so only an unrelated manual turn in the same session could falsely settle — strictly better than 0% success. Ledger records `startProofSource` as `agent_start`/`turn_start` when fallback fires.
7
+
8
+ Hardcoded 60s retry backoff after the first 30s start-proof window is now env-configurable (`GLLA_CONTINUATION_RETRY_BACKOFF_MS`, legacy `GLLA_CONTINUATION_START_RETRY_BACKOFF_MS`) independent of `GLLA_CONTINUATION_START_TIMEOUT_MS`, so slow local models can extend both windows (observed 5m + 60s hard cap in issue #40 secondary).
9
+
10
+ ### Added
11
+ Regression pins for the fallback path and env var (`tests/loop-start-proof-fallback.test.ts`, `tests/stale-api-terminal.test.ts`, `tests/stall-handling.test.ts`).
12
+
3
13
  ## 0.37.2 — queued vs monitoring visuals and long-running daemon handling (2026-09-01)
4
14
 
5
15
  ### 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.37.2 continue through the supervisor freeze (`/glla pause`),
21
+ v0.35.14–v0.37.3 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
@@ -204,7 +204,11 @@ export function createGoalContinuation(flagsArg: ContinuationFlags, d: Continuat
204
204
  // self-heal; only the second window failure declares unacknowledged (the
205
205
  // explicit /list|/goal|/loop resume fallback for genuine provider stalls).
206
206
  const CONTINUATION_START_TIMEOUT_MS = Number(process.env.GLLA_CONTINUATION_START_TIMEOUT_MS ?? 30_000);
207
- const NO_TURN_START_RETRY_BACKOFF_MS = 60_000;
207
+ const NO_TURN_START_RETRY_BACKOFF_MS = Number(
208
+ process.env.GLLA_CONTINUATION_RETRY_BACKOFF_MS ??
209
+ process.env.GLLA_CONTINUATION_START_RETRY_BACKOFF_MS ??
210
+ 60_000,
211
+ );
208
212
  let continuationStartTimeoutOverrideMs: number | null = null;
209
213
  let continuationRetryBackoffOverrideMs: number | null = null;
210
214
  function continuationStartTimeoutMs(): number {
@@ -568,21 +572,43 @@ export function dispatchStartAcknowledged(ctx: ExtensionContext, source: string,
568
572
  }
569
573
  // A dispatch has one accepted window and one start proof. Once a start was
570
574
  // recorded, later low-level events must not re-settle it; before that,
571
- // events without the exact before_agent_start marker are unrelated manual
572
- // activity and cannot clear the watchdog.
575
+ // only a marker-carrying before_agent_start or the pi>=0.84 fallback
576
+ // (agent_start/turn_start without a prompt) may clear the watchdog.
573
577
  const pending = pendingContinuationDispatch;
574
578
  if (!pending || pending.phase !== "accepted") return false;
575
- if (source !== "before_agent_start" && !pending.startProofSource) return false;
579
+ // v0.37.3 (issue #40): pi >=0.84 does not emit before_agent_start for
580
+ // followUp continuations (sendMessage { deliverAs: "followUp" }) — the
581
+ // only delivery path for continuations. Gate on the strongest proof when
582
+ // available, but accept agent_start/turn_start as fallback so the
583
+ // continuation is not stuck at 0% success. Owner/generation/foreign
584
+ // checks below still fence the fallback to the same session/generation.
585
+ if (
586
+ source !== "before_agent_start" &&
587
+ source !== "agent_start" &&
588
+ source !== "turn_start" &&
589
+ !pending.startProofSource
590
+ )
591
+ return false;
576
592
  const record = pendingContinuationDispatch;
577
593
  if (!record || flags.sessionHandoffPending || flags.extensionApiStale || flags.staleTerminalDone || flags.zombieStoodDown) return false;
578
594
  if (record.generation !== flags.sessionGeneration || isForeignCtx(ctx)) return false;
579
595
  if (!dispatchMatchesOwner(record, flags.sessionGeneration, sessionManagerId(ctx))) return false;
580
596
  if ((record.kind === "goal" || record.kind === "stall") && (!state.goal || state.goal.id !== record.goalId || state.goal.status !== "active")) return false;
581
- // before_agent_start is the required proof: it must carry this exact
582
- // dispatch marker. Older low-level events without a prompt are liveness
583
- // signals only; accepting them would let an unrelated manual turn settle
584
- // this dispatch and suppress its recovery watchdog.
585
- if (source !== "before_agent_start" || !dispatchPromptMatches(record, prompt)) return false;
597
+ // before_agent_start must carry this exact dispatch marker. The fallback
598
+ // (agent_start/turn_start) carries no prompt in pi >=0.84 for followUp
599
+ // turns owner/generation/foreign above already fence it to the same
600
+ // session, so an unrelated manual turn in the same session is the only
601
+ // remaining false-positive, strictly better than never acknowledging.
602
+ if (source === "before_agent_start") {
603
+ if (!dispatchPromptMatches(record, prompt)) return false;
604
+ } else if (source === "agent_start" || source === "turn_start") {
605
+ // fallback — no prompt to match
606
+ } else {
607
+ // message_update / agent_end / other liveness signals cannot settle
608
+ // without an existing proof, and pending.phase !== "accepted" already
609
+ // blocks re-settlement after the first proof.
610
+ return false;
611
+ }
586
612
  const settledAt = Date.now();
587
613
  const started: ContinuationDispatch = {
588
614
  ...transitionDispatch(record, "started"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-goal-list-loop-audit",
3
- "version": "0.37.2",
3
+ "version": "0.37.3",
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",