instar 1.3.654 → 1.3.655

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instar",
3
- "version": "1.3.654",
3
+ "version": "1.3.655",
4
4
  "description": "Coherence infrastructure for self-evolving AI agents — on the Claude Code or Codex subscription you already have.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-06-24T14:42:23.151Z",
5
- "instarVersion": "1.3.654",
4
+ "generatedAt": "2026-06-24T16:39:12.372Z",
5
+ "instarVersion": "1.3.655",
6
6
  "entryCount": 202,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -0,0 +1,29 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ Two signal-only honesty fixes to the standby/reap user-facing surfaces (spec: `docs/specs/honest-session-state-surfaces.md`).
9
+
10
+ **Fix (b) — Tier1/Tier2 standby honesty (dev-gated dark behind `monitoring.standbyHonestyTiers.enabled`, LIVE on a development agent, dark on the fleet).** `PresenceProxy` already had an honest stuck-state classifier (`classifyStuckSignature` — rate-limited / policy-wedge / context-wedge / context-too-long) but invoked it ONLY at Tier 3 (the 5-minute check); at Tier 1 (~20s) and Tier 2 (~2min) the fallback paths hardcoded "is actively working" / "is still working". So for the first several minutes a genuinely rate-limited or permanently-wedged live session was reported to the user as "actively working" — the exact lie the honest-turn-receipts work set out to kill, fixed at Tier 3 but not the earlier, more-frequently-seen tiers. A new private `PresenceProxy.maybeStuckMessage(snapshot, sessionName, tierLabel)` helper reuses the SAME tail-gated classifier on the SAME sanitized snapshot and returns one of three outcomes: a string (stuck, no recovery owner → send the honest line), a `SUPPRESS` sentinel (stuck, but a recovery sentinel owns the voice → send nothing this fire, mirroring Tier 3's silent return — NOT a fall-through to the "working" copy), or `null` (not stuck → unchanged LLM path). It is inserted into `fireTier1`/`fireTier2` AFTER the existing quota and idle short-circuits and BEFORE the LLM block. Scheduling is NEVER gated — the next tier is scheduled in every branch (Tier 2 after Tier 1, Tier 3 after Tier 2), so the Tier-3 context-too-long auto-recovery still fires. It emits ONLY the verbatim classifier message (no pane-derived text). The flag is OMITTED from `ConfigDefaults` so it resolves via `resolveDevAgentGate`; a `DEV_GATED_FEATURES` entry was added. Flag-OFF (the whole fleet) is byte-identical to today.
11
+
12
+ **Fix (c) — paused-aware "restart is queued" claim (ships unflagged).** `ResumeQueue.hasLiveQueuedEntryFor` fed `ReapNotifier`'s "A restart is queued … I'll bring it back" line, but it gated on `dryRun`/`disabledReason`/`enabled` — NOT on whether the queue was PAUSED (e.g. by an emergency stop). When paused, a queued entry will NOT revive until the queue resumes, yet the notice still promised revival. The fix is a SPLIT predicate, not a paused-blind edit of the shared one: `hasLiveQueuedEntryFor` (OWNERSHIP, deliberately paused-BLIND) is left UNCHANGED because the PromiseBeacon I2 double-spawn coordination guard (`server.ts`) reads it and must keep deferring to the queue while paused — a paused-blind flip would re-open a double-spawn and revive emergency-stopped work. A NEW sibling `ResumeQueue.hasClaimableQueuedEntryFor` (= `hasLiveQueuedEntryFor && !isPaused()`) is added and ONLY the ReapNotifier copy consumer (`server.ts`) is re-pointed at it. The entries remain queued and revive normally on unpause.
13
+
14
+ ## What to Tell Your User
15
+
16
+ (These changes are mostly internal honesty fixes — the bigger one ships only on the development agent for now, so a regular agent's behavior is unchanged.) When one of your sessions goes quiet, I post short "standby" updates while you wait. Previously, in the first couple of minutes, those updates would say I was "actively working" even when my session was actually stuck — rate-limited, or wedged in a way that needs a fresh start. On the development agent (⚗️ experimental, dark on everyone else for now), I now tell you the REAL reason at the 20-second and 2-minute marks instead, the same way I already did at the 5-minute mark. Separately (and live for everyone): if a session's restart is on hold because work was paused (for example by an emergency stop), I no longer falsely promise "a restart is queued — I'll bring it back" — I only say that when a restart will actually happen. Your queued work is never dropped; it still comes back once the pause is lifted.
17
+
18
+ ## Summary of New Capabilities
19
+
20
+ - `PresenceProxy` Tier 1 / Tier 2 standby now surface the honest stuck reason (rate-limited / policy-wedge / context-wedge / context-too-long) instead of "actively working", via the new `maybeStuckMessage` helper reusing the existing tail-gated `classifyStuckSignature`. Dev-gated dark behind `monitoring.standbyHonestyTiers.enabled` (live-on-dev / dark-on-fleet); flag-OFF is byte-identical to today. Signal-only: it changes the standby MESSAGE TEXT (or suppresses it under one-voice ownership), never the tier schedule, recovery, spend, or egress.
21
+ - `ResumeQueue.hasClaimableQueuedEntryFor` (= live entry AND not paused) is a new claimability accessor that feeds the user-facing "restart is queued" copy, so the claim is suppressed while the queue is paused. Ships unflagged (pure correctness).
22
+ - The shared `ResumeQueue.hasLiveQueuedEntryFor` (ownership, paused-blind) is left unchanged so the PromiseBeacon I2 double-spawn coordination guard keeps deferring to the queue while paused — preserved byte-for-byte.
23
+
24
+ ## Evidence
25
+
26
+ Both are honesty defects in EXISTING surfaces, demonstrated by new 3-tier tests (signal-only / dev-gated dark — no production outage to repro). Phase-5 independent diff review concurred (no blockers).
27
+
28
+ - **Fix (b) — the Tier1/Tier2 lie.** Before: a live-but-stuck pane (policy-wedge / context-wedge / context-too-long) at Tier 1 or Tier 2 produced "is actively working" / "is still working". After: with the flag ON it produces the honest classifier reason and NOT the "working" copy, and a stuck pane where a recovery sentinel owns the voice produces NO message at all (one-voice silent-suppress) — while the tier schedule is unchanged in every branch. Proven in `tests/unit/PresenceProxy-standby-honesty.test.ts` (Tier 1 + Tier 2 both-sides incl. the SUPPRESS-still-schedules and the no-leak assertions), the integration test `tests/integration/standby-honesty-reap-notice.test.ts` (real PresenceProxy fire path), and the e2e `tests/e2e/standby-honesty-flag-default.test.ts` (dev-gate both-sides + wiring integrity: resolved-TRUE threads into `classifyStuckSignature`, resolved-FALSE is a strict no-op byte-identical to today). The `devGatedFeatures-wiring.test.ts` both-sides assertion covers the new registry entry; `lint-dev-agent-dark-gate` confirms the flag is OMITTED from `ConfigDefaults`.
29
+ - **Fix (c) — the false "restart is queued" claim + the I2 regression guard.** Before: with a queued entry and the queue paused, the reap notice claimed "A restart is queued". After: `hasClaimableQueuedEntryFor` returns false while paused (copy suppressed) while `hasLiveQueuedEntryFor` stays true (ownership preserved → the PromiseBeacon I2 double-spawn guard keeps deferring). Proven both directions in `tests/unit/ResumeQueue-paused-claimable.test.ts` (incl. the I2-guard ownership-survives-pause assertion and the unpause-restores case) and the integration test (the ReapNotifier copy path suppresses the line while paused and emits it after unpause; the I2-guard path still reports ownership while paused). No entry is dropped, cancelled, or double-spawned.
@@ -0,0 +1,185 @@
1
+ # Side-Effects Review — Honest Session-State Surfaces (Tier1/Tier2 standby honesty + paused-queue notice correctness)
2
+
3
+ **Version / slug:** `honest-session-state-surfaces`
4
+ **Date:** `2026-06-24`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `general-purpose (independent Phase-5 diff review)`
7
+
8
+ ## Summary of the change
9
+
10
+ Two small honesty fixes to the standby/reap user-facing surfaces, both signal-only.
11
+ **Finding (b)** lifts the existing Tier-3 honest stuck-state classifier
12
+ (`classifyStuckSignature` — rate-limited / policy-wedge / context-wedge /
13
+ context-too-long) into PresenceProxy **Tier 1** and **Tier 2** so a live-but-failing
14
+ session is reported with its REAL reason at the 20s / 2-minute marks instead of
15
+ "actively working". It is gated behind a dev-dark flag
16
+ `monitoring.standbyHonestyTiers.enabled` (OMITTED from ConfigDefaults → resolved via
17
+ `resolveDevAgentGate`; live on a dev agent, dark on the fleet). **Finding (c)** fixes a
18
+ false "A restart is queued — I'll bring it back" claim when the ResumeQueue is paused:
19
+ it adds a NEW `ResumeQueue.hasClaimableQueuedEntryFor` (= `hasLiveQueuedEntryFor && !isPaused()`)
20
+ and re-points ONLY the ReapNotifier copy consumer at it, leaving the paused-blind
21
+ `hasLiveQueuedEntryFor` (ownership) for the PromiseBeacon I2 double-spawn guard. Files:
22
+ `src/monitoring/PresenceProxy.ts`, `src/commands/server.ts`, `src/core/types.ts`,
23
+ `src/core/devGatedFeatures.ts`, `src/monitoring/ResumeQueue.ts`, plus 4 test files.
24
+
25
+ ## Decision-point inventory
26
+
27
+ - `PresenceProxy Tier 1 / Tier 2 standby copy` — modify — flag-ON substitutes the honest stuck reason (or suppresses the message under one-voice) for "working" copy; flag-OFF byte-identical.
28
+ - `ReapNotifier "restart is queued" line (via ResumeQueue predicate)` — modify — now reads claimability (false while paused) instead of ownership; no flag, pure correctness.
29
+ - `PromiseBeacon I2 double-spawn coordination guard (server.ts:11980)` — pass-through — still reads the unchanged paused-blind `hasLiveQueuedEntryFor` (ownership). Deliberately UNCHANGED.
30
+
31
+ ---
32
+
33
+ ## 1. Over-block
34
+
35
+ The change has no block/allow surface — it changes message TEXT and suppresses a
36
+ specific false claim. (b) The honest pre-check can only substitute the standby message
37
+ string or suppress it under one-voice ownership; it never blocks a session, a send, or
38
+ a tier. (c) Suppressing the "restart is queued" copy while paused omits one notice LINE,
39
+ never a whole notice and never a queue entry. "No block/allow surface — over-block not applicable."
40
+
41
+ ---
42
+
43
+ ## 2. Under-block
44
+
45
+ Not applicable (no block surface). The honest classifier is inherited as-is (tail-gated,
46
+ same false-positive profile as the established Tier-3 usage — the early tiers do not
47
+ widen its input surface). The claimability predicate is a strict conjunction over the
48
+ already-shipped ownership predicate, so it cannot pass a case the ownership predicate
49
+ already rejects. "No block/allow surface — under-block not applicable."
50
+
51
+ ---
52
+
53
+ ## 3. Level-of-abstraction fit
54
+
55
+ Right layer in both. (b) reuses the existing classifier (a detector) and feeds the
56
+ existing standby-message emission path — it adds NO new detector and NO new parse
57
+ surface; recovery stays with the Tier-3 block and the sentinels (the early tiers only
58
+ REPORT or stay silent). (c) adds a sibling read accessor on the store that already owns
59
+ the queue state (`ResumeQueue`) rather than re-deriving pause state in the caller — the
60
+ authority over "is this claimable?" lives with the queue.
61
+
62
+ ---
63
+
64
+ ## 4. Signal vs authority compliance
65
+
66
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
67
+
68
+ - [x] No — this change produces a signal (a message string / a boolean read) consumed by existing smart gates and emission paths; it holds NO new block authority.
69
+
70
+ (b) only alters which message string is sent, or sends none when a recovery sentinel
71
+ owns the voice — it NEVER gates scheduling (`scheduleTier` runs in every branch),
72
+ initiates recovery, spends, or egresses. Every uncertainty (no snapshot, classifier
73
+ returns null/throws, recovery owner present) fails toward today's behavior. (c) is a
74
+ read-accessor correctness fix; the I2 guard's blocking decision still reads the
75
+ unchanged ownership predicate, so the only coordination authority in play is untouched.
76
+
77
+ ---
78
+
79
+ ## 5. Interactions
80
+
81
+ - **Shadowing:** (b) The honest pre-check is placed AFTER the existing quota
82
+ short-circuit (`detectQuotaExhaustion`) and AFTER the idle/finished checks in both
83
+ fireTier1 and fireTier2, so it never shadows the quota or "agent finished" paths
84
+ (quota panes — the rate-limit form — are still handled by the pre-existing quota
85
+ short-circuit, which the lift sits below; the lift's incremental value is the wedge
86
+ set quota does not catch). It is placed BEFORE the LLM block, so a stuck session never
87
+ reaches the LLM "working" summary.
88
+ - **Double-fire:** (c) The whole point — the I2 guard keeps deferring to the queue while
89
+ paused (reads ownership, still true), so a PromiseBeacon escalation cannot double-spawn
90
+ a revive for a paused-frozen topic. A naïve single-predicate paused-aware edit would
91
+ have re-opened exactly that double-spawn; the split predicate prevents it.
92
+ - **Races:** No new shared state. (b) reuses the existing per-topic PresenceState and the
93
+ same persist/schedule tail. (c) reads `ResumeQueue` state through its existing accessors.
94
+ - **Feedback loops:** None — message text and a boolean read have no feedback into the systems they describe.
95
+
96
+ ---
97
+
98
+ ## 6. External surfaces
99
+
100
+ - Other agents: none.
101
+ - Install base: (b) ships dark on the fleet (dev-gate) → no fleet behavior change until a
102
+ deliberate flip; (c) ships live but only removes a false claim line.
103
+ - External systems: the honest standby message and the reap notice both flow through the
104
+ EXISTING `sendMessage` / Telegram formatter+escape path — no new outbound surface, no raw send.
105
+ - Persistent state: none changed. ResumeQueue entries are untouched (paused entries
106
+ remain queued and revive normally on unpause).
107
+ - **Operator surface (Mobile-Complete Operator Actions):** No operator-facing actions —
108
+ both surfaces are passive notifications the agent emits; there is nothing for the
109
+ operator to do/tap. Not applicable.
110
+
111
+ ---
112
+
113
+ ## 6b. Operator-surface quality (Operator-Surface Quality standard)
114
+
115
+ No operator surface — not applicable. This change touches no dashboard renderer/markup
116
+ file, no approval page, and no grant/revoke/secret-drop form. It alters two passive
117
+ agent-emitted notification strings (a 🔭 standby line and a 🪦 reap-notice line); there
118
+ is no operator form, button, or page in the diff.
119
+
120
+ ---
121
+
122
+ ## 7. Multi-machine posture (Cross-Machine Coherence)
123
+
124
+ **machine-local BY DESIGN** — both surfaces are per-machine-local honesty surfaces with a
125
+ concrete reason each:
126
+
127
+ - **(b)** `PresenceProxy` already runs under the WS3 one-voice speaker election (only the
128
+ topic's OWNER machine speaks 🔭). The honest classifier reads the LIVE LOCAL tmux pane of
129
+ a session running on THIS machine — there is no remote session to classify, so it is
130
+ correctly machine-local: the machine serving the topic reports honestly about the session
131
+ it is actually running. User-facing notice → one-voice gating is already inherited from
132
+ the existing PresenceProxy speaker election (the pre-check sits inside that gate; the
133
+ SUPPRESS branch also honors the recovery-owner one-voice rule).
134
+ - **(c)** `ResumeQueue` is a durable PER-MACHINE queue (it holds a host-local lock
135
+ precisely to forbid two machines sharing its state). Its `paused` flag and entries are
136
+ machine-local, and the reap notice is emitted by the machine that reaped the session, so
137
+ the paused-guard is correctly local — it suppresses the claim on the only machine that
138
+ could (or could not) honor it. No durable state strands on transfer (entries are
139
+ untouched); no URLs are generated.
140
+
141
+ No `multiMachine.*` config, no replicated-store work, no pool routes touched.
142
+
143
+ ---
144
+
145
+ ## 8. Rollback cost
146
+
147
+ - **Hot-fix release:** pure code change — revert and ship a patch. (b) is additionally
148
+ flag-gated, so disabling `monitoring.standbyHonestyTiers.enabled` (or running on the
149
+ fleet, where it is already dark) reverts Tier 1/2 to byte-identical-to-today wording
150
+ without a code change.
151
+ - **Data migration:** none — no persistent state added or changed.
152
+ - **Agent state repair:** none — no agent needs notification or reset.
153
+ - **User visibility:** none during rollback — reverting (b) restores "actively working";
154
+ reverting (c) restores the (incorrect) "restart is queued" claim, a cosmetic regression
155
+ only, with no behavioral loss.
156
+
157
+ ---
158
+
159
+ ## Conclusion
160
+
161
+ This review produced no design changes — the spec's convergence had already resolved the
162
+ two load-bearing constraints this review re-verifies: (b) scheduling is never gated (the
163
+ honest pre-check substitutes the message string or suppresses it, then falls through to
164
+ the existing scheduling tail in every branch, including SUPPRESS), and (c) the shared
165
+ `hasLiveQueuedEntryFor` stays paused-blind for the I2 double-spawn guard while a NEW
166
+ claimability predicate feeds only the user-facing copy. The 3-tier test suite pins both
167
+ sides of each boundary, including the I2-guard regression assertion (ownership survives a
168
+ pause) and the no-leak contract at the new Tier1/2 callsite. Clear to ship.
169
+
170
+ ---
171
+
172
+ ## Second-pass review (if required)
173
+
174
+ **Reviewer:** general-purpose (independent Phase-5 diff review)
175
+ **Independent read of the artifact: concur**
176
+
177
+ The independent reviewer read the real staged diff and the surrounding source (the full
178
+ `fireTier1`/`fireTier2` methods, `maybeStuckMessage`, `ResumeQueue.hasLiveQueuedEntryFor`
179
+ / `hasClaimableQueuedEntryFor` / `isPaused`, and server.ts lines 7219/7244/7501/11980),
180
+ checking specifically: (1) the next tier is scheduled in EVERY branch of the new
181
+ pre-check (string / SUPPRESS / null); (2) the SUPPRESS branch sends no "working"
182
+ fallback; (3) the pre-check sits after the quota/idle short-circuits; (4)
183
+ `hasLiveQueuedEntryFor` is left paused-blind for the I2 guard; (5) only the ReapNotifier
184
+ copy reads the claimable predicate; (6) the no-leak contract holds; (7) no control-flow
185
+ bug from the fireTier2 brace restructuring. Findings are recorded below.