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
@@ -0,0 +1,231 @@
1
+ /**
2
+ * ReapNoticeDrain — the ALWAYS-ON delivery loop for reap notices
3
+ * (reap-notify spec R1.3, tier0 supervision — deterministic delivery of
4
+ * pre-authored template content, declared per P7).
5
+ *
6
+ * Why it exists: the durable layer's existing drain (DeliveryFailureSentinel)
7
+ * is default-OFF fleet-wide, so "DFS will retry it" is false on a default
8
+ * agent — the round-2 foundation audit's central finding. The R1 guarantee
9
+ * ("every non-silent reap produces a durable, retried, recorded notice")
10
+ * therefore ships its OWN small always-on drain, independent of the DFS flag.
11
+ *
12
+ * Contract:
13
+ * - Claims ONLY rows inside the `reap-notify:` PK range (index-compatible
14
+ * range predicate; DFS claims the complement). The claim itself is a CAS
15
+ * UPDATE — two drains can never double-claim a row.
16
+ * - 30s tick; idle cost is one indexed claim query (~zero on an empty store).
17
+ * - Per-pass send cap (15) keeps a 500-topic storm under Telegram's
18
+ * per-group rate: 500 durable rows drain over ~17 minutes (R1.5's global
19
+ * release throttle); the remainder is picked up next tick.
20
+ * - Delivery is the DIRECT adapter send (`sendToTopic`) — NOT the
21
+ * /telegram/reply relay — so the relay's tone gate, whoami check, and
22
+ * duplicate-suppression are structurally off this path (notices carry
23
+ * per-notice distinct content anyway).
24
+ * - Bounded retries: store-backed exponential backoff on the existing
25
+ * attempts/next_attempt_at columns; at `maxAttempts` (8) the row is
26
+ * escalated terminally into ONE aggregated attention item (updated in
27
+ * place — never per-row items; P17).
28
+ * - Outcome records (R1.3 pairs): the terminal record (`sent` /
29
+ * `send-failed-escalated`) is appended HERE, event-driven from the drain
30
+ * that owns the terminal transition.
31
+ * - Loop brakes (P19, declared): backoff + maxAttempts + per-pass cap +
32
+ * terminal escalation; plus a bounded terminal-row cleanup so the
33
+ * always-on lane cannot grow the store unboundedly while DFS's retention
34
+ * pass is off.
35
+ */
36
+ import { parseReapNotifyDeliveryId } from '../messaging/reap-notice-delivery-id.js';
37
+ export const DEFAULT_REAP_NOTICE_DRAIN_OPTIONS = {
38
+ tickIntervalMs: 30_000,
39
+ perPassSendCap: 15,
40
+ maxAttempts: 8,
41
+ leaseDurationMs: 120_000,
42
+ backoffBaseMs: 30_000,
43
+ backoffMaxMs: 30 * 60_000,
44
+ terminalRetentionMs: 24 * 3600_000,
45
+ };
46
+ const ESCALATION_ATTENTION_ID = 'reap-notice-drain:escalations';
47
+ export class ReapNoticeDrain {
48
+ deps;
49
+ opts;
50
+ now;
51
+ timer = null;
52
+ ticking = false;
53
+ /** Rolling escalation aggregate since boot (feeds the ONE attention item). */
54
+ escalations = [];
55
+ lastCleanupAt = 0;
56
+ constructor(deps, opts) {
57
+ this.deps = deps;
58
+ this.opts = { ...DEFAULT_REAP_NOTICE_DRAIN_OPTIONS, ...(opts ?? {}) };
59
+ this.now = deps.now ?? (() => Date.now());
60
+ }
61
+ start() {
62
+ if (this.timer)
63
+ return;
64
+ this.timer = setInterval(() => {
65
+ void this.tick().catch(() => {
66
+ /* @silent-fallback-ok — last-resort belt: tick() already guards and
67
+ records every per-row failure durably (attempts/backoff/escalation);
68
+ a throw here would only kill the interval timer. */
69
+ });
70
+ }, this.opts.tickIntervalMs);
71
+ if (typeof this.timer.unref === 'function')
72
+ this.timer.unref();
73
+ }
74
+ stop() {
75
+ if (this.timer) {
76
+ clearInterval(this.timer);
77
+ this.timer = null;
78
+ }
79
+ }
80
+ /** One drain pass. Public so tests (and a manual flush) can drive it. */
81
+ async tick() {
82
+ const counters = { sent: 0, retried: 0, escalated: 0 };
83
+ if (this.ticking)
84
+ return counters; // re-entrancy guard
85
+ this.ticking = true;
86
+ try {
87
+ const nowMs = this.now();
88
+ const nowIso = new Date(nowMs).toISOString();
89
+ let candidates = [];
90
+ try {
91
+ candidates = this.deps.store
92
+ .selectClaimableReapNotices(nowIso, this.opts.perPassSendCap * 2)
93
+ .filter((row) => row.state === 'queued' || this.isLeaseStale(row, nowMs));
94
+ }
95
+ catch (err) {
96
+ console.warn('[reap-notice-drain] select raised:', err);
97
+ return counters;
98
+ }
99
+ let processed = 0;
100
+ for (const row of candidates) {
101
+ if (processed >= this.opts.perPassSendCap)
102
+ break;
103
+ const leaseUntil = new Date(nowMs + this.opts.leaseDurationMs).toISOString();
104
+ const claimedBy = `${this.deps.bootId}:${process.pid}:${leaseUntil}`;
105
+ let won = false;
106
+ try {
107
+ won = this.deps.store.claimCas(row.delivery_id, claimedBy, {
108
+ state: row.state,
109
+ claimed_by: row.claimed_by,
110
+ });
111
+ }
112
+ catch {
113
+ won = false;
114
+ }
115
+ if (!won)
116
+ continue; // lost the race (or the row moved) — next tick re-selects
117
+ processed++;
118
+ const noticeId = parseReapNotifyDeliveryId(row.delivery_id) ?? row.delivery_id;
119
+ const text = Buffer.isBuffer(row.text) ? row.text.toString('utf-8') : String(row.text ?? '');
120
+ try {
121
+ await this.deps.sendToTopic(row.topic_id, text);
122
+ this.safeTransition(row.delivery_id, 'delivered-recovered', { claimed_by: null });
123
+ this.safeRecord({ noticeId, topicId: row.topic_id, outcome: 'sent' });
124
+ counters.sent++;
125
+ }
126
+ catch (err) {
127
+ const errMsg = err instanceof Error ? err.message : String(err);
128
+ const attempts = (row.attempts ?? 1) + 1;
129
+ if (attempts >= this.opts.maxAttempts) {
130
+ this.safeTransition(row.delivery_id, 'escalated', {
131
+ attempts,
132
+ claimed_by: null,
133
+ error_body: errMsg.slice(0, 512),
134
+ });
135
+ this.safeRecord({
136
+ noticeId,
137
+ topicId: row.topic_id,
138
+ outcome: 'send-failed-escalated',
139
+ detail: `after ${attempts} attempts: ${errMsg.slice(0, 200)}`,
140
+ });
141
+ counters.escalated++;
142
+ await this.escalate(noticeId, row.topic_id, nowIso);
143
+ }
144
+ else {
145
+ const backoff = Math.min(this.opts.backoffBaseMs * 2 ** Math.max(0, attempts - 1), this.opts.backoffMaxMs);
146
+ this.safeTransition(row.delivery_id, 'queued', {
147
+ attempts,
148
+ claimed_by: null,
149
+ next_attempt_at: new Date(nowMs + backoff).toISOString(),
150
+ error_body: errMsg.slice(0, 512),
151
+ });
152
+ counters.retried++;
153
+ }
154
+ }
155
+ }
156
+ // Bounded terminal-row cleanup (≤ once/hour).
157
+ if (nowMs - this.lastCleanupAt > 3600_000) {
158
+ this.lastCleanupAt = nowMs;
159
+ try {
160
+ this.deps.store.purgeTerminalReapNotices(new Date(nowMs - this.opts.terminalRetentionMs).toISOString());
161
+ }
162
+ catch {
163
+ /* cleanup is best-effort */
164
+ }
165
+ }
166
+ return counters;
167
+ }
168
+ finally {
169
+ this.ticking = false;
170
+ }
171
+ }
172
+ /** Lease format mirrors DFS: `<bootId>:<pid>:<leaseUntilIso>`. */
173
+ isLeaseStale(row, nowMs) {
174
+ if (!row.claimed_by)
175
+ return true;
176
+ const parts = row.claimed_by.split(':');
177
+ if (parts.length < 3)
178
+ return true;
179
+ const bootId = parts[0];
180
+ const leaseUntilIso = parts.slice(2).join(':');
181
+ if (bootId !== this.deps.bootId)
182
+ return true; // prior boot — reclaimable
183
+ const lease = Date.parse(leaseUntilIso);
184
+ if (Number.isNaN(lease))
185
+ return true;
186
+ return lease < nowMs;
187
+ }
188
+ safeTransition(deliveryId, state, fields) {
189
+ try {
190
+ this.deps.store.transition(deliveryId, state, fields);
191
+ }
192
+ catch (err) {
193
+ console.warn(`[reap-notice-drain] transition(${deliveryId}, ${state}) raised:`, err);
194
+ }
195
+ }
196
+ safeRecord(e) {
197
+ try {
198
+ this.deps.recordNotify(e);
199
+ }
200
+ catch {
201
+ /* the audit sink never endangers delivery */
202
+ }
203
+ }
204
+ /** ONE rolling deduped attention item, updated in place (P17). */
205
+ async escalate(noticeId, topicId, atIso) {
206
+ this.escalations.push({ noticeId, topicId, at: atIso });
207
+ if (this.escalations.length > 50)
208
+ this.escalations.shift();
209
+ if (!this.deps.emitAttention)
210
+ return;
211
+ const topics = [...new Set(this.escalations.map((e) => e.topicId))];
212
+ try {
213
+ await this.deps.emitAttention({
214
+ id: ESCALATION_ATTENTION_ID,
215
+ title: `Reap notices could not be delivered (${this.escalations.length} since startup)`,
216
+ summary: `Delivery of session-shutdown notices failed after all retries for topic(s) ${topics.join(', ')}.`,
217
+ description: `I tried to tell the affected conversation(s) that sessions were shut down, but the messages ` +
218
+ `could not be delivered after repeated attempts. The shutdowns themselves are all recorded — ` +
219
+ `ask me "what happened to my sessions?" and I can reconstruct it. Most recent failure: notice ` +
220
+ `${noticeId} for topic ${topicId} at ${atIso}.`,
221
+ category: 'delivery',
222
+ priority: 'medium',
223
+ sourceContext: 'reap-notice-drain',
224
+ });
225
+ }
226
+ catch (err) {
227
+ console.warn('[reap-notice-drain] attention emit failed:', err);
228
+ }
229
+ }
230
+ }
231
+ //# sourceMappingURL=ReapNoticeDrain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReapNoticeDrain.js","sourceRoot":"","sources":["../../src/monitoring/ReapNoticeDrain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAGH,OAAO,EAAE,yBAAyB,EAAE,MAAM,yCAAyC,CAAC;AAuDpF,MAAM,CAAC,MAAM,iCAAiC,GAA2B;IACvE,cAAc,EAAE,MAAM;IACtB,cAAc,EAAE,EAAE;IAClB,WAAW,EAAE,CAAC;IACd,eAAe,EAAE,OAAO;IACxB,aAAa,EAAE,MAAM;IACrB,YAAY,EAAE,EAAE,GAAG,MAAM;IACzB,mBAAmB,EAAE,EAAE,GAAG,QAAQ;CACnC,CAAC;AAEF,MAAM,uBAAuB,GAAG,+BAA+B,CAAC;AAEhE,MAAM,OAAO,eAAe;IACT,IAAI,CAAsB;IAC1B,IAAI,CAAyB;IAC7B,GAAG,CAAe;IAC3B,KAAK,GAA0B,IAAI,CAAC;IACpC,OAAO,GAAG,KAAK,CAAC;IACxB,8EAA8E;IACtE,WAAW,GAA6D,EAAE,CAAC;IAC3E,aAAa,GAAG,CAAC,CAAC;IAE1B,YAAY,IAAyB,EAAE,IAAsC;QAC3E,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,EAAE,GAAG,iCAAiC,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;QACtE,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO;QACvB,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;YAC5B,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;gBAC1B;;sEAEsD;YACxD,CAAC,CAAC,CAAC;QACL,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC7B,IAAI,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,UAAU;YAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACjE,CAAC;IAED,IAAI;QACF,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,KAAK,CAAC,IAAI;QACR,MAAM,QAAQ,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;QACvD,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO,QAAQ,CAAC,CAAC,oBAAoB;QACvD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACzB,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;YAE7C,IAAI,UAAU,GAAsB,EAAE,CAAC;YACvC,IAAI,CAAC;gBACH,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK;qBACzB,0BAA0B,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC;qBAChE,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;YAC9E,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,oCAAoC,EAAE,GAAG,CAAC,CAAC;gBACxD,OAAO,QAAQ,CAAC;YAClB,CAAC;YAED,IAAI,SAAS,GAAG,CAAC,CAAC;YAClB,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;gBAC7B,IAAI,SAAS,IAAI,IAAI,CAAC,IAAI,CAAC,cAAc;oBAAE,MAAM;gBACjD,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,WAAW,EAAE,CAAC;gBAC7E,MAAM,SAAS,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,CAAC;gBACrE,IAAI,GAAG,GAAG,KAAK,CAAC;gBAChB,IAAI,CAAC;oBACH,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,EAAE;wBACzD,KAAK,EAAE,GAAG,CAAC,KAAK;wBAChB,UAAU,EAAE,GAAG,CAAC,UAAU;qBAC3B,CAAC,CAAC;gBACL,CAAC;gBAAC,MAAM,CAAC;oBACP,GAAG,GAAG,KAAK,CAAC;gBACd,CAAC;gBACD,IAAI,CAAC,GAAG;oBAAE,SAAS,CAAC,0DAA0D;gBAC9E,SAAS,EAAE,CAAC;gBAEZ,MAAM,QAAQ,GAAG,yBAAyB,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,WAAW,CAAC;gBAC/E,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;gBAC7F,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;oBAChD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,WAAW,EAAE,qBAAqB,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;oBAClF,IAAI,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;oBACtE,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAClB,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;oBAChE,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;oBACzC,IAAI,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;wBACtC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,WAAW,EAAE,WAAW,EAAE;4BAChD,QAAQ;4BACR,UAAU,EAAE,IAAI;4BAChB,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;yBACjC,CAAC,CAAC;wBACH,IAAI,CAAC,UAAU,CAAC;4BACd,QAAQ;4BACR,OAAO,EAAE,GAAG,CAAC,QAAQ;4BACrB,OAAO,EAAE,uBAAuB;4BAChC,MAAM,EAAE,SAAS,QAAQ,cAAc,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;yBAC9D,CAAC,CAAC;wBACH,QAAQ,CAAC,SAAS,EAAE,CAAC;wBACrB,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;oBACtD,CAAC;yBAAM,CAAC;wBACN,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CACtB,IAAI,CAAC,IAAI,CAAC,aAAa,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,CAAC,CAAC,EACxD,IAAI,CAAC,IAAI,CAAC,YAAY,CACvB,CAAC;wBACF,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,EAAE;4BAC7C,QAAQ;4BACR,UAAU,EAAE,IAAI;4BAChB,eAAe,EAAE,IAAI,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,CAAC,WAAW,EAAE;4BACxD,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;yBACjC,CAAC,CAAC;wBACH,QAAQ,CAAC,OAAO,EAAE,CAAC;oBACrB,CAAC;gBACH,CAAC;YACH,CAAC;YAED,8CAA8C;YAC9C,IAAI,KAAK,GAAG,IAAI,CAAC,aAAa,GAAG,QAAQ,EAAE,CAAC;gBAC1C,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;gBAC3B,IAAI,CAAC;oBACH,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,wBAAwB,CACtC,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,WAAW,EAAE,CAC9D,CAAC;gBACJ,CAAC;gBAAC,MAAM,CAAC;oBACP,4BAA4B;gBAC9B,CAAC;YACH,CAAC;YACD,OAAO,QAAQ,CAAC;QAClB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACvB,CAAC;IACH,CAAC;IAED,kEAAkE;IAC1D,YAAY,CAAC,GAAoB,EAAE,KAAa;QACtD,IAAI,CAAC,GAAG,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC;QACjC,MAAM,KAAK,GAAG,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QAClC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACxB,MAAM,aAAa,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/C,IAAI,MAAM,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC,CAAC,2BAA2B;QACzE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACxC,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACrC,OAAO,KAAK,GAAG,KAAK,CAAC;IACvB,CAAC;IAEO,cAAc,CACpB,UAAkB,EAClB,KAAoB,EACpB,MAA4H;QAE5H,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACxD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,kCAAkC,UAAU,KAAK,KAAK,WAAW,EAAE,GAAG,CAAC,CAAC;QACvF,CAAC;IACH,CAAC;IAEO,UAAU,CAAC,CAA4F;QAC7G,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,6CAA6C;QAC/C,CAAC;IACH,CAAC;IAED,kEAAkE;IAC1D,KAAK,CAAC,QAAQ,CAAC,QAAgB,EAAE,OAAe,EAAE,KAAa;QACrE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QACxD,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,EAAE;YAAE,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;QAC3D,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE,OAAO;QACrC,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACpE,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;gBAC5B,EAAE,EAAE,uBAAuB;gBAC3B,KAAK,EAAE,wCAAwC,IAAI,CAAC,WAAW,CAAC,MAAM,iBAAiB;gBACvF,OAAO,EAAE,8EAA8E,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;gBAC3G,WAAW,EACT,8FAA8F;oBAC9F,8FAA8F;oBAC9F,+FAA+F;oBAC/F,GAAG,QAAQ,cAAc,OAAO,OAAO,KAAK,GAAG;gBACjD,QAAQ,EAAE,UAAU;gBACpB,QAAQ,EAAE,QAAQ;gBAClB,aAAa,EAAE,mBAAmB;aACnC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,4CAA4C,EAAE,GAAG,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;CACF"}
@@ -1,50 +1,103 @@
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
  */
25
42
  import type { Session } from '../core/types.js';
43
+ import type { ReapNotifyOutcome } from './ReapLog.js';
26
44
  export interface ReapEvent {
27
45
  session: Pick<Session, 'name' | 'tmuxSession'>;
28
46
  reason: string;
29
47
  disposition?: 'terminal' | 'recovery-bounce';
30
48
  origin?: 'operator' | 'autonomous';
49
+ /** Mid-work stamp from the kill chokepoint (reap-notify spec R2.1). */
50
+ midWork?: boolean;
51
+ /** Clamped work-evidence names behind midWork. */
52
+ workEvidence?: string[];
31
53
  }
32
54
  export interface ReapNotifierDeps {
33
55
  /** Bound messaging topic for a session, or null if unbound. */
34
56
  resolveTopic: (tmuxSession: string) => number | null;
35
57
  /** The always-on system/lifeline topic, or null if none is configured. */
36
58
  lifelineTopic: () => number | null;
37
- /** Deliver a (GFM) notice to a topic. Wiring decides the transport/tier. */
59
+ /** Legacy delivery (perTopic:false and drainEnabled:false modes). */
38
60
  send: (topicId: number, text: string) => void | Promise<void>;
61
+ /** Durable store enqueue (v2). Returns false on PK-dedupe no-op. */
62
+ enqueueNotice?: (input: {
63
+ delivery_id: string;
64
+ topic_id: number;
65
+ text: string;
66
+ next_attempt_at: string;
67
+ }) => boolean;
68
+ /** Append a notify outcome record to the reap-log (R1.3 pairs). */
69
+ recordNotify?: (e: {
70
+ noticeId: string;
71
+ topicId: number | null;
72
+ outcome: ReapNotifyOutcome;
73
+ detail?: string;
74
+ }) => void;
75
+ /** Epoch ms when the current quiet-hours window ends; null = not in quiet hours. */
76
+ quietHoursEndAt?: (nowMs: number) => number | null;
77
+ /** Epoch ms of the next SUMMARY-window release (≤30 min out — R1.5). */
78
+ summaryReleaseAt?: (nowMs: number) => number;
79
+ /** True when a resume-queue entry is QUEUED for this session AND the queue is
80
+ * LIVE (not dry-run) — gates the "resume queued" line (R1.2). */
81
+ resumeQueuedFor?: (tmuxSession: string) => boolean;
82
+ /** Loud degradation surface for enqueue failures (aggregated upstream). */
83
+ reportDegradation?: (reason: string, impact: string) => void;
39
84
  now?: () => number;
40
85
  }
41
86
  export interface ReapNotifierOptions {
42
87
  enabled: boolean;
43
88
  coalesceWindowMs: number;
44
- /** Max reaps retained for the consolidated-message detail list (count is exact regardless). */
89
+ /** Max reaps retained for detail lists (counts stay exact regardless). */
45
90
  maxBuffer: number;
91
+ /** v2 per-topic grouping (R1.1). false = legacy single-buffer behavior. */
92
+ perTopic: boolean;
93
+ /** Max notices released IMMEDIATE in one flush (R1.5). */
94
+ maxImmediatePerFlush: number;
95
+ /** Durable delivery via store + drain (R1.3). false = legacy direct send
96
+ * (grouping unaffected; the durability guarantee lapses — stated rollback). */
97
+ drainEnabled: boolean;
46
98
  }
47
99
  export declare const DEFAULT_REAP_NOTIFIER_OPTIONS: ReapNotifierOptions;
100
+ export declare function plainEnglishReason(slug: string): string;
48
101
  export declare class ReapNotifier {
49
102
  private readonly deps;
50
103
  private readonly opts;
@@ -52,15 +105,33 @@ export declare class ReapNotifier {
52
105
  private timer;
53
106
  private buffer;
54
107
  private windowCount;
108
+ /** v2 affected-set (R1.1) — tracked separately from the detail buffer. */
109
+ private affected;
110
+ private affectedOverflow;
111
+ private unbound;
112
+ private noticeSeq;
55
113
  constructor(deps: ReapNotifierDeps, opts?: Partial<ReapNotifierOptions>);
56
114
  /** The `sessionReaped` event handler. */
57
115
  onReaped(event: ReapEvent): void;
116
+ private trackAffected;
117
+ /** Remove a buffer-evicted event from its topic's detail list (count stays). */
118
+ private dropDetail;
119
+ private safeResolveTopic;
120
+ private safeResumeQueued;
58
121
  /**
59
122
  * Emit the coalesced notice(s) for the closed window and reset. Public so the
60
123
  * lifecycle (and tests) can drive it deterministically.
61
124
  */
62
125
  flush(): Promise<void>;
63
- private formatSingle;
64
- private formatBurst;
126
+ /** Legacy (pre-v2) flush — byte-compatible single-buffer behavior. */
127
+ private flushLegacy;
128
+ private nextNoticeId;
129
+ private releaseAt;
130
+ private deliver;
131
+ private formatTopicNotice;
132
+ private formatUnboundNotice;
133
+ private formatCrossTopicIndex;
134
+ private formatSingleLegacy;
135
+ private formatBurstLegacy;
65
136
  }
66
137
  //# sourceMappingURL=ReapNotifier.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ReapNotifier.d.ts","sourceRoot":"","sources":["../../src/monitoring/ReapNotifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEhD,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAAC,CAAC;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,UAAU,GAAG,iBAAiB,CAAC;IAC7C,MAAM,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;CACpC;AAED,MAAM,WAAW,gBAAgB;IAC/B,+DAA+D;IAC/D,YAAY,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACrD,0EAA0E;IAC1E,aAAa,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IACnC,4EAA4E;IAC5E,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,+FAA+F;IAC/F,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,6BAA6B,EAAE,mBAI3C,CAAC;AAQF,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmB;IACxC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAsB;IAC3C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,WAAW,CAAK;gBAEZ,IAAI,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC;IAMvE,yCAAyC;IACzC,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAiBhC;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB5B,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,WAAW;CAWpB"}
1
+ {"version":3,"file":"ReapNotifier.d.ts","sourceRoot":"","sources":["../../src/monitoring/ReapNotifier.ts"],"names":[],"mappings":"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"}