pi-goal-list-loop-audit 0.35.13 → 0.35.64
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 +977 -0
- package/INSTALL.md +13 -3
- package/LIST-PHILOSOPHY.md +90 -0
- package/PLAN.md +316 -0
- package/README.md +201 -26
- package/docs/DESIGN-subagent-visibility.md +76 -0
- package/docs/DESIGN.md +59 -8
- package/docs/GLLA-POSITIONING-AND-DECOMPOSITION-2026-08-08.md +6 -1
- package/docs/INDEX.md +4 -0
- package/docs/VISION-ASSIST.md +2 -2
- package/extensions/auditor-extensions.ts +289 -0
- package/extensions/context-hygiene.ts +129 -0
- package/extensions/faulty-objective-recovery.ts +24 -0
- package/extensions/glla-state-root.ts +99 -0
- package/extensions/goal-agents-panel.ts +211 -0
- package/extensions/goal-commands.ts +226 -10
- package/extensions/goal-continuation.ts +119 -21
- package/extensions/goal-heartbeat.ts +560 -35
- package/extensions/goal-loop-auditor-process.ts +126 -4
- package/extensions/goal-loop-auditor.ts +3 -5
- package/extensions/goal-loop-backoff.ts +79 -0
- package/extensions/goal-loop-core.ts +197 -15
- package/extensions/goal-loop-dispatch.ts +3 -2
- package/extensions/goal-loop-display.ts +141 -8
- package/extensions/goal-loop-forever.ts +52 -3
- package/extensions/goal-loop-shield.ts +132 -26
- package/extensions/goal-loop-stats.ts +3 -2
- package/extensions/goal-loop.ts +101 -4
- package/extensions/goal-recovery.ts +8 -2
- package/extensions/goal-settings.ts +61 -14
- package/extensions/goal-state.ts +20 -0
- package/extensions/loops/goal-activation.ts +426 -45
- package/extensions/loops/goal-auditor-hooks.ts +39 -3
- package/extensions/loops/goal-auditor-surface.ts +32 -0
- package/extensions/loops/goal-list-queue.ts +72 -12
- package/extensions/loops/goal-orchestrator.ts +33 -1
- package/extensions/loops/goal-runtime-globals.ts +5 -0
- package/extensions/loops/goal-session.ts +68 -8
- package/extensions/loops/goal-settings-ui.ts +116 -5
- package/extensions/loops/goal-tools.ts +104 -29
- package/extensions/loops/goal-ui.ts +106 -1
- package/extensions/loops/goal.ts +7 -7
- package/extensions/main-model-recovery.ts +10 -0
- package/extensions/multi-model-picker.ts +45 -7
- package/extensions/payload-guard.ts +172 -0
- package/extensions/reviewer.ts +3 -1
- package/extensions/settings-menu.ts +39 -4
- package/package.json +9 -3
- package/prompts/goal-loop-plan-loop.md +31 -0
- package/prompts/goal-loop-plan.md +51 -0
- package/schemas/goal.schema.json +4 -1
- package/scripts/auditor-extension-fixture.mjs +19 -0
- package/scripts/goal-auditor-launch.mjs +19 -1
- package/scripts/goal-auditor-worker.mjs +15 -0
- package/scripts/verify-auditor-extensions-offline.mjs +72 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,982 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.35.64 — bounded recovery for frozen subagents (2026-08-25)
|
|
4
|
+
|
|
5
|
+
### Fix
|
|
6
|
+
A tracked top-level subagent that produces no tool-use or output-token
|
|
7
|
+
progress now receives the existing short warning first, then one
|
|
8
|
+
generation-fenced child-specific abort request after the configurable
|
|
9
|
+
`subagentHangEscalationMinutes` threshold (default 30; 0 keeps
|
|
10
|
+
warning/telemetry-only behavior). Nested, unreachable, or ownership-
|
|
11
|
+
ambiguous children remain warning-only. A stale child no longer shields an
|
|
12
|
+
unrelated parent zombie watchdog, and `/glla agents` shows ABORTING,
|
|
13
|
+
unavailable, or failed action state while preserving partial output.
|
|
14
|
+
|
|
15
|
+
### Tests
|
|
16
|
+
`tests/subagent-hang-detection.test.ts` covers one-shot escalation,
|
|
17
|
+
progress-before-action cancellation, manager-unavailable and nested-child
|
|
18
|
+
safety, and `tests/agents-panel.test.ts` pins the action surface. Settings
|
|
19
|
+
menu/editor and INSTALL documentation expose the new threshold.
|
|
20
|
+
|
|
21
|
+
### Follow-up hardening
|
|
22
|
+
Frozen-child escalation now uses pi-subagents' existing root-session
|
|
23
|
+
`subagents:rpc:stop` bridge, with readiness, ownership, generation, and
|
|
24
|
+
timeout-race fencing. The real AgentManager/RPC path is covered by a
|
|
25
|
+
deterministic pending-provider integration test without modifying the
|
|
26
|
+
upstream package.
|
|
27
|
+
|
|
28
|
+
Malformed saved goal/list objectives now produce a bounded repair/replan
|
|
29
|
+
card instead of a self-blocking first turn. One durable bootstrap turn
|
|
30
|
+
carries the complete preserved target and `propose_task_list` confirmation;
|
|
31
|
+
automatic repeats are fenced, while explicit `/list resume` re-arms one
|
|
32
|
+
retry. The card keeps its concrete recovery action and queue position
|
|
33
|
+
visible.
|
|
34
|
+
|
|
35
|
+
### Tests
|
|
36
|
+
Focused repair/replan, display, stale-probe, and RPC regressions are
|
|
37
|
+
included in the release contract. The complete gate remains the source of
|
|
38
|
+
truth for the published artifact.
|
|
39
|
+
|
|
40
|
+
## 0.35.63 — auditor context held until resume (2026-08-25)
|
|
41
|
+
|
|
42
|
+
### Fix
|
|
43
|
+
Cold session restores now keep unfinished goal/list objectives and their
|
|
44
|
+
status visible without automatically injecting the previous auditor report
|
|
45
|
+
or dispatching a new continuation. Explicit `/goal resume`, list/glla/loop
|
|
46
|
+
continuation commands, validated lifecycle continuity, and global
|
|
47
|
+
`autoResume: true` release the auditor-context gate. The prior Pi transcript
|
|
48
|
+
and durable audit history remain untouched.
|
|
49
|
+
|
|
50
|
+
### Tests
|
|
51
|
+
`tests/auditor-blank-until-resume.test.ts` proves objective visibility,
|
|
52
|
+
pre-consent report/TODO suppression, explicit resume release, auto-resume
|
|
53
|
+
release, and rejected stale-resume suppression. Version metadata is
|
|
54
|
+
synchronized to 0.35.63.
|
|
55
|
+
|
|
56
|
+
### Follow-up hardening
|
|
57
|
+
`/goal resume` now releases the auditor surface only after its existing
|
|
58
|
+
stale/foreign admission probe. Active-idle resumes receive the same probe;
|
|
59
|
+
stale paused resumes preserve the existing active/interrupted recovery
|
|
60
|
+
marker without exposing old auditor context. Main-model recovery resumes
|
|
61
|
+
now use the same stale/foreign admission probe and release the surface on
|
|
62
|
+
manual-hold, retry, and primary-probe recovery paths; a recovery regression
|
|
63
|
+
test pins the consent behavior.
|
|
64
|
+
|
|
65
|
+
## 0.35.62 — subagent host-state boundary (2026-08-25)
|
|
66
|
+
|
|
67
|
+
### Fix
|
|
68
|
+
Headless child sessions are now rejected before state-root registration,
|
|
69
|
+
restore, owner claims, and tool repair. The same fail-closed boundary covers
|
|
70
|
+
persistent children, foreign slash commands, and missing tool invocation
|
|
71
|
+
contexts. File-backed host successors remain eligible for legitimate reload
|
|
72
|
+
and silent-rebind recovery. Main-host subagent telemetry continues through
|
|
73
|
+
the event bus and `/glla agents` path.
|
|
74
|
+
|
|
75
|
+
### Tests
|
|
76
|
+
`tests/subagent-host-boundary.test.ts` proves first-claim prevention,
|
|
77
|
+
foreign slash-command refusal, persistent-worker refusal, legitimate host
|
|
78
|
+
successor admission, and durable Explore telemetry. Version metadata is
|
|
79
|
+
synchronized to 0.35.62.
|
|
80
|
+
|
|
81
|
+
## 0.35.61 — list queue visibility across host replacement (2026-08-25)
|
|
82
|
+
|
|
83
|
+
### Fix
|
|
84
|
+
Waiting-only list state now has an actionable status/widget projection even
|
|
85
|
+
when no list item is active. Silent host-successor and same-session stale
|
|
86
|
+
recovery boundaries also re-read the selected durable root and hydrate queue
|
|
87
|
+
sidecars before repainting. A recovered queue now stays visible and can be
|
|
88
|
+
started with `/list next` without requiring a full reload.
|
|
89
|
+
|
|
90
|
+
### Tests
|
|
91
|
+
`tests/list-invisible-restart.test.ts` covers waiting-only visibility and
|
|
92
|
+
activation plus sidecar-only silent-successor rehydration. Version metadata
|
|
93
|
+
is synchronized to 0.35.61.
|
|
94
|
+
|
|
95
|
+
## 0.35.60 — pre-turn glla tool visibility (2026-08-25)
|
|
96
|
+
|
|
97
|
+
### Fix
|
|
98
|
+
GLLA agent tools are now registered and reactivated immediately before
|
|
99
|
+
agent turns, with `agent_start`/`turn_start` compatibility fallbacks. This
|
|
100
|
+
closes the interval where an external tool allowlist or modlist could remove
|
|
101
|
+
`pause_goal` after session restore and Pi would answer a valid model call
|
|
102
|
+
with `Tool pause_goal not found`, leaving a parked objective looking stuck
|
|
103
|
+
until reload.
|
|
104
|
+
|
|
105
|
+
### Tests
|
|
106
|
+
`tests/gettick-tool-visibility.test.ts` simulates a post-restore active-tool
|
|
107
|
+
replacement and verifies the pre-turn boundary restores `pause_goal` and
|
|
108
|
+
keeps it callable. Version metadata is synchronized to 0.35.60.
|
|
109
|
+
|
|
110
|
+
## 0.35.59 — safe cancel/wipe across unresolved session roots (2026-08-25)
|
|
111
|
+
|
|
112
|
+
### Fix
|
|
113
|
+
`/glla cancel`, `/glla wipe`, `/list cancel`, `/list clear`, and the shared
|
|
114
|
+
goal archive path now fail closed while opt-in `sessionDir` resolution is
|
|
115
|
+
pending. They leave the in-memory objective/list untouched and do not
|
|
116
|
+
recreate or mutate an ambiguous cwd state tree; after host lifecycle
|
|
117
|
+
admission registers the session root, cancel and wipe archive/clear under
|
|
118
|
+
the selected session root as before.
|
|
119
|
+
|
|
120
|
+
### Tests
|
|
121
|
+
`tests/objective-loss-lifecycle.test.ts` covers both deferred destructive
|
|
122
|
+
commands and successful `/glla cancel` + `/glla wipe` cleanup under a
|
|
123
|
+
registered session root. Version metadata is synchronized to 0.35.59.
|
|
124
|
+
|
|
125
|
+
## 0.35.58 — objective-loss lifecycle repair (2026-08-24)
|
|
126
|
+
|
|
127
|
+
### Fix
|
|
128
|
+
Wired the opt-in `sessionDir` root into the admitted production lifecycle.
|
|
129
|
+
`session_start` and silent host-successor admission now register Pi's
|
|
130
|
+
canonical `SessionManager.getSessionDir()` before owner, invalidation, or
|
|
131
|
+
restore writes; in-memory worker sessions remain pending instead of creating
|
|
132
|
+
an ambiguous cwd tree. The configured session directory wins over an
|
|
133
|
+
imported session-file parent, while `PI_SESSION_FILE` remains the explicit
|
|
134
|
+
child-process fallback.
|
|
135
|
+
|
|
136
|
+
### Evidence
|
|
137
|
+
Added `tests/objective-loss-lifecycle.test.ts`: a real registered
|
|
138
|
+
`session_start` handler proves production root registration, and separate
|
|
139
|
+
fresh Bun writer/reader processes recover an objective across a cwd switch.
|
|
140
|
+
The report intentionally does not claim to simulate a crash mid-write or a
|
|
141
|
+
specific version migration. Full evidence:
|
|
142
|
+
audit/OBJECTIVE-LOSS-VALIDATION-2026-08-24.md.
|
|
143
|
+
|
|
144
|
+
### Tests
|
|
145
|
+
Focused lifecycle/state-root tests and clean tsc pass; the full release gate
|
|
146
|
+
is run for this version before closure.
|
|
147
|
+
|
|
148
|
+
## 0.35.57 — objective-loss validation (2026-08-24)
|
|
149
|
+
|
|
150
|
+
### Evidence
|
|
151
|
+
Validated the Now report that objectives disappeared after a Wez crash or
|
|
152
|
+
version/cwd switch. The historical workingDir default intentionally makes a
|
|
153
|
+
cwd switch select a different on-disk root, while explicit sessionDir keeps
|
|
154
|
+
the objective visible across cwd changes. Pending session-root resolution
|
|
155
|
+
does not migrate or delete the old cwd tree. The bounded result was
|
|
156
|
+
evidence-based closure pending production lifecycle wiring; crash-only loss
|
|
157
|
+
was not reproduced. The subsequent gettick, list-reload, and
|
|
158
|
+
subagent-visibility reports remain separate items.
|
|
159
|
+
Full evidence: audit/OBJECTIVE-LOSS-VALIDATION-2026-08-24.md.
|
|
160
|
+
## 0.35.56 — state-root consumer/lifecycle hardening (2026-08-24)
|
|
161
|
+
|
|
162
|
+
### Fix
|
|
163
|
+
Hardened every remaining state-root consumer and lifecycle boundary missed
|
|
164
|
+
by the core/settings slice. Raw `<cwd>/.pi-glla` joins in auditor jobs,
|
|
165
|
+
dispatch, goal-loop ledger reads, reviewer, stats rollup/discovery, and
|
|
166
|
+
session owner/handoff/pending-list paths now route through `piGlaDir` and
|
|
167
|
+
respect the selected root. Pending `sessionDir` resolution (no session dir
|
|
168
|
+
yet) is a strict deferral: dispatch, reviewer, session owner, handoff, and
|
|
169
|
+
pending-list writes return a deferred/false result without creating a
|
|
170
|
+
fallback `<cwd>/.pi-glla` tree, and legacy `.pi-gla` trees are still never
|
|
171
|
+
migrated. Audit-loop open-count helpers now resolve via the selected root
|
|
172
|
+
as well. Host/subagent ownership stays per-process via `PI_SESSION_FILE`
|
|
173
|
+
fallback and the explicit `setRuntimeSessionDir` hook — no global overwrite.
|
|
174
|
+
|
|
175
|
+
### Tests
|
|
176
|
+
New `tests/state-root-consumers.test.ts` pins resolved-root routing for
|
|
177
|
+
dispatch/stats/audit helpers, pending deferral for dispatch/reviewer, the
|
|
178
|
+
`PI_SESSION_FILE` fallback, and source-level absence of raw hardcodings plus
|
|
179
|
+
pending guards. Existing `tests/state-root.test.ts` continues to cover core
|
|
180
|
+
core/settings behavior. Red/green: breaking the `piGlaDir` routing makes the
|
|
181
|
+
consumer pins fail; restoring passes 9/9 focused plus 56 prior. tsc and full
|
|
182
|
+
release gate green for this tree.
|
|
183
|
+
## 0.35.55 — opt-in session-root state core/settings slice (2026-08-24)
|
|
184
|
+
|
|
185
|
+
### Fix
|
|
186
|
+
Ported the valid state-root portion of PR #21 onto current main without
|
|
187
|
+
merging the stale PR verbatim. New dependency-free
|
|
188
|
+
extensions/glla-state-root.ts owns the typed global root selector and
|
|
189
|
+
session-directory resolution so goal-loop-core can select a root without a
|
|
190
|
+
settings import cycle. The historical <cwd>/.pi-glla workingDir remains
|
|
191
|
+
the default; sessionDir is explicit opt-in and resolves to the top-level Pi
|
|
192
|
+
session directory (or PI_SESSION_FILE's parent for worker processes).
|
|
193
|
+
Session-root mode is global-only because project settings.json lives inside
|
|
194
|
+
the selected root. Pending sessionDir resolution is a write boundary:
|
|
195
|
+
core directory/ledger/queue/sentinel/audit-log writes defer rather than
|
|
196
|
+
recreate an ambiguous cwd tree, and old .pi-gla/.pi-glla trees are never
|
|
197
|
+
migrated or deleted by the new mode. The settings menu exposes the two
|
|
198
|
+
choices and project attempts to override stateRoot are stripped.
|
|
199
|
+
|
|
200
|
+
### Tests
|
|
201
|
+
tests/state-root.test.ts covers default cwd persistence, opt-in session-root
|
|
202
|
+
persistence, pending-write/no-migration behavior, PI_SESSION_FILE fallback,
|
|
203
|
+
and global-only settings round-trip. settings-editors and
|
|
204
|
+
settings-menu-complete pin the UI/provenance surface; the long-term
|
|
205
|
+
preferences boundary now checks the dependency-free global path owner.
|
|
206
|
+
Red/green proved the session-root branch is required (2 of 5 focused tests
|
|
207
|
+
fail when neutered; restored 5/5). tsc and focused tests pass before the
|
|
208
|
+
full release gate.
|
|
209
|
+
## 0.35.54 — RESUMABLE_STOP honors the v0.35.31 "metric never moved" stop (2026-08-24)
|
|
210
|
+
|
|
211
|
+
### Fix
|
|
212
|
+
Collect-pass HIGH finding: the v0.35.31 "metric never moved" stop reason
|
|
213
|
+
promises "/loop resume retries or /loop stop" in its own message, but the
|
|
214
|
+
RESUMABLE_STOP predicate in /loop resume never matched that prefix - the
|
|
215
|
+
promised command answered "No held loop to resume", and with
|
|
216
|
+
propose_loop_refine gated on an ACTIVE loop, the only recovery was
|
|
217
|
+
/loop stop + a fresh start discarding iteration history. Same class as
|
|
218
|
+
the v0.35.25 issue-#14 zombie prefix bug (fixed there for zero-stream,
|
|
219
|
+
missed for this brand-new prefix). The prefix is now resumable: resuming
|
|
220
|
+
re-arms the error/stuck/stall counters while preserving iteration, best,
|
|
221
|
+
and history; if the metric is still dead it re-stops loudly after its
|
|
222
|
+
window, and a measure-changing propose_loop_refine (usable again once
|
|
223
|
+
resumed) re-scopes the measure era so the never-moved grace re-arms.
|
|
224
|
+
|
|
225
|
+
### Tests
|
|
226
|
+
tests/metric-never-moved-resumable.test.ts: behavioral - a loop parked by
|
|
227
|
+
the exact production reason string resumes via /loop resume with
|
|
228
|
+
iteration/best/history preserved and all three streak counters re-armed;
|
|
229
|
+
negative pin - a bounded stop ("max iterations reached") stays
|
|
230
|
+
non-resumable. Red-proven by removing the predicate clause (behavioral
|
|
231
|
+
fails, negative pin stays green).
|
|
232
|
+
## 0.35.53 — false repair card after abort+reload: parser marker fix + contract-derived objective heal (2026-08-24)
|
|
233
|
+
|
|
234
|
+
### Fix
|
|
235
|
+
note.md Now: "objective needs repair issue, but before reload it looked
|
|
236
|
+
fine". Field forensics (neonbreak, item 20260823082852-in3rc7): the list
|
|
237
|
+
draft batch wrote an item with objective "" and the ENTIRE intent inside
|
|
238
|
+
the verification contract - extractVerificationContract's line marker
|
|
239
|
+
regex `verify\b[^:]*:` misread the imperative sentence "Verify the
|
|
240
|
+
shipped PREMIUM-UIUX pass (...): confirm ..." as a contract marker
|
|
241
|
+
("verify" is both a marker word and an ordinary imperative verb), leaving
|
|
242
|
+
the objective empty. The activation gate then correctly flagged "empty"
|
|
243
|
+
and jammed a repair card ahead of the item - 42
|
|
244
|
+
faulty_objective_list_activation_blocked events over 22 hours, an endless
|
|
245
|
+
repair-card loop that wedged the session. Two-layer durable fix:
|
|
246
|
+
(1) WRITER - the line marker for the ambiguous verbs now requires the
|
|
247
|
+
colon immediately ("Verify:" / "Verify when:" / "Verification:");
|
|
248
|
+
"done"/"done when"/"verified when" keep a bounded 60-char decorated-marker
|
|
249
|
+
gap so prose tails cannot masquerade as markers either. The field text
|
|
250
|
+
now parses with the real objective and only the grep tail as contract.
|
|
251
|
+
(2) READER - legacy items already persisted with an empty objective plus
|
|
252
|
+
a clean, actionable contract derive their objective deterministically
|
|
253
|
+
from the contract's leading imperative sentence at activation
|
|
254
|
+
(list_objective_derived_from_contract) instead of demanding a repair
|
|
255
|
+
card. Empty objective + absent or suspicious contract still takes the
|
|
256
|
+
true broken-objective repair path, unchanged.
|
|
257
|
+
|
|
258
|
+
### Tests
|
|
259
|
+
tests/false-repair-card.test.ts: the exact field text parses with its
|
|
260
|
+
intent in the objective; short-marker and decorated-marker forms still
|
|
261
|
+
parse; derivation unit rules (first sentence, suspicious/non-imperative
|
|
262
|
+
contracts rejected); behavioral - a legacy stuck item activates with the
|
|
263
|
+
derived objective (no repair demand, contract preserved), a truly broken
|
|
264
|
+
item still triggers the repair card, and a fresh /list add of the field
|
|
265
|
+
text activates directly end-to-end. Red-proven by neutering both layers
|
|
266
|
+
(4 of 6 fail; the true-broken-path tests stay green).
|
|
267
|
+
## 0.35.52 — context hygiene: era-scope failed error-only turns out of the effective context (2026-08-24)
|
|
268
|
+
|
|
269
|
+
### Fix
|
|
270
|
+
note.md Now: "failed requests add to the context, while clearly adding
|
|
271
|
+
nothing of value". When retries are exhausted, the failed assistant turn
|
|
272
|
+
(stopReason "error", errorMessage set, content empty/partial) STAYS in
|
|
273
|
+
agent state and the session - pi strips it from live state only for
|
|
274
|
+
mid-flight retries. Every later LLM call receives it and compaction
|
|
275
|
+
summarizes it; nothing downstream filters these. Field evidence (polis,
|
|
276
|
+
2026-08-23): a run of 503/network_error/retry-cancelled turns drove the
|
|
277
|
+
estimated context to 122.7% of the 200k window, and auto-compaction then
|
|
278
|
+
aborted on its own bloated summarization input. New
|
|
279
|
+
extensions/context-hygiene.ts: a durable bounded rule drops error-only
|
|
280
|
+
assistant turns (stopReason "error", NO tool-call blocks) from the
|
|
281
|
+
effective context EXCEPT the most recent one, which stays so the model
|
|
282
|
+
sees why the previous attempt failed on the retry send. Applied at two
|
|
283
|
+
points: the `context` event projection (per-send, transcript untouched -
|
|
284
|
+
alongside the v0.35.51 payload guard) and `session_before_compact`
|
|
285
|
+
(prunes the shared preparation object the compaction runner summarizes,
|
|
286
|
+
shrinking the summarizer request and keeping failures out of the summary).
|
|
287
|
+
Tool-call-carrying error turns own paired toolResults and stay intact;
|
|
288
|
+
"aborted" turns are user-intent boundaries and are never touched. Drops
|
|
289
|
+
are ledgered (context_hygiene_dropped / context_hygiene_compaction_input).
|
|
290
|
+
|
|
291
|
+
### Tests
|
|
292
|
+
tests/context-hygiene.test.ts: predicate (tool-carrying/aborted/healthy
|
|
293
|
+
never droppable); bounded drop rule (newest kept, older dropped, identity
|
|
294
|
+
preserved at/under the window, configurable window); seeded bloat (60
|
|
295
|
+
failures collapse, normal turns survive verbatim); in-place compaction
|
|
296
|
+
preparation pruning; behavioral wiring through MockPi for both hooks with
|
|
297
|
+
ledger assertions and clean-history no-op. Red-proven by neutering both
|
|
298
|
+
production call sites.
|
|
299
|
+
## 0.35.51 — payload guard: bound inline image bytes on every outgoing LLM call (2026-08-24)
|
|
300
|
+
|
|
301
|
+
### Fix
|
|
302
|
+
note.md Now: "req body too large due to images in context". Generated
|
|
303
|
+
images accumulate in conversation history as inline base64 blocks until
|
|
304
|
+
the provider rejects the request with 413 ("Downloaded image content
|
|
305
|
+
cannot exceed 30MB" / "Request Entity Too Large") - and every
|
|
306
|
+
main-model-recovery probe re-sent the same bloated history, so recovery
|
|
307
|
+
could never classify or heal the failure; the session was wedged until a
|
|
308
|
+
manual restart WITHOUT history. Two-layer durable fix: (1) a new
|
|
309
|
+
extensions/payload-guard.ts projects the outgoing message list at the pi
|
|
310
|
+
`context` event (fired before EVERY LLM call), bounding cumulative
|
|
311
|
+
inline-image bytes to 16MB - evicting the OLDEST images first, always
|
|
312
|
+
keeping the newest two, replacing each evicted block with a short text
|
|
313
|
+
placeholder. Disk history is untouched (per-send projection), and the
|
|
314
|
+
chokepoint protects ordinary turns AND recovery probes alike. Evictions
|
|
315
|
+
are ledgered as payload_guard_eviction. (2) classifyMainModelFailure now
|
|
316
|
+
maps 413/payload-size texts to "transient" - retryable in place, because
|
|
317
|
+
the payload guard (not a fallback-model switch) heals the size; the old
|
|
318
|
+
"unknown" classification burned the whole chain on useless rotations.
|
|
319
|
+
|
|
320
|
+
### Tests
|
|
321
|
+
tests/payload-guard.test.ts: under-budget pass-through (same identity);
|
|
322
|
+
oldest-first eviction with newest-two floor; floor holds when the budget
|
|
323
|
+
cannot be met; idempotent projection, non-image content untouched;
|
|
324
|
+
behavioral wiring (context handler projects + ledgeres; under-budget
|
|
325
|
+
passes unprojected); 413 texts classify transient (not unknown, not
|
|
326
|
+
context-overflow). Red-proven by neutering both production sites.
|
|
327
|
+
## 0.35.50 — same-process session successors auto-resume the main thread (2026-08-23)
|
|
328
|
+
|
|
329
|
+
### Fix
|
|
330
|
+
note.md Now #2: session-start auto-resume asymmetry. The v0.35.23 loop
|
|
331
|
+
branch treats a SAME-PROCESS session successor (shutdown recorded in the
|
|
332
|
+
owner sidecar with a non-quit reason, previous pid === current pid) as
|
|
333
|
+
mid-flight continuity and resumes held loops - but a plain ACTIVE goal
|
|
334
|
+
held ("restored on session load - held for explicit resume") and a parked
|
|
335
|
+
completion-audit claim stayed parked in that exact corner: from the
|
|
336
|
+
user's seat, the list kept going after the session replacement while the
|
|
337
|
+
goal sat "awaiting first turn". The goal restore gate and the auditor
|
|
338
|
+
claim's canRecoverNow now accept the same consent, refined per the
|
|
339
|
+
v0.34.49 one-shot identity law: a PRESENT handoff marker is authoritative
|
|
340
|
+
even when mismatched (rejection holds); only an ABSENT marker with a
|
|
341
|
+
same-pid non-quit shutdown is continuity - the same distinction
|
|
342
|
+
listOperationLifecycleResume already draws. Different-pid crash
|
|
343
|
+
successors and cold loads still hold for an explicit decision;
|
|
344
|
+
Auto-resume stays the only load-time automation for them.
|
|
345
|
+
|
|
346
|
+
### Tests
|
|
347
|
+
tests/same-process-successor-resume.test.ts: same-process successor
|
|
348
|
+
resumes a held ACTIVE goal (continuation dispatched, no stale interrupt
|
|
349
|
+
marker); same-process successor auto-retries a parked completion claim
|
|
350
|
+
(audit_recovery_auto_retry_claimed fence in the ledger); different-pid
|
|
351
|
+
crash successor still HOLDS (cold-load law). Red-proven by neutering
|
|
352
|
+
both consent sites; the v0.34.49 mismatched-marker identity test stays
|
|
353
|
+
green against the refined consent.
|
|
354
|
+
## 0.35.49 — parent-side silence watchdogs close the auditor-AWOL gap (2026-08-23)
|
|
355
|
+
|
|
356
|
+
### Fix
|
|
357
|
+
Field evidence across five projects (football-forever, doomtap,
|
|
358
|
+
junk-runner, email-api-compare, vps-compare): a detached auditor worker
|
|
359
|
+
whose provider hangs emits ONE boot RPC event (or none) and then total
|
|
360
|
+
silence. The v0.34.57 no-progress watchdog only arms while heartbeats
|
|
361
|
+
stay FRESH, so a stale heartbeat disarmed it, the worker's own stall
|
|
362
|
+
brake was the only other bound, and every doomed attempt burned its full
|
|
363
|
+
30m wall while the goal sat "auditing" and the queue looked dead. The
|
|
364
|
+
poll loop now owns two complementary silence axes with the same
|
|
365
|
+
running-tool exemption: heartbeat-stale (had an event, went silent for
|
|
366
|
+
the window) and first-event-timeout (never emitted anything within
|
|
367
|
+
firstEventTimeoutMs, a new runtime knob defaulting to the same window).
|
|
368
|
+
Both demote the HUD to quiet, emit auditor_stalled, terminate the
|
|
369
|
+
worker, and return retryable "timeout" infra - which the existing
|
|
370
|
+
fallback ladder re-drives with its eager 5s first retry instead of the
|
|
371
|
+
wall.
|
|
372
|
+
|
|
373
|
+
### Tests
|
|
374
|
+
tests/auditor-stall-watchdog.test.ts: three workers (silent since boot,
|
|
375
|
+
one-boot-heartbeat-then-silence, tool-open-silent) prove both axes fail
|
|
376
|
+
fast BEFORE the wall, classify as retryable infra, SIGTERM the worker,
|
|
377
|
+
and remove the job scratch; the third pins the running-tool exemption.
|
|
378
|
+
Red-proven against pre-change code: both stall runs burned the full
|
|
379
|
+
wall and never stalled. tests/auditor-process.test.ts heartbeat test
|
|
380
|
+
disarms the new axis (firstEventTimeoutMs) to isolate its own.
|
|
381
|
+
## 0.35.48 — overdue-wait backstop respects the dispatch-surface gates (2026-08-23)
|
|
382
|
+
|
|
383
|
+
### Fix
|
|
384
|
+
Audit-pass finding: overdueWaitBackstop mutated durable state (parked to
|
|
385
|
+
active, pauseResumeAt cleared) without checking the
|
|
386
|
+
extensionApiStale/sessionHandoffPending/stale-terminal or
|
|
387
|
+
mainModelRecoveryActive gates - during a latched-stale heartbeat a
|
|
388
|
+
durably parked wait could become an ACTIVE goal with no dispatch until a
|
|
389
|
+
fresh session_start, breaking the paused-is-safe invariant. The backstop
|
|
390
|
+
now refuses mid-handoff and stale-latched windows, and under an active
|
|
391
|
+
main-model recovery releases ONLY recovery-routed waits (the probe route
|
|
392
|
+
re-parks with a fresh resumeAt on failure) - unrelated agent-authored
|
|
393
|
+
waits stay parked until recovery resolves. The gates sit BEFORE the
|
|
394
|
+
lastOverdueWaitKey one-shot latch so skipped windows stay retriable.
|
|
395
|
+
|
|
396
|
+
## 0.35.47 — completions/handler parity for /list and /loop verbs (2026-08-23)
|
|
397
|
+
|
|
398
|
+
### Fix
|
|
399
|
+
Audit-pass finding: verbs handled by the dispatchers but absent from the
|
|
400
|
+
subcommand completions - /list add|import|rm (and pause, caught while
|
|
401
|
+
pinning), and /loop resume|refine|polish. All seven now appear in their
|
|
402
|
+
getArgumentCompletions tables with accurate descriptions. A generic
|
|
403
|
+
parity pin in tests/command-registration-collisions.test.ts scans every
|
|
404
|
+
`sub === "x"` dispatch literal inside cmdList/cmdLoop and fails when a
|
|
405
|
+
handled verb has no completion entry - future verbs cannot ship
|
|
406
|
+
half-registered.
|
|
407
|
+
|
|
408
|
+
## 0.35.46 — /glla agents --tail sanitization + bounded scan reads (2026-08-23)
|
|
409
|
+
|
|
410
|
+
### Fix
|
|
411
|
+
Audit-pass finding, two parts: (1) child-transcript tail lines were
|
|
412
|
+
rendered through ctx.ui.notify WITHOUT ANSI/control-character
|
|
413
|
+
sanitization - unlike every other external-text projection - so a
|
|
414
|
+
hostile child transcript could emit terminal escape sequences;
|
|
415
|
+
formatTranscriptEntry now runs all output paths (both [raw] fallbacks
|
|
416
|
+
and the [role] text path) through sanitizeDisplayText. (2) The candidate
|
|
417
|
+
scan synchronously read up to 25 FULL transcript files on the main
|
|
418
|
+
thread; the reader contract now takes an optional maxBytes and the
|
|
419
|
+
production command passes a real partial tail read (256 KiB window,
|
|
420
|
+
TRANSCRIPT_SCAN_MAX_BYTES), so the scan touches at most the last 256 KiB
|
|
421
|
+
of each candidate. The single matched file still gets a full read so the
|
|
422
|
+
"last N of M" detail stays honest.
|
|
423
|
+
|
|
424
|
+
## 0.35.45 — plan-mode seeded hint separator (2026-08-23)
|
|
425
|
+
|
|
426
|
+
### Fix
|
|
427
|
+
Audit-pass finding: planNote ended "...than a regular draft." and was
|
|
428
|
+
concatenated directly with the label hint, producing
|
|
429
|
+
"...regular draft.Goal drafting - deep planning: ..." in the notified
|
|
430
|
+
seeded hint. The join is now explicit (planNote ? `${planNote} ` : "").
|
|
431
|
+
Behavioral test drives the real /goal plan command with a seed and
|
|
432
|
+
asserts the notified hint reads "regular draft. Goal drafting - deep
|
|
433
|
+
planning:"; proven red with the glued concatenation restored.
|
|
434
|
+
|
|
435
|
+
## 0.35.44 — draftingDepth dead state removed; orphaned-gate windows closed (2026-08-23)
|
|
436
|
+
|
|
437
|
+
### Fix
|
|
438
|
+
Audit-pass finding, three parts: (1) the draftingDepth runtime global was
|
|
439
|
+
write-only dead state - set in startDrafting, reset in clearDraftingState,
|
|
440
|
+
zero readers (template selection uses the depth parameter) - removed
|
|
441
|
+
outright; "no target => normal depth" now holds by construction, so no
|
|
442
|
+
consumer can observe stale depth across proposal-completion paths.
|
|
443
|
+
(2) The two bare `draftingTarget = null` completion paths that skipped the
|
|
444
|
+
drafter-model restore (batch-activation conflict refusal, zombie-twin
|
|
445
|
+
rejection) now restore like every other exit. (3) beginDrafterModel moved
|
|
446
|
+
inside a try that clears the drafting gate on throw - a throw used to
|
|
447
|
+
leave the orphaned gate startDrafting's own header warns about.
|
|
448
|
+
|
|
449
|
+
## 0.35.43 — refine re-baselines specChecked with the spec write (2026-08-23)
|
|
450
|
+
|
|
451
|
+
### Fix
|
|
452
|
+
Audit-pass finding: refine's orchestrator-side spec write updated
|
|
453
|
+
specHash but not loop.specChecked, so the next tick saw checked >
|
|
454
|
+
specChecked against the OLD file's count and ledged spec_item_progress
|
|
455
|
+
attributed to the agent's iteration - unearned progress feeding the
|
|
456
|
+
multi-signal stuck gate (the user confirmed the respec; the agent may
|
|
457
|
+
have done nothing). The refine handler now re-baselines specChecked
|
|
458
|
+
together with specHash after writing the new spec.
|
|
459
|
+
|
|
460
|
+
## 0.35.42 — measure-era scoping for loop movement accounting (2026-08-23)
|
|
461
|
+
|
|
462
|
+
### Fix
|
|
463
|
+
Audit-pass finding: applyRefinement re-baselines best/last/stall on a
|
|
464
|
+
measure-changing refine but keeps history, so OLD-era improved entries
|
|
465
|
+
made both movement checks permanently true for the NEW metric era - the
|
|
466
|
+
v0.35.31 flat-reading grace could never apply after a measure-changing
|
|
467
|
+
refine, and a dead new metric could never earn its never-moved stop.
|
|
468
|
+
applyMeasurement now scopes metricHasMoved and metricNeverMoved to the
|
|
469
|
+
current measure era (history after the last measure-changing
|
|
470
|
+
refinement's iteration; the boundary was already recorded on every
|
|
471
|
+
LoopRefinement). Two twin tests proven red without the scoping, green
|
|
472
|
+
with it.
|
|
473
|
+
|
|
474
|
+
## 0.35.41 — the last two loop-stop routes announce queue resumption (2026-08-23)
|
|
475
|
+
|
|
476
|
+
### Fix
|
|
477
|
+
Audit-pass finding: v0.35.22's "ends by ANY route ... ANNOUNCE loudly"
|
|
478
|
+
contract was only wired into some stop routes. The stuck-ladder stop and
|
|
479
|
+
the provider-error/abort-cap stop notified the loop line but never
|
|
480
|
+
announced that waiting list items can start again - a dead silent entry.
|
|
481
|
+
Both routes now call announceQueuedListAfterLoopEnd (exported from
|
|
482
|
+
goal-loop.ts for the goal-activation site). Two twin behavioral tests
|
|
483
|
+
drive each production route against a seeded waiting queue; both proven
|
|
484
|
+
red with their call neutered, green restored.
|
|
485
|
+
|
|
486
|
+
## 0.35.40 — regression pins for the audit-kind measurement exemption (2026-08-23)
|
|
487
|
+
|
|
488
|
+
### Tests
|
|
489
|
+
Audit-pass finding: commit 28131527's audit-kind exemption in
|
|
490
|
+
applyMeasurement shipped with zero regression pin. Two twin-loop tests in
|
|
491
|
+
tests/loop-forever.test.ts now pin it: (1) identical flat-metric shapes
|
|
492
|
+
diverge by kind - the audit loop counts every flat toward plateau from
|
|
493
|
+
iteration 1 while the non-audit loop's pre-movement flats stay free;
|
|
494
|
+
(2) a dead metric gets the dedicated "metric never moved" stop on plain
|
|
495
|
+
loops but never on audit loops, whose final verdict stays plateau.
|
|
496
|
+
Red/green proven: deleting both halves of guard one fails both twins;
|
|
497
|
+
the never-moved kind-guard proved unreachable-by-construction for audits
|
|
498
|
+
(plateau always returns first) and is pinned in source instead.
|
|
499
|
+
|
|
500
|
+
## 0.35.39 — README Files map is actually complete (2026-08-23)
|
|
501
|
+
|
|
502
|
+
### Docs
|
|
503
|
+
Audit-pass finding: the Files map showed 4 of 7 prompts (missing both
|
|
504
|
+
plan-draft prompts shipped in v0.35.33 and goal-loop-forever-metricless)
|
|
505
|
+
and ~19 of 44 extensions files while reading as complete. The map now
|
|
506
|
+
enumerates every file - 34 extensions/ + 10 loops/ + 7 prompts/ + all
|
|
507
|
+
scripts/ - grouped by concern, with one-line descriptions verified
|
|
508
|
+
against each module's exports.
|
|
509
|
+
|
|
510
|
+
# 0.35.38 — README verb-semantics documentation (2026-08-23)
|
|
511
|
+
|
|
512
|
+
### Docs
|
|
513
|
+
User-requested audit finding: what /goal|/list|/loop audit MEAN vs start
|
|
514
|
+
vs the plan verbs lived only in code comments. New "What the verbs mean"
|
|
515
|
+
table right after the quick-start block (audit is deliberately three
|
|
516
|
+
machines: one-shot fix-in-pass goal, collect-then-drain list item,
|
|
517
|
+
forever cadence loop; plan = extended draft on all surfaces; verify
|
|
518
|
+
audits the CURRENT goal, not the project), the drafting-rules paragraph
|
|
519
|
+
now names plan as the fourth depth, and "Which loop?" cross-links it.
|
|
520
|
+
Includes the DECIDED semantics: /list plan takes prose only — a file
|
|
521
|
+
path stays bulk import; files mentioned inside /list plan are research
|
|
522
|
+
input, never auto-imported.
|
|
523
|
+
|
|
524
|
+
## 0.35.37 — recovery welcome-back notice now fires exactly once (2026-08-23)
|
|
525
|
+
|
|
526
|
+
### Fix
|
|
527
|
+
Audit-pass finding: autoResumedAt/autoResumedEvent were set by three
|
|
528
|
+
auto-recovery sites (heartbeat overdue-wait backstop, main-model provider
|
|
529
|
+
recovery, auditor provider retry) but the ONLY clearing site was MANUAL
|
|
530
|
+
resume — so the continuation prompt injected the "WELCOME BACK, YOU WERE
|
|
531
|
+
RECOVERED" directive into EVERY dispatch of a goal that kept running days
|
|
532
|
+
after one recovery. The accepted-dispatch site in sendContinuation now
|
|
533
|
+
marks the notice delivered: the stamp clears and a
|
|
534
|
+
recovery_notice_delivered ledger entry records it, so the directive is
|
|
535
|
+
injected exactly once per auto-resume. Manual /goal resume keeps its own
|
|
536
|
+
clearing (user-driven, no notice needed).
|
|
537
|
+
|
|
538
|
+
## 0.35.36 — complete_goal newObjective no longer launders agent text into userSeeds (2026-08-23)
|
|
539
|
+
|
|
540
|
+
### Fix
|
|
541
|
+
Audit-pass finding: the newObjective branch appended the AGENT-authored
|
|
542
|
+
objective to objectiveProvenance.userSeeds; since createdVia stays "user"
|
|
543
|
+
from creation, the v0.35.31 seed trust then treated that agent-written
|
|
544
|
+
text as explicit user prose and dispatched it verbatim past the
|
|
545
|
+
suspicious-objective fence. userSeeds is now strictly human-confirmed
|
|
546
|
+
text (creation arg, /goal tweak Confirm dialog, repair-redraft task-list
|
|
547
|
+
confirm); a newObjective pivot is recorded via its goal_tweaked ledger
|
|
548
|
+
entry and reviewed by the isolated auditor against the NEW contract in
|
|
549
|
+
the same call. Regression test proves red-on-laundering /
|
|
550
|
+
green-on-fix; behavioral consequence observed: heuristic-tripping pivots
|
|
551
|
+
on user goals now flow through the normal fence (auto-restore from the
|
|
552
|
+
durable original) instead of being waved through.
|
|
553
|
+
|
|
554
|
+
## 0.35.35 — user-seed trust works with contract clauses and role markers (2026-08-23)
|
|
555
|
+
|
|
556
|
+
### Fix
|
|
557
|
+
Audit-pass finding: v0.35.31's seed trust compared the CLEANED
|
|
558
|
+
goal.objective against RAW stored seeds by exact equality — but createGoal
|
|
559
|
+
strips "Done when:" clauses and Agent:/Role: declarations out of the
|
|
560
|
+
objective while keeping the raw arg as the seed, so any seeded goal WITH a
|
|
561
|
+
clause/role silently no-op'd the trust and still parked behind the
|
|
562
|
+
suspicious-objective heuristic. New pure helper objectiveIsUserSeeded()
|
|
563
|
+
normalizes BOTH sides through the same extraction pipeline the creation
|
|
564
|
+
path applies; createdVia still gates WHO is trusted (agent-authored seeds
|
|
565
|
+
gain nothing). Regression tests: clause+role user seeds dispatch verbatim;
|
|
566
|
+
reviewer-created goals with matching-cleaned seeds never get the trust.
|
|
567
|
+
|
|
568
|
+
### Mechanical pre-audit: maxBuffer ceiling killed verbose green suites (2026-08-23)
|
|
569
|
+
|
|
570
|
+
#### Fix
|
|
571
|
+
runMechanicalPreAuditChecks passed no maxBuffer to execFileSync, so
|
|
572
|
+
Node's default 1 MB cap applied: any contract gate whose output exceeds
|
|
573
|
+
1 MB gets its child SIGTERMed by Node and the call throws ENOBUFS —
|
|
574
|
+
which the banner logic (signal==="SIGTERM") then misreported as "killed
|
|
575
|
+
after 600s". Field incident (2026-08-23, five consecutive auditor
|
|
576
|
+
rounds on hellhunter's `bun test src/lib/game`): the gate emits ~1.17 MB
|
|
577
|
+
of ALL-PASSING output and was unpassable by construction — every attempt
|
|
578
|
+
died at ~1 MB (~15s in) while the identical tree passed green from an
|
|
579
|
+
interactive shell 19/19 times, including piped-output and single-core
|
|
580
|
+
pinned runs. Now passes maxBuffer: 64 MB, and ENOBUFS deaths no longer
|
|
581
|
+
print the misleading 600s timeout banner.
|
|
582
|
+
|
|
583
|
+
## 0.35.34 — lastOutcome actually durable (2026-08-23)
|
|
584
|
+
|
|
585
|
+
### Fix
|
|
586
|
+
Audit-pass finding: v0.35.30's "durable" last-outcome record was never
|
|
587
|
+
serialized — persistStateLine omitted the field and readState never
|
|
588
|
+
restored it, so any restart/reload blanked the widget retention line
|
|
589
|
+
within its 24h window (the exact failure v0.35.30 fixed). Now always
|
|
590
|
+
written (null when absent — readState spreads successive state events, so
|
|
591
|
+
an omitted key would resurrect stale values and /glla wipe could never
|
|
592
|
+
clear the record) and restored through a strict shape sanitizer (corrupt
|
|
593
|
+
lines degrade to absent, never throw). Round-trip + corruption regression
|
|
594
|
+
tests added.
|
|
595
|
+
|
|
596
|
+
## 0.35.33 — plan mode: the extended draft (2026-08-22)
|
|
597
|
+
|
|
598
|
+
### Add
|
|
599
|
+
/goal plan | /list plan | /loop plan — the EXTENDED DRAFT for
|
|
600
|
+
greenfield/megaplan work where the standard 5–7-question interview is too
|
|
601
|
+
shallow (user design 2026-08-22). Research BEFORE questions (Explore
|
|
602
|
+
subagents, file reads), multi-round interviewing (architecture → scope →
|
|
603
|
+
failure conditions → verification), and a structured expanded objective:
|
|
604
|
+
current-state analysis, decisions with rationale, milestone breakdown,
|
|
605
|
+
per-milestone verification contract. Deliberately NOT a separate artifact —
|
|
606
|
+
the objective itself is the single truth (the respec lesson: a second
|
|
607
|
+
document always goes stale). Trust machinery unchanged: propose_*_draft +
|
|
608
|
+
the Confirm card still gate activation; regular drafts stay the fast path.
|
|
609
|
+
New prompts prompts/goal-loop-plan.md + goal-loop-plan-loop.md; depth flag
|
|
610
|
+
on the drafting session (runtime-global, reset by clearDraftingState);
|
|
611
|
+
completions on all three commands; /list plan gated as a mutating verb on
|
|
612
|
+
stale handles. respec stays untouched (kept by user decision).
|
|
613
|
+
|
|
614
|
+
## 0.35.32 — hermetic settings round-trip test (2026-08-22)
|
|
615
|
+
|
|
616
|
+
### Fix
|
|
617
|
+
tests/auditor-extensions.test.ts depended on the developer machine having
|
|
618
|
+
~/.pi/agent extensions to discover: on a bare CI home the discovered list
|
|
619
|
+
was empty, the handler fell back to the input prompt, and the TUI-picker
|
|
620
|
+
branch under test never ran (publish workflow failure). The test now seeds
|
|
621
|
+
a project-scope `.pi/extensions/hermetic-ext.js` so discovery is non-empty
|
|
622
|
+
on every machine; verified green under both an empty HOME and a populated one.
|
|
623
|
+
|
|
624
|
+
## 0.35.31 — user-seed trust for /goal start; loop plateau no longer false-stops on a never-moved baseline (2026-08-22)
|
|
625
|
+
|
|
626
|
+
### Fix 1: explicit /goal start paused by the suspicious-objective heuristic
|
|
627
|
+
Field: Screenshot_20260822_193744 — `/goal start "…because we are logged in"`
|
|
628
|
+
was parked as "Suspicious objective detected (dangling-fragment)" with a
|
|
629
|
+
repair task queued instead of dispatching. The fragment heuristics exist
|
|
630
|
+
for AGENT-authored report garbage; an explicit `/goal start` whose
|
|
631
|
+
objective is verbatim a user seed now dispatches and ledgers
|
|
632
|
+
`faulty_objective_user_seed_trusted` (/goal tweak remains available).
|
|
633
|
+
### Fix 2: loop plateau vs a degenerate zero baseline
|
|
634
|
+
Field: doomtap loop stopped "plateau — best: 0" while iterations visibly
|
|
635
|
+
fixed real findings: a min-direction metric reading 0 before work starts
|
|
636
|
+
pins best at 0, so every later productive reading scores flat and burns
|
|
637
|
+
plateau slots. Flat readings now count toward plateau only once the metric
|
|
638
|
+
has demonstrably moved (an improvement on record, or best ≠ first measured
|
|
639
|
+
reading of the run); a metric that NEVER moves gets its own loud bounded
|
|
640
|
+
stop ("metric never moved …") after 2× window, not a fake plateau.
|
|
641
|
+
|
|
642
|
+
## 0.35.30 — durable last-outcome retention: the final verdict stays visible (2026-08-22)
|
|
643
|
+
|
|
644
|
+
### Gap
|
|
645
|
+
Field report with screenshots (email-api-compare, 2026-08-22): "goal gets
|
|
646
|
+
closed before final audit, so auditor never approves." Forensics showed the
|
|
647
|
+
lifecycle was CORRECT — every archived goal had an approving verdict — but
|
|
648
|
+
closeArchivedSlot nulled the widget slot the moment the goal archived, so
|
|
649
|
+
after the agent's turn ended the surface went completely blank and the only
|
|
650
|
+
trace of the approval was one transient toast. Returning later, "Auditor
|
|
651
|
+
verdict pending" was the last visible text: indistinguishable from closed-
|
|
652
|
+
without-audit.
|
|
653
|
+
### Ship
|
|
654
|
+
- State.lastOutcome {at, ok, title, recap}: written by closeArchivedSlot on
|
|
655
|
+
every terminal slot close (approved AND aborted), overwritten per outcome.
|
|
656
|
+
- Widget: while no goal/list/loop occupies the slot, one dim retention line
|
|
657
|
+
renders for 24h — "✓ done · auditor … approved · <recap>" or "▪ ended ·
|
|
658
|
+
<reason>" — then goes silent. A live goal always outranks it.
|
|
659
|
+
- /glla wipe clears the record (clean slate means clean).
|
|
660
|
+
- Tests: tests/last-outcome-retention.test.ts (5) — render shapes, expiry +
|
|
661
|
+
garbage-timestamp safety, live-goal precedence, source pins for both
|
|
662
|
+
write and wipe-clear sites.
|
|
663
|
+
|
|
664
|
+
## 0.35.29 — /glla agents: tracked-subagent panel, transcript tail, widget segment (2026-08-22, GitHub issue #15)
|
|
665
|
+
|
|
666
|
+
### Gap
|
|
667
|
+
During long fan-outs the only child visibility was the widget's 3-slot
|
|
668
|
+
recent-action ring. A child that "almost completed its final report, went
|
|
669
|
+
back to check some more, then crashed" was invisible: no live status, no
|
|
670
|
+
counters, and no post-mortem trail anyone could find (issue #15).
|
|
671
|
+
Scope agreed with the user: panel + transcript tail + widget line; a live
|
|
672
|
+
activity stream was explicitly rejected as too noisy.
|
|
673
|
+
### Ship
|
|
674
|
+
- getSubagentAgentsSnapshot() (goal-heartbeat.ts): read-only view of the
|
|
675
|
+
tracked-subagent probes with hung classification mirroring the watchdog
|
|
676
|
+
scan WITHOUT its counter mutation; record-frozen vs event-only evidence
|
|
677
|
+
named; degrades gracefully when the pi-subagents manager registry is
|
|
678
|
+
absent (as on currently installed versions).
|
|
679
|
+
- /glla agents: ranked table (hung > running > ended), per-child
|
|
680
|
+
tools/output/silent clocks, liveness hint on hung rows, 20-row cap with
|
|
681
|
+
an explicit trim notice. Read-only, stale-safe.
|
|
682
|
+
- /glla agents --tail <id> [--lines N]: locates the child's session file
|
|
683
|
+
in the cwd-munged session store by needle + newest mtime and prints the
|
|
684
|
+
last N entries tolerantly ([role] text, raw fallback). LOUD when nothing
|
|
685
|
+
matches — searched dir, transcript count, needles. Never resumes or
|
|
686
|
+
attaches to a child session.
|
|
687
|
+
- Widget segment: "● N agents · <busiest> silent Xm ⚠" appended to every
|
|
688
|
+
card shape via buildWidgetLines; hidden at zero tracked children.
|
|
689
|
+
- New pure module extensions/goal-agents-panel.ts; snapshot reaches
|
|
690
|
+
goal-commands via CommandDeps injection (no heartbeat import cycle).
|
|
691
|
+
|
|
692
|
+
## 0.35.28 — due-wait backstop: lapsed wait pauses actually resume; "you were recovered" notice (2026-08-22, GitHub issue #16)
|
|
693
|
+
|
|
694
|
+
### Root cause (field: goal paused 30min past its scheduled auto-resume while the agent narrated "the system should have auto-resumed by now")
|
|
695
|
+
Auto-resume for pauseKind "wait" relied SOLELY on in-memory timers. An
|
|
696
|
+
exhaustive map of every wait-pause site found: agent-authored waits
|
|
697
|
+
(pause_goal kind="wait") armed NO timer at all while their own copy
|
|
698
|
+
promised automatic continuation; error-brake cooldown waits were not
|
|
699
|
+
re-armed on session_start; single-slot provider-retry timers could be
|
|
700
|
+
silently clobbered by a later schedule; and no code path anywhere compared
|
|
701
|
+
wall time against pauseResumeAt outside display rendering.
|
|
702
|
+
### Fix
|
|
703
|
+
The heartbeat owns the durable invariant now: every tick, a wait whose
|
|
704
|
+
pauseResumeAt lapsed >90s is re-fired — main-model recovery waits route to
|
|
705
|
+
a provider probe, everything else clears the park and dispatches one fresh
|
|
706
|
+
continuation. supervisorPaused() still freezes it under /glla pause and
|
|
707
|
+
the load hold, one attempt per (goalId:resumeAt) key prevents storms (the
|
|
708
|
+
route re-parks with a fresh resumeAt on failure), and every fire is
|
|
709
|
+
ledgered wait_pause_overdue_resume. A stale hold persisted by a previous
|
|
710
|
+
process is released when a consenting reload arrives. Issue part 2:
|
|
711
|
+
resumed goals carry an autoResumed stamp rendered as a RECOVERY NOTICE in
|
|
712
|
+
the continuation prompt — "welcome back, YOU were recovered" — so agents
|
|
713
|
+
stop waiting for an external recovery signal that already happened.
|
|
714
|
+
|
|
715
|
+
## 0.35.27 — Windows auditor launch: quote only when needed, gate always first (2026-08-22, PR #17)
|
|
716
|
+
|
|
717
|
+
### Field report (PR #17, reproduced on Windows 11 + pnpm global shim)
|
|
718
|
+
The detached auditor died ~0.5s after launch and retried forever: quoting
|
|
719
|
+
EVERY argument wraps a bare executable name in quotes, which changes how
|
|
720
|
+
cmd.exe resolves it and how npm/pnpm .CMD shims compute their own
|
|
721
|
+
directory -> MODULE_NOT_FOUND -> "pi exited without an agent_settled RPC
|
|
722
|
+
event" in a 60s retry loop of flashing terminal windows.
|
|
723
|
+
### Fix
|
|
724
|
+
buildAuditorPiSpawnSpec now runs the WINDOWS_UNSAFE_ARG rejection on EVERY
|
|
725
|
+
argument BEFORE the quoting decision, then quotes only when tokenization
|
|
726
|
+
requires it (whitespace / cmd metacharacters / empty). Clean bare tokens
|
|
727
|
+
reach cmd.exe untouched (shims resolve; full RPC sessions work); the
|
|
728
|
+
upstream PR's variant was not mergeable as-is because its needs-quoting
|
|
729
|
+
regex also gated the unsafe-arg check, letting %/CR/LF through bare.
|
|
730
|
+
Regression tests pin all three classes through the spec builder.
|
|
731
|
+
|
|
732
|
+
## 0.35.26 — zombie watchdog recognizes pi-subagents tool names (2026-08-22, GitHub issue #13)
|
|
733
|
+
|
|
734
|
+
### Gap
|
|
735
|
+
The v0.35.4 subagent-wait carve-out matched only the legacy built-in names
|
|
736
|
+
(Agent / get_subagent_result / steer_subagent). The pi-subagents extension
|
|
737
|
+
registers its foreground dispatch tool as "subagent" and a blocking wait as
|
|
738
|
+
"subagent_wait", so a parent legitimately BUSY on a healthy foreground child
|
|
739
|
+
tripped the bounded abort: field report shows a child writing Postgres
|
|
740
|
+
records productively for 30 minutes while the parent was stream-silent on
|
|
741
|
+
`subagent` — zombie_run_suspected at 20m, loop_stopped + zombie_run_aborted
|
|
742
|
+
at 30m, productive work killed mid-write.
|
|
743
|
+
### Fix
|
|
744
|
+
One shared SUBAGENT_WAIT_TOOL_NAMES set + isSubagentWaitCall predicate in
|
|
745
|
+
goal-heartbeat.ts, consumed by BOTH sites (zombie stand-down and wedge-alert
|
|
746
|
+
hint) so the lists cannot drift apart again. New names: "subagent",
|
|
747
|
+
"subagent_wait". Behavioral tests drive the real heartbeat tick with a real
|
|
748
|
+
tool_call event: stand-down while in flight, clean abort once it settles,
|
|
749
|
+
no blanket amnesty.
|
|
750
|
+
|
|
751
|
+
## 0.35.25 — /loop resume honors the zero-stream abort park (2026-08-22, GitHub issue #14)
|
|
752
|
+
|
|
753
|
+
### Gap
|
|
754
|
+
abortZombieRun parks a loop with stopReason "stopped: automatic zero-stream
|
|
755
|
+
abort — ... (iteration N preserved; /loop resume to retry)" and its message
|
|
756
|
+
promises /loop resume — but the RESUMABLE_STOP predicate in the resume
|
|
757
|
+
handler never matched that prefix. The explicit resume answered "No held
|
|
758
|
+
loop to resume"; iteration count, best value, and preserved history were
|
|
759
|
+
unreachable without re-drafting from scratch (field report: a metricless
|
|
760
|
+
24h loop parked at iteration 210 with 200 history entries).
|
|
761
|
+
### Fix
|
|
762
|
+
RESUMABLE_STOP gains the "stopped: automatic zero-stream abort" prefix.
|
|
763
|
+
The explicit resume now re-arms the loop exactly as promised: fresh stall
|
|
764
|
+
window, re-armed counters, load hold released, one new dispatch — with
|
|
765
|
+
iteration/best/history intact. Control test pins that non-resumable stops
|
|
766
|
+
(e.g. bounds) stay stopped.
|
|
767
|
+
|
|
768
|
+
## 0.35.24 — auditor model picker at full selector parity: forbidden-models filtering (2026-08-22, note.md Next #1)
|
|
769
|
+
|
|
770
|
+
### Gap
|
|
771
|
+
The /glla -> Auditor model row already hosted the /model-style fuzzy
|
|
772
|
+
picker and persisted to the exact key resolveAuditorModel reads — but
|
|
773
|
+
unlike every main-agent flow it did NOT apply forbidden-models policy:
|
|
774
|
+
blocked models appeared in the list and the typed escape hatch accepted
|
|
775
|
+
them, yielding pins the resolver silently skips at audit time.
|
|
776
|
+
### Fix
|
|
777
|
+
promptModelRef gains an excludeRefs opt threading into buildModelPickItems
|
|
778
|
+
(list-level filter) AND validating typed entries against isForbiddenModel
|
|
779
|
+
(a policy match is refused with a warning naming the ref — never saved).
|
|
780
|
+
Both auditor slots use it: Auditor model and Auditor fallback agent.
|
|
781
|
+
A pin saved by the picker is one the resolver honors; runtime skips
|
|
782
|
+
(auditor_model_fallback reason:"forbidden") remain as belt-and-suspenders.
|
|
783
|
+
|
|
784
|
+
## 0.35.23 — load without autostart: cold sessions hold automation for an explicit decision (2026-08-22, note.md Next #2)
|
|
785
|
+
|
|
786
|
+
### Root cause
|
|
787
|
+
shouldAutoResumeOnSessionStart already demanded explicit `autoResume ===
|
|
788
|
+
true` (v0.28.21 tri-state, undefined default = HOLD) — but its only
|
|
789
|
+
consumer fed it the AGGRESSIVE-MODE COERCED value (unset -> true because
|
|
790
|
+
aggressiveMode defaults on), so stock installs auto-resumed everything on
|
|
791
|
+
every session load despite the documented default. Three further paths
|
|
792
|
+
bypassed the consent entirely.
|
|
793
|
+
### Fixes
|
|
794
|
+
- Load consent now reads the RAW global autoResume setting; aggressive
|
|
795
|
+
mode keeps owning its caps only. Default (unset/false) = restore and
|
|
796
|
+
DISPLAY state, hold automation.
|
|
797
|
+
- New durable loadHoldAt state engages through the SAME freeze gates as
|
|
798
|
+
/glla pause (continuation dispatch, loop ticks, heartbeat refires,
|
|
799
|
+
recovery timers); released by any explicit work command (/goal resume,
|
|
800
|
+
/list resume, /list next, /loop resume|start, new goal creation),
|
|
801
|
+
each release ledgered load_hold_released. Heartbeat host-loss
|
|
802
|
+
supervision stays armed under the hold — a held plane is never an
|
|
803
|
+
unprobed idle plane.
|
|
804
|
+
- Closed consent bypasses: different-pid crash successors no longer
|
|
805
|
+
auto-resume held loops or replay journals as automation (same-process
|
|
806
|
+
/reload successors keep continuity); parked completion-audit claims no
|
|
807
|
+
longer auto-retry on a bare cold start (the main-model-recovery one-
|
|
808
|
+
shot retry keeps its pinned consent).
|
|
809
|
+
|
|
810
|
+
## 0.35.22 — a queued item blocked by a live loop is loud and self-heals at loop end (2026-08-22)
|
|
811
|
+
|
|
812
|
+
### suspicious-unstartable-repair-card fix (note.md Next #3)
|
|
813
|
+
Field (screenshots 20260821_114109/114210/134442/134645): /goal start of a
|
|
814
|
+
lowercase-fragment objective paused the goal and queued a repair task; the
|
|
815
|
+
card said "/list next starts the preserved repair/replan task" — but with
|
|
816
|
+
the Chrome-Bridge loop owning the surface, activateNextListItem's
|
|
817
|
+
one-active-thing guard refused activation LEDGER-ONLY: unstartable AND
|
|
818
|
+
invisibly blocked. Two fixes:
|
|
819
|
+
- the refusal now notifies with the queued objective and the way out
|
|
820
|
+
("/loop stop … then /list next"), and the ledger names what stayed queued;
|
|
821
|
+
- when a loop ends by ANY route (/loop stop, /loop finish, plateau/bounds
|
|
822
|
+
stop), resumeQueuedListAfterLoopEnd retries list activation when no goal
|
|
823
|
+
owns the surface — the blocked entry starts instead of staying dead.
|
|
824
|
+
Also: tests/list-invisible-restart.test.ts no longer depends on co-resident
|
|
825
|
+
module state (unique owner session + explicit reset), fixing the cross-file
|
|
826
|
+
ordering failure surfaced by audit round eight.
|
|
827
|
+
|
|
828
|
+
## 0.35.21 — list queue stays visible across lifecycle boundaries (2026-08-22)
|
|
829
|
+
|
|
830
|
+
### list-invisible-until-restart fix (note.md Next #4)
|
|
831
|
+
Field: a stopped/interrupted /list exec left the queue surface blank —
|
|
832
|
+
active item only, no "N waiting · up next" line — until a session
|
|
833
|
+
restart. Root cause: the sidebar renders state.list from MEMORY while the
|
|
834
|
+
durable queue is the UNION of the state ledger and the per-item
|
|
835
|
+
.queue.json sidecars (v0.34.60 disk-first writes); a plugin re-init /
|
|
836
|
+
stale-handle window reset RAM to defaults and only some later path
|
|
837
|
+
re-ran the disk merge. session_start's restore now converges memory to
|
|
838
|
+
that union immediately (hydrateListQueueFromDisk after readState), so
|
|
839
|
+
the next lifecycle boundary heals the surface without a restart; the
|
|
840
|
+
hydration notifies with a truthful count ("restored N queued list
|
|
841
|
+
item(s)"). Regression tests: sidecar-only item is hydrated AND rendered;
|
|
842
|
+
convergence is idempotent (no duplicate for items in both stores).
|
|
843
|
+
|
|
844
|
+
## 0.35.20 — one bounded automatic retry for transient mechanical-check deaths (2026-08-21)
|
|
845
|
+
|
|
846
|
+
### Gate resilience
|
|
847
|
+
Field (sixth audit round): the pre-audit gate died MID-RUN under machine
|
|
848
|
+
load ~30 — output ends inside a passing file, no runner summary, exit 1 —
|
|
849
|
+
while the identical tree passed green twice in isolation. Resource
|
|
850
|
+
contention, not a red suite. Mechanical check commands now get exactly ONE
|
|
851
|
+
bounded automatic retry on failure: a deterministic red command stays red
|
|
852
|
+
on both attempts (final output names the retry and preserves the second
|
|
853
|
+
attempt's diagnostics); a first-attempt transient death followed by a
|
|
854
|
+
passing retry passes with an honest `recoveredRetryNote` in the result.
|
|
855
|
+
Mirrors the v0.35.17 zero-stream auto-retry philosophy at the gate level.
|
|
856
|
+
|
|
857
|
+
## 0.35.19 — load-resilient budgets for the aggressive-recovery test (2026-08-21)
|
|
858
|
+
|
|
859
|
+
### Flake hardening
|
|
860
|
+
At machine load ~50 (16 cores), the aggressive no-verdict recovery test's
|
|
861
|
+
wall-clock wait budgets (2x 25s inside a 60s per-test ceiling) expired
|
|
862
|
+
before two real subprocess-based auditor retry cycles completed — while
|
|
863
|
+
the canonical full-suite run stayed green in the same conditions. Raised:
|
|
864
|
+
per-test 60s→120s, retry waits 25s→45s, state-transition waits 8s→20s.
|
|
865
|
+
Budgets only; semantics untouched (same precedent as v0.35.15's 30s→60s).
|
|
866
|
+
|
|
867
|
+
## 0.35.18 — mechanical checks resolve raw runners to their canonical scripts (2026-08-21)
|
|
868
|
+
|
|
869
|
+
### Spurious fast-fail fix (fourth audit round)
|
|
870
|
+
A verification contract that names a RAW RUNNER in prose ("passes under
|
|
871
|
+
`bun test`") made the deterministic pre-audit execute `bun test` bare,
|
|
872
|
+
ignoring the project's own required configuration encoded in package.json
|
|
873
|
+
scripts (--parallel=1 --max-concurrency=1 --timeout; this suite shares
|
|
874
|
+
module state process-wide by design and serializes deliberately). The bare
|
|
875
|
+
invocation failed 6 tests + 5 nested-test errors while the canonical gate
|
|
876
|
+
was green twice — a spurious fast-fail of finished work. Mechanical check
|
|
877
|
+
commands that are exactly a raw runner invocation (bun test / vitest /
|
|
878
|
+
jest, no extra args) now resolve to the package script that wraps them;
|
|
879
|
+
narrower runs and non-runner programs pass through untouched. Pure resolver
|
|
880
|
+
(`resolveCanonicalRunnerCommand`) lives in goal-loop-backoff.ts with unit
|
|
881
|
+
tests; bunfig cannot express the required flags (verified empirically:
|
|
882
|
+
`[test] timeout` is not honored on bun 1.3.14).
|
|
883
|
+
|
|
884
|
+
## 0.35.17 — zero-stream abort gains ONE bounded automatic retry; tag backfill (2026-08-21)
|
|
885
|
+
|
|
886
|
+
### Post-accept hang self-heal (note.md Next §1)
|
|
887
|
+
Turns dispatched by accepting a Confirm dialog hung with zero provider
|
|
888
|
+
stream activity often enough that users repeatedly returned to parked
|
|
889
|
+
"action needed" sessions (field screenshot 20260821_152311). The watchdog's
|
|
890
|
+
bounded abort was correct; what was missing is self-heal. The FIRST silence
|
|
891
|
+
of a zero-stream streak now arms exactly ONE automatic retry ~90s after the
|
|
892
|
+
park — the parked goal/list item/loop auto-resumes through the durable
|
|
893
|
+
continuation machinery and one fresh dispatch goes out. A SECOND consecutive
|
|
894
|
+
silence refuses further retries (`zombie_auto_retry_refused_streak`) and
|
|
895
|
+
parks permanently for manual resume; real stream activity between aborts
|
|
896
|
+
resets the streak so an independent later hang earns its own single retry.
|
|
897
|
+
`/glla pause` freezes the retry like every other automatic side-effect;
|
|
898
|
+
the timer only clears a pause carrying exactly the watchdog's own reason
|
|
899
|
+
(a newer manual/recovery pause supersedes it); the heartbeat's one-shot
|
|
900
|
+
abort latch is released on retry dispatch so a fully-silent retry can still
|
|
901
|
+
be re-aborted. Pure streak decision lives in goal-loop-backoff.ts
|
|
902
|
+
(`zombieRetryDecision`) with unit tests; behavioral coverage drives the
|
|
903
|
+
full hang→abort/park→auto-resume→re-dispatch arc plus the double-hang and
|
|
904
|
+
pause-during-waystation paths (tests/post-accept-hang-retry.test.ts).
|
|
905
|
+
|
|
906
|
+
### Version tags backfilled
|
|
907
|
+
All 41 released versions missing their `v<version>` git tag (v0.34.20 …
|
|
908
|
+
v0.35.16) were tagged at the historical commit whose package.json carried
|
|
909
|
+
that exact version and pushed to all remotes. Additive-only — no history
|
|
910
|
+
rewrite.
|
|
911
|
+
|
|
912
|
+
### README currency pass
|
|
913
|
+
Documents the v0.35.15 per-phase glyphs/activity meter/silent-stretch
|
|
914
|
+
footer, `/glla pause`, and the v0.35.17 zero-stream auto-retry.
|
|
915
|
+
|
|
916
|
+
## 0.35.16 — mechanical pre-audit gate no longer kills legitimate long checks (2026-08-21)
|
|
917
|
+
|
|
918
|
+
### Deterministic pre-audit timeout fix
|
|
919
|
+
`runMechanicalPreAuditChecks` executed every contract command under a
|
|
920
|
+
hard 60-second `execFileSync` ceiling — but this repo's own contract
|
|
921
|
+
command (`npm run release:check`) legitimately needs ~3 minutes. Every
|
|
922
|
+
deterministic pre-audit therefore fast-failed with a truncated
|
|
923
|
+
head-of-output report showing only startup logs (two field rounds:
|
|
924
|
+
2026-08-21 14:17 and 16:01), burning two auditor cycles on a gate that
|
|
925
|
+
could never pass inside its own bound. The default bound is now 10 minutes
|
|
926
|
+
— still a hang guard, no longer an honest-slow-work guard. Failed output
|
|
927
|
+
keeps the TAIL (where failures live) instead of the head, truncation is
|
|
928
|
+
labeled, and a timeout kill is bannered as such instead of masquerading as
|
|
929
|
+
an exit-code-1 test failure.
|
|
930
|
+
|
|
931
|
+
## 0.35.15 — glla status-surface UX: visual footer, /glla pause, proactive quiet notify (2026-08-21)
|
|
932
|
+
|
|
933
|
+
### Visual status footer
|
|
934
|
+
The auditing footer now leads each auditor phase with a distinct glyph
|
|
935
|
+
(queued ⋯ · running ▶ · quiet ◌ · blocked ⛔ · awaiting-verdict ✓) and a
|
|
936
|
+
compact draining activity meter (▰▱) that empties as worker silence grows
|
|
937
|
+
toward the quiet threshold. A glance answers "is the audit alive?" without
|
|
938
|
+
reading the sentence.
|
|
939
|
+
|
|
940
|
+
### /glla pause | resume — broad supervisor freeze
|
|
941
|
+
`/glla pause` freezes ALL automatic machinery — heartbeat re-arms, stale
|
|
942
|
+
probes, zombie cleanup, main-model recovery probes, automatic completion-
|
|
943
|
+
audit recovery, continuation dispatch, loop ticks, and the proactive quiet
|
|
944
|
+
notification — while leaving the active goal/list item/loop and any
|
|
945
|
+
detached worker untouched. The flag persists via `supervisorPausedAt`, so a
|
|
946
|
+
session restart cannot silently re-arm machinery the user explicitly
|
|
947
|
+
stopped. `/glla resume` clears it first, then resumes whatever else is
|
|
948
|
+
resumable, and never follows with a misleading "Nothing to resume". Manual
|
|
949
|
+
user commands always still work.
|
|
950
|
+
|
|
951
|
+
### Proactive auditor quiet reporting
|
|
952
|
+
Entering the quiet phase (~3 min of zero worker activity) now fires exactly
|
|
953
|
+
ONE warning notify instead of only recoloring the status chip — the field
|
|
954
|
+
complaint was an 8-minute silent stretch the user only discovered after the
|
|
955
|
+
fact. Once activity resumes, the footer shows "silent Xm then resumed" for
|
|
956
|
+
10 minutes so a missed silence stays visible.
|
|
957
|
+
|
|
958
|
+
### Persistence fix (latent bug)
|
|
959
|
+
`persistStateLine` never serialized `lastCompactionAt` despite v0.34.97's
|
|
960
|
+
comment claiming it did — the ⏳ compacting… chip silently lost its reload
|
|
961
|
+
survival. Both epoch fields now ride the state line with explicit nulls so
|
|
962
|
+
ledger merges clear them correctly.
|
|
963
|
+
|
|
964
|
+
## 0.35.14 — full extension audit hardening (2026-08-21)
|
|
965
|
+
|
|
966
|
+
### Verification and lifecycle integrity
|
|
967
|
+
Mechanical contract checks now run through a shell-free literal-argument
|
|
968
|
+
boundary, auditor verdicts require one final terminal marker, and regression
|
|
969
|
+
shield references must appear inside `<evidence>`. Invalid persisted IDs are
|
|
970
|
+
rejected at state hydration and filesystem boundaries. Child extension
|
|
971
|
+
factories no longer claim the host API or start timers before an admitted
|
|
972
|
+
`session_start`; completion approval cannot report success when terminal
|
|
973
|
+
archiving fails, and branch-mode loop resumes refuse the wrong branch.
|
|
974
|
+
|
|
975
|
+
### Release contract
|
|
976
|
+
Published documentation includes the linked planning files, the workflow
|
|
977
|
+
runs the release contract on pushes and pull requests, and release tooling
|
|
978
|
+
uses pinned Node/npm versions.
|
|
979
|
+
|
|
3
980
|
## 0.35.13 — stale-API recovery loop fix (2026-08-20)
|
|
4
981
|
|
|
5
982
|
### Stale-handle recovery correctness
|