instar 1.3.499 → 1.3.501

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.
Files changed (98) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +407 -6
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  5. package/dist/config/ConfigDefaults.js +10 -0
  6. package/dist/config/ConfigDefaults.js.map +1 -1
  7. package/dist/core/PostUpdateMigrator.d.ts +1 -0
  8. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  9. package/dist/core/PostUpdateMigrator.js +69 -0
  10. package/dist/core/PostUpdateMigrator.js.map +1 -1
  11. package/dist/core/ReapGuard.d.ts +24 -0
  12. package/dist/core/ReapGuard.d.ts.map +1 -1
  13. package/dist/core/ReapGuard.js +62 -0
  14. package/dist/core/ReapGuard.js.map +1 -1
  15. package/dist/core/SessionManager.d.ts +32 -0
  16. package/dist/core/SessionManager.d.ts.map +1 -1
  17. package/dist/core/SessionManager.js +74 -2
  18. package/dist/core/SessionManager.js.map +1 -1
  19. package/dist/core/WorkEvidence.d.ts +45 -0
  20. package/dist/core/WorkEvidence.d.ts.map +1 -0
  21. package/dist/core/WorkEvidence.js +88 -0
  22. package/dist/core/WorkEvidence.js.map +1 -0
  23. package/dist/core/componentCategories.d.ts.map +1 -1
  24. package/dist/core/componentCategories.js +3 -0
  25. package/dist/core/componentCategories.js.map +1 -1
  26. package/dist/core/devGatedFeatures.d.ts.map +1 -1
  27. package/dist/core/devGatedFeatures.js +5 -0
  28. package/dist/core/devGatedFeatures.js.map +1 -1
  29. package/dist/core/types.d.ts +50 -0
  30. package/dist/core/types.d.ts.map +1 -1
  31. package/dist/core/types.js.map +1 -1
  32. package/dist/messaging/NotificationBatcher.d.ts +12 -0
  33. package/dist/messaging/NotificationBatcher.d.ts.map +1 -1
  34. package/dist/messaging/NotificationBatcher.js +36 -0
  35. package/dist/messaging/NotificationBatcher.js.map +1 -1
  36. package/dist/messaging/pending-relay-store.d.ts +67 -8
  37. package/dist/messaging/pending-relay-store.d.ts.map +1 -1
  38. package/dist/messaging/pending-relay-store.js +151 -14
  39. package/dist/messaging/pending-relay-store.js.map +1 -1
  40. package/dist/messaging/reap-notice-delivery-id.d.ts +37 -0
  41. package/dist/messaging/reap-notice-delivery-id.d.ts.map +1 -0
  42. package/dist/messaging/reap-notice-delivery-id.js +52 -0
  43. package/dist/messaging/reap-notice-delivery-id.js.map +1 -0
  44. package/dist/monitoring/QuotaManager.d.ts +6 -0
  45. package/dist/monitoring/QuotaManager.d.ts.map +1 -1
  46. package/dist/monitoring/QuotaManager.js +11 -0
  47. package/dist/monitoring/QuotaManager.js.map +1 -1
  48. package/dist/monitoring/ReapLog.d.ts +39 -4
  49. package/dist/monitoring/ReapLog.d.ts.map +1 -1
  50. package/dist/monitoring/ReapLog.js +54 -4
  51. package/dist/monitoring/ReapLog.js.map +1 -1
  52. package/dist/monitoring/ReapNoticeDrain.d.ts +113 -0
  53. package/dist/monitoring/ReapNoticeDrain.d.ts.map +1 -0
  54. package/dist/monitoring/ReapNoticeDrain.js +231 -0
  55. package/dist/monitoring/ReapNoticeDrain.js.map +1 -0
  56. package/dist/monitoring/ReapNotifier.d.ts +89 -18
  57. package/dist/monitoring/ReapNotifier.d.ts.map +1 -1
  58. package/dist/monitoring/ReapNotifier.js +329 -22
  59. package/dist/monitoring/ReapNotifier.js.map +1 -1
  60. package/dist/monitoring/ResumeQueue.d.ts +223 -0
  61. package/dist/monitoring/ResumeQueue.d.ts.map +1 -0
  62. package/dist/monitoring/ResumeQueue.js +600 -0
  63. package/dist/monitoring/ResumeQueue.js.map +1 -0
  64. package/dist/monitoring/ResumeQueueDrainer.d.ts +151 -0
  65. package/dist/monitoring/ResumeQueueDrainer.d.ts.map +1 -0
  66. package/dist/monitoring/ResumeQueueDrainer.js +420 -0
  67. package/dist/monitoring/ResumeQueueDrainer.js.map +1 -0
  68. package/dist/monitoring/SessionMigrator.d.ts +10 -0
  69. package/dist/monitoring/SessionMigrator.d.ts.map +1 -1
  70. package/dist/monitoring/SessionMigrator.js +43 -1
  71. package/dist/monitoring/SessionMigrator.js.map +1 -1
  72. package/dist/monitoring/SessionReaper.d.ts +1 -0
  73. package/dist/monitoring/SessionReaper.d.ts.map +1 -1
  74. package/dist/monitoring/SessionReaper.js +5 -0
  75. package/dist/monitoring/SessionReaper.js.map +1 -1
  76. package/dist/monitoring/delivery-failure-sentinel.d.ts.map +1 -1
  77. package/dist/monitoring/delivery-failure-sentinel.js +7 -3
  78. package/dist/monitoring/delivery-failure-sentinel.js.map +1 -1
  79. package/dist/scaffold/templates.d.ts.map +1 -1
  80. package/dist/scaffold/templates.js +4 -3
  81. package/dist/scaffold/templates.js.map +1 -1
  82. package/dist/server/AgentServer.d.ts +5 -0
  83. package/dist/server/AgentServer.d.ts.map +1 -1
  84. package/dist/server/AgentServer.js +3 -0
  85. package/dist/server/AgentServer.js.map +1 -1
  86. package/dist/server/routes.d.ts +8 -0
  87. package/dist/server/routes.d.ts.map +1 -1
  88. package/dist/server/routes.js +94 -0
  89. package/dist/server/routes.js.map +1 -1
  90. package/package.json +1 -1
  91. package/skills/spec-converge/SKILL.md +23 -0
  92. package/src/data/builtin-manifest.json +65 -65
  93. package/src/data/state-coherence-registry.json +14 -1
  94. package/src/scaffold/templates.ts +4 -3
  95. package/upgrades/1.3.500.md +43 -0
  96. package/upgrades/1.3.501.md +51 -0
  97. package/upgrades/side-effects/conformance-gate-autoinvoke.md +58 -0
  98. package/upgrades/side-effects/reap-notify-resume-queue.md +89 -0
@@ -1,32 +1,77 @@
1
1
  /**
2
2
  * ReapNotifier — the single coalescing listener for `sessionReaped`
3
- * (UNIFIED-SESSION-LIFECYCLE §P3).
3
+ * (UNIFIED-SESSION-LIFECYCLE §P3; v2 per reap-notify spec R1.1–R1.5).
4
4
  *
5
5
  * `SessionManager.terminateSession` emits `sessionReaped` exactly once per kill
6
- * at the one chokepoint. This listener turns a TERMINAL reap of a user-facing
7
- * session into a "your session was shut down" notice so a session never silently
8
- * vanishes (the 2026-05-27 incident). It stays SILENT for:
6
+ * at the one chokepoint. This listener turns TERMINAL reaps of user-facing
7
+ * sessions into "your session was shut down" notices so a session never
8
+ * silently vanishes (the 2026-05-27 incident). It stays SILENT for:
9
9
  * - `recovery-bounce` reaps (a kill-to-respawn is a bounce, not a disappearance),
10
10
  * - `origin:'operator'` reaps (the user clicked kill — telling them is noise).
11
11
  *
12
- * Coalescing (SE-7): terminal reaps within a short rolling window collapse onto a
13
- * single shared timer. On flush:
14
- * - exactly ONE reap in the window a per-session notice routed to its bound
15
- * topic (or the lifeline topic if unbound),
16
- * - MORE than one ONE consolidated lifeline message stating the TOTAL count,
17
- * so a mass-reap burst that overflows the bounded buffer is never
18
- * under-reported (the reap-log P4 has the complete record regardless).
12
+ * v2 (perTopic: true, the shipped default):
13
+ * - Per-topic coalescing (R1.1): every topic that lost a session gets ONE
14
+ * notice in THAT topic; the lifeline gets unbound sessions plus when >1
15
+ * topic is affected a one-line cross-topic index. Never creates topics.
16
+ * - Affected-set tracking is SEPARATE from the bounded detail buffer, so in
17
+ * a storm larger than the buffer every affected topic still gets at least
18
+ * a correct count (count-only notice when its detail was dropped).
19
+ * - Durable delivery (R1.3): notices become PendingRelayStore rows keyed
20
+ * `reap-notify:<noticeId>` with the release hold riding `next_attempt_at`;
21
+ * the always-on ReapNoticeDrain delivers them. Outcome records land in
22
+ * the reap-log as append-only pairs. Enqueue failure degrades LOUDLY to
23
+ * one direct send attempt, recorded `enqueue-failed`.
24
+ * - Release tiers (decision 1 + R1.5): a mid-work reap with a QUEUED resume
25
+ * releases IMMEDIATE outside quiet hours (quiet-hours end inside them —
26
+ * never wakes the user; a queued resume means the system is already
27
+ * handling it); everything else releases on the SUMMARY window. At most
28
+ * `maxImmediatePerFlush` immediate releases per flush.
29
+ * - Plain English (R1.2): reason slugs map to human sentences (unknown slug
30
+ * ⇒ generic sentence with the slug parenthesized); no curl/API pointers
31
+ * in any user-facing body.
32
+ *
33
+ * Legacy (perTopic: false — the rollback lever): byte-compatible with the
34
+ * pre-v2 behavior (single buffer; burst ⇒ ONE consolidated lifeline message).
19
35
  *
20
36
  * Sanitization: session names follow user-controlled topic renames, so the
21
- * dynamic fields (name, reason) are wrapped as inline-code spans — the downstream
22
- * Telegram formatter renders code spans as literal, HTML-escaped text, never
23
- * markup. The notifier never emits raw markup around user-controlled values.
37
+ * dynamic fields (name, reason) are wrapped as inline-code spans — the
38
+ * downstream Telegram formatter renders code spans as literal, HTML-escaped
39
+ * text, never markup. The notifier never emits raw markup around
40
+ * user-controlled values.
24
41
  */
42
+ import { buildReapNotifyDeliveryId } from '../messaging/reap-notice-delivery-id.js';
25
43
  export const DEFAULT_REAP_NOTIFIER_OPTIONS = {
26
44
  enabled: true,
27
45
  coalesceWindowMs: 60_000,
28
46
  maxBuffer: 100,
47
+ perTopic: true,
48
+ maxImmediatePerFlush: 5,
49
+ drainEnabled: true,
50
+ };
51
+ /** Hard cap on tracked affected topics per window (R1.1 storm bound). */
52
+ const AFFECTED_SET_CAP = 500;
53
+ /** Plain-English reason map (R1.2). Unknown slugs get the generic sentence. */
54
+ const REASON_MAP = {
55
+ 'quota-shed': 'usage limits were nearly exhausted, so running sessions were paused to switch accounts',
56
+ 'reaped-idle': 'it had been idle for a long time and the machine needed the resources',
57
+ 'age-limit': 'it reached its maximum allowed runtime',
58
+ 'idle-zombie': 'it stopped responding and looked abandoned',
59
+ 'orphan-reap': 'it was left over from an earlier run that already ended',
60
+ 'watchdog-stuck': 'it was stuck and not responding',
61
+ 'sentinel-complete': 'its work was detected as complete',
62
+ 'rerouted-lifetime': 'its background task reached its time limit',
63
+ 'boot-purge': 'it was already dead when the server restarted',
29
64
  };
65
+ export function plainEnglishReason(slug) {
66
+ const mapped = REASON_MAP[slug];
67
+ if (mapped)
68
+ return mapped;
69
+ // Free-text reasons (e.g. "topic moved to <machine> — …") read acceptably
70
+ // as-is; slug-like unknowns get the generic sentence with the slug shown.
71
+ if (slug.includes(' '))
72
+ return slug;
73
+ return `it was shut down automatically (reason: ${slug})`;
74
+ }
30
75
  /** Wrap a user-controlled value as a literal inline-code span (never markup). */
31
76
  function literal(value) {
32
77
  // Neutralize backticks so the code span can't be broken out of.
@@ -39,6 +84,11 @@ export class ReapNotifier {
39
84
  timer = null;
40
85
  buffer = [];
41
86
  windowCount = 0;
87
+ /** v2 affected-set (R1.1) — tracked separately from the detail buffer. */
88
+ affected = new Map();
89
+ affectedOverflow = 0;
90
+ unbound = { count: 0, midWorkCount: 0, resumeQueuedCount: 0, detail: [] };
91
+ noticeSeq = 0;
42
92
  constructor(deps, opts) {
43
93
  this.deps = deps;
44
94
  this.opts = { ...DEFAULT_REAP_NOTIFIER_OPTIONS, ...(opts ?? {}) };
@@ -48,22 +98,86 @@ export class ReapNotifier {
48
98
  onReaped(event) {
49
99
  if (!this.opts.enabled)
50
100
  return;
51
- // Silent dispositions/origins: a bounce is not a disappearance, and the user
52
- // already knows about their own operator kill.
101
+ // Silent dispositions/origins (R1.4): a bounce is not a disappearance, and
102
+ // the user already knows about their own operator kill.
53
103
  if ((event.disposition ?? 'terminal') !== 'terminal')
54
104
  return;
55
105
  if (event.origin === 'operator')
56
106
  return;
57
107
  this.windowCount++;
58
108
  this.buffer.push(event);
59
- if (this.buffer.length > this.opts.maxBuffer)
60
- this.buffer.shift(); // drop-oldest detail
109
+ const dropped = this.buffer.length > this.opts.maxBuffer ? this.buffer.shift() : undefined;
110
+ if (this.opts.perTopic) {
111
+ this.trackAffected(event);
112
+ // The dropped event's detail leaves the buffer but its topic's counts
113
+ // remain in the affected set (already incremented when it arrived).
114
+ if (dropped)
115
+ this.dropDetail(dropped);
116
+ }
61
117
  if (!this.timer) {
62
118
  this.timer = setTimeout(() => { void this.flush(); }, this.opts.coalesceWindowMs);
63
119
  if (typeof this.timer.unref === 'function')
64
120
  this.timer.unref();
65
121
  }
66
122
  }
123
+ trackAffected(event) {
124
+ const topicId = this.safeResolveTopic(event.session.tmuxSession);
125
+ const resumeQueued = this.safeResumeQueued(event.session.tmuxSession);
126
+ const bump = (agg) => {
127
+ agg.count++;
128
+ if (event.midWork)
129
+ agg.midWorkCount++;
130
+ if (resumeQueued)
131
+ agg.resumeQueuedCount++;
132
+ agg.detail.push(event);
133
+ };
134
+ if (topicId == null) {
135
+ bump(this.unbound);
136
+ return;
137
+ }
138
+ const existing = this.affected.get(topicId);
139
+ if (existing) {
140
+ bump(existing);
141
+ return;
142
+ }
143
+ if (this.affected.size >= AFFECTED_SET_CAP) {
144
+ this.affectedOverflow++;
145
+ return;
146
+ }
147
+ const agg = { count: 0, midWorkCount: 0, resumeQueuedCount: 0, detail: [] };
148
+ bump(agg);
149
+ this.affected.set(topicId, agg);
150
+ }
151
+ /** Remove a buffer-evicted event from its topic's detail list (count stays). */
152
+ dropDetail(event) {
153
+ const topicId = this.safeResolveTopic(event.session.tmuxSession);
154
+ const agg = topicId == null ? this.unbound : this.affected.get(topicId);
155
+ if (!agg)
156
+ return;
157
+ const idx = agg.detail.indexOf(event);
158
+ if (idx >= 0)
159
+ agg.detail.splice(idx, 1);
160
+ }
161
+ safeResolveTopic(tmuxSession) {
162
+ try {
163
+ return this.deps.resolveTopic(tmuxSession);
164
+ }
165
+ catch {
166
+ // @silent-fallback-ok — null = "unbound": the session is routed to the
167
+ // lifeline index line instead; a notice is never dropped on this path.
168
+ return null;
169
+ }
170
+ }
171
+ safeResumeQueued(tmuxSession) {
172
+ try {
173
+ return this.deps.resumeQueuedFor?.(tmuxSession) ?? false;
174
+ }
175
+ catch {
176
+ // @silent-fallback-ok — cosmetic: only omits the "a restart is queued"
177
+ // line from the notice text; queueing itself is not affected.
178
+ return false;
179
+ }
180
+ }
67
181
  /**
68
182
  * Emit the coalesced notice(s) for the closed window and reset. Public so the
69
183
  * lifecycle (and tests) can drive it deterministically.
@@ -73,6 +187,62 @@ export class ReapNotifier {
73
187
  clearTimeout(this.timer);
74
188
  this.timer = null;
75
189
  }
190
+ if (!this.opts.perTopic) {
191
+ await this.flushLegacy();
192
+ return;
193
+ }
194
+ const affected = this.affected;
195
+ const unbound = this.unbound;
196
+ const overflow = this.affectedOverflow;
197
+ this.affected = new Map();
198
+ this.unbound = { count: 0, midWorkCount: 0, resumeQueuedCount: 0, detail: [] };
199
+ this.affectedOverflow = 0;
200
+ this.windowCount = 0;
201
+ this.buffer = [];
202
+ if (affected.size === 0 && unbound.count === 0)
203
+ return;
204
+ // Release-tier selection (decision 1 + R1.5): topics with a mid-work reap
205
+ // AND a queued resume go IMMEDIATE, capped at maxImmediatePerFlush —
206
+ // most-severe first (resume-queued count, then mid-work count).
207
+ const entries = [...affected.entries()];
208
+ const immediateEligible = entries
209
+ .filter(([, agg]) => agg.midWorkCount > 0 && agg.resumeQueuedCount > 0)
210
+ .sort(([, a], [, b]) => b.resumeQueuedCount - a.resumeQueuedCount || b.midWorkCount - a.midWorkCount)
211
+ .slice(0, this.opts.maxImmediatePerFlush)
212
+ .map(([topicId]) => topicId);
213
+ const immediateSet = new Set(immediateEligible);
214
+ for (const [topicId, agg] of entries) {
215
+ const body = this.formatTopicNotice(agg);
216
+ await this.deliver(topicId, body, immediateSet.has(topicId) ? 'IMMEDIATE' : 'SUMMARY');
217
+ }
218
+ // Lifeline: unbound sessions + (when >1 topic affected) a cross-topic index.
219
+ const lifeline = this.deps.lifelineTopic();
220
+ const lifelineParts = [];
221
+ if (unbound.count > 0) {
222
+ lifelineParts.push(this.formatUnboundNotice(unbound));
223
+ }
224
+ if (affected.size > 1) {
225
+ lifelineParts.push(this.formatCrossTopicIndex(affected, overflow));
226
+ }
227
+ else if (overflow > 0) {
228
+ lifelineParts.push(`(${overflow} additional affected topic${overflow === 1 ? '' : 's'} exceeded the tracking cap — every reap is still in the reap-log.)`);
229
+ }
230
+ if (lifelineParts.length > 0) {
231
+ if (lifeline == null) {
232
+ this.deps.recordNotify?.({
233
+ noticeId: this.nextNoticeId('lifeline'),
234
+ topicId: null,
235
+ outcome: 'no-topic',
236
+ detail: 'lifeline topic not configured',
237
+ });
238
+ }
239
+ else {
240
+ await this.deliver(lifeline, lifelineParts.join('\n\n'), 'SUMMARY');
241
+ }
242
+ }
243
+ }
244
+ /** Legacy (pre-v2) flush — byte-compatible single-buffer behavior. */
245
+ async flushLegacy() {
76
246
  const count = this.windowCount;
77
247
  const detail = this.buffer;
78
248
  this.windowCount = 0;
@@ -84,20 +254,157 @@ export class ReapNotifier {
84
254
  const topic = this.deps.resolveTopic(ev.session.tmuxSession) ?? this.deps.lifelineTopic();
85
255
  if (topic == null)
86
256
  return; // unreachable channel — reap-log (P4) still has it
87
- await this.deps.send(topic, this.formatSingle(ev));
257
+ await this.deps.send(topic, this.formatSingleLegacy(ev));
88
258
  return;
89
259
  }
90
260
  // Burst → ONE consolidated lifeline message stating the exact total count.
91
261
  const topic = this.deps.lifelineTopic();
92
262
  if (topic == null)
93
263
  return;
94
- await this.deps.send(topic, this.formatBurst(count, detail));
264
+ await this.deps.send(topic, this.formatBurstLegacy(count, detail));
265
+ }
266
+ // ── v2 delivery (R1.3) ───────────────────────────────────────────────
267
+ nextNoticeId(scope) {
268
+ // Charset-clamped for the delivery-id helper: [A-Za-z0-9._-]
269
+ return `${this.now().toString(36)}-${(this.noticeSeq++).toString(36)}-${scope}`;
270
+ }
271
+ releaseAt(tier) {
272
+ const now = this.now();
273
+ let quietEnd = null;
274
+ try {
275
+ quietEnd = this.deps.quietHoursEndAt?.(now) ?? null;
276
+ }
277
+ catch {
278
+ // @silent-fallback-ok — unreadable quiet-hours ⇒ no quiet hold: the
279
+ // notice releases SOONER, never later and never lost.
280
+ quietEnd = null;
281
+ }
282
+ if (tier === 'IMMEDIATE') {
283
+ // Never wakes the user: inside quiet hours an IMMEDIATE notice holds to
284
+ // the window's end (a queued resume means the system is already on it).
285
+ return quietEnd ?? now;
286
+ }
287
+ let summaryAt = now;
288
+ try {
289
+ summaryAt = this.deps.summaryReleaseAt?.(now) ?? now;
290
+ }
291
+ catch {
292
+ summaryAt = now;
293
+ }
294
+ return Math.max(summaryAt, quietEnd ?? 0);
295
+ }
296
+ async deliver(topicId, body, tier) {
297
+ const noticeId = this.nextNoticeId(`t${topicId}`);
298
+ if (!this.opts.drainEnabled || !this.deps.enqueueNotice) {
299
+ // Legacy delivery lever (rollback): direct send, durability claim lapses.
300
+ try {
301
+ await this.deps.send(topicId, body);
302
+ }
303
+ catch {
304
+ // legacy path is fire-and-forget by definition
305
+ }
306
+ return;
307
+ }
308
+ const releaseAtIso = new Date(this.releaseAt(tier)).toISOString();
309
+ let enqueued = false;
310
+ let enqueueError = '';
311
+ try {
312
+ enqueued = this.deps.enqueueNotice({
313
+ delivery_id: buildReapNotifyDeliveryId(noticeId),
314
+ topic_id: topicId,
315
+ text: body,
316
+ next_attempt_at: releaseAtIso,
317
+ });
318
+ }
319
+ catch (err) {
320
+ // @silent-fallback-ok — not silent: the captured error drives the
321
+ // enqueue-failed fallback below (direct send + recordNotify outcome +
322
+ // DegradationReporter via reportDegradation).
323
+ enqueued = false;
324
+ enqueueError = err instanceof Error ? err.message : String(err);
325
+ }
326
+ if (enqueued) {
327
+ this.deps.recordNotify?.({ noticeId, topicId, outcome: 'enqueued', detail: `release ${releaseAtIso} (${tier})` });
328
+ return;
329
+ }
330
+ // Enqueue failure (store probe-failed/disabled/threw): degrade LOUDLY to
331
+ // ONE direct immediate send attempt, recorded with the send result (R1.3).
332
+ let sendResult = 'sent-direct';
333
+ try {
334
+ await this.deps.send(topicId, body);
335
+ }
336
+ catch (err) {
337
+ sendResult = `direct-send-failed: ${err instanceof Error ? err.message : String(err)}`;
338
+ }
339
+ this.deps.recordNotify?.({
340
+ noticeId,
341
+ topicId,
342
+ outcome: 'enqueue-failed',
343
+ detail: `${enqueueError ? `enqueue: ${enqueueError}; ` : 'enqueue returned false; '}${sendResult}`,
344
+ });
345
+ try {
346
+ this.deps.reportDegradation?.(`reap-notice enqueue failed for topic ${topicId}${enqueueError ? ` (${enqueueError})` : ''}`, `The durable-delivery guarantee degraded to one direct attempt (${sendResult}).`);
347
+ }
348
+ catch {
349
+ // degradation reporting is best-effort
350
+ }
351
+ }
352
+ // ── v2 formatting (R1.2 — plain English, no API pointers) ───────────
353
+ formatTopicNotice(agg) {
354
+ const lines = [];
355
+ if (agg.count === 1 && agg.detail.length === 1) {
356
+ const ev = agg.detail[0];
357
+ lines.push(`🪦 Your session ${literal(ev.session.name)} was shut down — ${plainEnglishReason(ev.reason)}.`);
358
+ if (ev.midWork) {
359
+ lines.push(`It was in the middle of work when it was stopped.`);
360
+ }
361
+ if (this.safeResumeQueued(ev.session.tmuxSession)) {
362
+ lines.push(`A restart is queued: once the machine has recovered, I'll bring it back to pick the work up.`);
363
+ }
364
+ return lines.join('\n');
365
+ }
366
+ // Multiple reaps on one topic (or detail dropped in a storm): counts first.
367
+ const header = agg.detail.length > 0
368
+ ? `🪦 ${agg.count} of this topic's sessions were shut down:`
369
+ : `🪦 ${agg.count} of this topic's sessions were shut down (details were trimmed in a busy window — every shutdown is still recorded).`;
370
+ lines.push(header);
371
+ for (const ev of agg.detail.slice(-5)) {
372
+ lines.push(`• ${literal(ev.session.name)} — ${plainEnglishReason(ev.reason)}${ev.midWork ? ' (mid-work)' : ''}`);
373
+ }
374
+ if (agg.detail.length > 5) {
375
+ lines.push(`(showing the latest 5 of ${agg.detail.length})`);
376
+ }
377
+ if (agg.midWorkCount > 0) {
378
+ lines.push(`${agg.midWorkCount} ${agg.midWorkCount === 1 ? 'was' : 'were'} mid-work.`);
379
+ }
380
+ if (agg.resumeQueuedCount > 0) {
381
+ lines.push(`${agg.resumeQueuedCount} restart${agg.resumeQueuedCount === 1 ? ' is' : 's are'} queued for when the machine recovers.`);
382
+ }
383
+ return lines.join('\n');
384
+ }
385
+ formatUnboundNotice(unbound) {
386
+ const lines = [`🪦 ${unbound.count} background session${unbound.count === 1 ? ' was' : 's were'} shut down:`];
387
+ for (const ev of unbound.detail.slice(-5)) {
388
+ lines.push(`• ${literal(ev.session.name)} — ${plainEnglishReason(ev.reason)}${ev.midWork ? ' (mid-work)' : ''}`);
389
+ }
390
+ if (unbound.count > unbound.detail.length) {
391
+ lines.push(`(showing ${Math.min(5, unbound.detail.length)} of ${unbound.count})`);
392
+ }
393
+ return lines.join('\n');
394
+ }
395
+ formatCrossTopicIndex(affected, overflow) {
396
+ const total = [...affected.values()].reduce((n, a) => n + a.count, 0);
397
+ const parts = [...affected.entries()].slice(0, 20).map(([topicId, agg]) => `topic ${topicId} (${agg.count})`);
398
+ const more = affected.size > 20 ? `, +${affected.size - 20} more topics` : '';
399
+ const overflowNote = overflow > 0 ? ` (+${overflow} past the tracking cap)` : '';
400
+ return `Index: ${total} session${total === 1 ? '' : 's'} across ${affected.size} topics${overflowNote} — ${parts.join(', ')}${more}. Each affected topic got its own notice.`;
95
401
  }
96
- formatSingle(ev) {
402
+ // ── Legacy formatting (byte-compatible) ──────────────────────────────
403
+ formatSingleLegacy(ev) {
97
404
  return `🪦 Session ${literal(ev.session.name)} was shut down — ${literal(ev.reason)}. `
98
405
  + `See the reap-log (\`GET /sessions/reap-log\`) for the full record.`;
99
406
  }
100
- formatBurst(count, detail) {
407
+ formatBurstLegacy(count, detail) {
101
408
  const lines = detail.map((e) => `• ${literal(e.session.name)} — ${literal(e.reason)}`);
102
409
  const shownNote = count > detail.length
103
410
  ? `\n\n(showing the latest ${detail.length}; full list in the reap-log)`
@@ -1 +1 @@
1
- {"version":3,"file":"ReapNotifier.js","sourceRoot":"","sources":["../../src/monitoring/ReapNotifier.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ReapNotifier.js","sourceRoot":"","sources":["../../src/monitoring/ReapNotifier.ts"],"names":[],"mappings":"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"}