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.
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +407 -6
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +10 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +1 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +69 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/ReapGuard.d.ts +24 -0
- package/dist/core/ReapGuard.d.ts.map +1 -1
- package/dist/core/ReapGuard.js +62 -0
- package/dist/core/ReapGuard.js.map +1 -1
- package/dist/core/SessionManager.d.ts +32 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +74 -2
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/WorkEvidence.d.ts +45 -0
- package/dist/core/WorkEvidence.d.ts.map +1 -0
- package/dist/core/WorkEvidence.js +88 -0
- package/dist/core/WorkEvidence.js.map +1 -0
- package/dist/core/componentCategories.d.ts.map +1 -1
- package/dist/core/componentCategories.js +3 -0
- package/dist/core/componentCategories.js.map +1 -1
- package/dist/core/devGatedFeatures.d.ts.map +1 -1
- package/dist/core/devGatedFeatures.js +5 -0
- package/dist/core/devGatedFeatures.js.map +1 -1
- package/dist/core/types.d.ts +50 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/messaging/NotificationBatcher.d.ts +12 -0
- package/dist/messaging/NotificationBatcher.d.ts.map +1 -1
- package/dist/messaging/NotificationBatcher.js +36 -0
- package/dist/messaging/NotificationBatcher.js.map +1 -1
- package/dist/messaging/pending-relay-store.d.ts +67 -8
- package/dist/messaging/pending-relay-store.d.ts.map +1 -1
- package/dist/messaging/pending-relay-store.js +151 -14
- package/dist/messaging/pending-relay-store.js.map +1 -1
- package/dist/messaging/reap-notice-delivery-id.d.ts +37 -0
- package/dist/messaging/reap-notice-delivery-id.d.ts.map +1 -0
- package/dist/messaging/reap-notice-delivery-id.js +52 -0
- package/dist/messaging/reap-notice-delivery-id.js.map +1 -0
- package/dist/monitoring/QuotaManager.d.ts +6 -0
- package/dist/monitoring/QuotaManager.d.ts.map +1 -1
- package/dist/monitoring/QuotaManager.js +11 -0
- package/dist/monitoring/QuotaManager.js.map +1 -1
- package/dist/monitoring/ReapLog.d.ts +39 -4
- package/dist/monitoring/ReapLog.d.ts.map +1 -1
- package/dist/monitoring/ReapLog.js +54 -4
- package/dist/monitoring/ReapLog.js.map +1 -1
- package/dist/monitoring/ReapNoticeDrain.d.ts +113 -0
- package/dist/monitoring/ReapNoticeDrain.d.ts.map +1 -0
- package/dist/monitoring/ReapNoticeDrain.js +231 -0
- package/dist/monitoring/ReapNoticeDrain.js.map +1 -0
- package/dist/monitoring/ReapNotifier.d.ts +89 -18
- package/dist/monitoring/ReapNotifier.d.ts.map +1 -1
- package/dist/monitoring/ReapNotifier.js +329 -22
- package/dist/monitoring/ReapNotifier.js.map +1 -1
- package/dist/monitoring/ResumeQueue.d.ts +223 -0
- package/dist/monitoring/ResumeQueue.d.ts.map +1 -0
- package/dist/monitoring/ResumeQueue.js +600 -0
- package/dist/monitoring/ResumeQueue.js.map +1 -0
- package/dist/monitoring/ResumeQueueDrainer.d.ts +151 -0
- package/dist/monitoring/ResumeQueueDrainer.d.ts.map +1 -0
- package/dist/monitoring/ResumeQueueDrainer.js +420 -0
- package/dist/monitoring/ResumeQueueDrainer.js.map +1 -0
- package/dist/monitoring/SessionMigrator.d.ts +10 -0
- package/dist/monitoring/SessionMigrator.d.ts.map +1 -1
- package/dist/monitoring/SessionMigrator.js +43 -1
- package/dist/monitoring/SessionMigrator.js.map +1 -1
- package/dist/monitoring/SessionReaper.d.ts +1 -0
- package/dist/monitoring/SessionReaper.d.ts.map +1 -1
- package/dist/monitoring/SessionReaper.js +5 -0
- package/dist/monitoring/SessionReaper.js.map +1 -1
- package/dist/monitoring/delivery-failure-sentinel.d.ts.map +1 -1
- package/dist/monitoring/delivery-failure-sentinel.js +7 -3
- package/dist/monitoring/delivery-failure-sentinel.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +4 -3
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts +5 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +3 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/routes.d.ts +8 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +94 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/skills/spec-converge/SKILL.md +23 -0
- package/src/data/builtin-manifest.json +65 -65
- package/src/data/state-coherence-registry.json +14 -1
- package/src/scaffold/templates.ts +4 -3
- package/upgrades/1.3.500.md +43 -0
- package/upgrades/1.3.501.md +51 -0
- package/upgrades/side-effects/conformance-gate-autoinvoke.md +58 -0
- 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
|
|
7
|
-
*
|
|
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
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* topic
|
|
16
|
-
* -
|
|
17
|
-
*
|
|
18
|
-
*
|
|
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
|
|
22
|
-
* Telegram formatter renders code spans as literal, HTML-escaped
|
|
23
|
-
* markup. The notifier never emits raw markup around
|
|
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
|
|
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
|
-
|
|
60
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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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"}
|