@catalyst-cloud/schema 0.1.17 → 0.1.19

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.
@@ -0,0 +1,2068 @@
1
+ // registry.ts — CTC-936 phase 2 (ADR-0039 binding condition 1). The closed, three-way,
2
+ // structurally-disjoint event-type registry: EVERY one of the 318 normalized types observed in the
3
+ // committed August census (docs/event-backbone/observed-types-2026-08.json) is classified here as a
4
+ // durable fact, a current-state (heartbeat-shaped) signal, or telemetry — never left unclassified.
5
+ //
6
+ // ⭐ STRUCTURAL, NOT SUBTRACTIVE — the CTC-671 idiom (packages/schema/src/index.ts's
7
+ // feedEntityTables/nonFeedEntityTables), copied deliberately. Three disjoint `as const` objects; a
8
+ // type's membership is a fact about which object it is typed into, never a filter or an exclusion
9
+ // array to forget. classifyEventType() derives from these objects — it never asserts a default.
10
+ //
11
+ // ⛔ THE 433 -> 318 STORY, because a future reader WILL ask why this doesn't match the plan's own
12
+ // headline number. The CTC-936 plan's Finding 2 measured 433 normalized types using a narrow rule
13
+ // (strip only a dot-joined CTC-###/CTL-###/ADV-### ticket id). Reproducing that narrow rule against
14
+ // this same census does land on 433 — but auditing those 433 found 87 of them (20%) still carrying
15
+ // an uppercase or underscore-bearing segment that fails the phase-1 grammar (packages/schema/src/
16
+ // events/type-grammar.ts): ticket ids under OTHER team prefixes the narrow rule didn't cover
17
+ // (OTL-67, EVR-39, CAT-1, PROJ-1, synthetic test ids like E-1/T-1), bare per-team codes with no
18
+ // ticket number (monitor.reconcile.failing.ADV/.CRM/.CTC/...), an orphan-detection status enum
19
+ // hyphen-fused onto a ticket id (...orphan-detected.CTL-1064-DIRTY), and — a different defect
20
+ // entirely — 46 legitimately snake_cased GitHub webhook names (check_suite, pr_review_comment,
21
+ // workflow_run, ...) that the lower-KEBAB-only grammar also rejects. Since this registry is KEYED ON
22
+ // the normalized type (the CTC-936 plan's Assumption 3) and every registry key must satisfy that
23
+ // grammar (see registry.test.ts), scripts/event-census.ts normalizes structurally instead of by an
24
+ // enumerated prefix list — see that file's header for the exact algorithm and the evidence. The
25
+ // result, verified type-by-type against the real isValidEventType() before being committed, is 318.
26
+ //
27
+ // ⚠️ Every DURABLE rationale below is a specific, reviewable claim, not a generated placeholder — the
28
+ // CTC-936 plan's own manual-verification bar. Grounded in ADR-0039's "What belongs in the event
29
+ // backbone" (its three named categories), Finding 3's measured durable/telemetry volume split, and
30
+ // (where noted) the raw JSONL evidence gathered while writing this file — e.g.
31
+ // recovery.skipped.pr-1071-blocked-by-a-pre-existing-repo-wide-ci-failure-on-main-n was confirmed
32
+ // against the actual log line to be a full free-text incident explanation baked into `event.name`.
33
+
34
+ import { keysOf } from "./registry-support.js";
35
+
36
+ /** Why a DURABLE fact belongs in the immutable history, which cloud ingest verb its producer already
37
+ * maps to (binding condition 2), and whether it may create a Queue wake-up pointer. */
38
+ export interface DurableEventSpec {
39
+ /** Why this is a durable FACT and not state or telemetry (ADR-0039 §"What belongs"). */
40
+ rationale: string;
41
+ /** The cloud ingest verb this producer maps to — binding condition 2. */
42
+ ingestVerb: "coordination.publish" | "webhook.ingest" | "artifacts.event";
43
+ /** May this type create a Queue wake-up pointer? (proposal phase-1 item 3) */
44
+ wakes: false | { consumerClass: "dispatcher" | "host-channel" };
45
+ /** The mirrored/domain entity this event is about, when it has one stable shape. */
46
+ entity?: string;
47
+ }
48
+
49
+ /**
50
+ * ⭐ THE CTC-936 CLOSED DURABLE-FACT REGISTRY. Every entry is a coordination or domain transition
51
+ * ADR-0039's "What belongs in the event backbone" §1 names: work became eligible; a lease was
52
+ * acquired/renewed/refused/expired/released; a phase started/completed/failed/preempted; a human
53
+ * answer was received; a provider webhook changed a mirrored entity; an arbiter made a decision; a
54
+ * runner reported an outcome.
55
+ */
56
+ export const durableEventTypes = {
57
+ "account.status.changed": {
58
+ rationale:
59
+ "A tenant account's operational status changed — a discrete boundary-crossing fact, not a sampled reading.",
60
+ ingestVerb: "coordination.publish",
61
+ wakes: false,
62
+ entity: "account",
63
+ },
64
+ "agent.checkin": {
65
+ rationale: "An agent (background worker) checking into a session — a real lifecycle fact.",
66
+ ingestVerb: "coordination.publish",
67
+ wakes: false,
68
+ },
69
+ "agent.checkout": {
70
+ rationale: "An agent checking out of a session — the paired fact to agent.checkin.",
71
+ ingestVerb: "coordination.publish",
72
+ wakes: false,
73
+ },
74
+ "agent.resumed": {
75
+ rationale: "An agent resumed from a paused/waiting state — a real lifecycle transition.",
76
+ ingestVerb: "coordination.publish",
77
+ wakes: false,
78
+ },
79
+ "agent.waiting-on-user": {
80
+ rationale:
81
+ "The agent is now blocked awaiting human input — a coordination fact a host must act on.",
82
+ ingestVerb: "coordination.publish",
83
+ wakes: { consumerClass: "host-channel" },
84
+ },
85
+ "broker.daemon.gc": {
86
+ rationale:
87
+ "The coordination broker daemon's own garbage-collection pass completing — a discrete lifecycle event of the process that OWNS the coordination log, worth recording to explain gaps in the log's own continuity.",
88
+ ingestVerb: "coordination.publish",
89
+ wakes: false,
90
+ },
91
+ "broker.daemon.shutdown": {
92
+ rationale:
93
+ "The coordination broker daemon stopped — the boundary fact broker.daemon.heartbeat's absence corresponds to.",
94
+ ingestVerb: "coordination.publish",
95
+ wakes: false,
96
+ },
97
+ "broker.daemon.startup": {
98
+ rationale:
99
+ "The coordination broker daemon started — the boundary fact broker.daemon.heartbeat's presence corresponds to.",
100
+ ingestVerb: "coordination.publish",
101
+ wakes: false,
102
+ },
103
+ "broker.terminal-needs-human.reconciled": {
104
+ rationale:
105
+ "A ticket that needed human attention was reconciled — 'a human answer was received', ADR-0039's own example, applied to the broker's own escalation queue.",
106
+ ingestVerb: "coordination.publish",
107
+ wakes: false,
108
+ entity: "ticket",
109
+ },
110
+ "catalyst.alert.boot-resume-pending": {
111
+ rationale:
112
+ "An operator-facing alert about a pending boot-resume — a real coordination fact needing eventual resolution.",
113
+ ingestVerb: "coordination.publish",
114
+ wakes: false,
115
+ },
116
+ "catalyst.alert.cleared": {
117
+ rationale: "An operator-facing alert was cleared — the paired fact to catalyst.alert.raised.",
118
+ ingestVerb: "coordination.publish",
119
+ wakes: false,
120
+ },
121
+ "catalyst.alert.raised": {
122
+ rationale: "An operator-facing alert was raised — a real event needing operator attention.",
123
+ ingestVerb: "coordination.publish",
124
+ wakes: { consumerClass: "host-channel" },
125
+ },
126
+ "catalyst.alert.ticket-state-live-fallback": {
127
+ rationale:
128
+ "An alert that a ticket-state read fell back to a live (non-replica) source — a real degraded-path fact, low volume.",
129
+ ingestVerb: "coordination.publish",
130
+ wakes: false,
131
+ entity: "ticket",
132
+ },
133
+ "catalyst.cluster.secrets.refreshed": {
134
+ rationale:
135
+ "The cluster's secrets were rotated — a real, low-volume infra state change worth an audit trail.",
136
+ ingestVerb: "coordination.publish",
137
+ wakes: false,
138
+ },
139
+ "catalyst.cluster.secrets.restart-required": {
140
+ rationale:
141
+ "A secrets rotation requires a restart to take effect — a real operational fact, not a sample.",
142
+ ingestVerb: "coordination.publish",
143
+ wakes: false,
144
+ },
145
+ "catalyst.ingestion.recovered": {
146
+ rationale:
147
+ "An ingestion pipeline's health crossed back to healthy — the boundary-crossing fact (ADR-0039's node.recovered pattern) applied to ingestion.",
148
+ ingestVerb: "coordination.publish",
149
+ wakes: false,
150
+ },
151
+ "catalyst.ingestion.stale": {
152
+ rationale:
153
+ "An ingestion pipeline's health crossed into stale — the boundary-crossing fact (ADR-0039's node.offline pattern) applied to ingestion.",
154
+ ingestVerb: "coordination.publish",
155
+ wakes: false,
156
+ },
157
+ "comms.message.posted": {
158
+ rationale:
159
+ "A real cross-agent/human communication fact — an actual message was posted, not sampled.",
160
+ ingestVerb: "coordination.publish",
161
+ wakes: false,
162
+ },
163
+ "fence.claimed": {
164
+ rationale:
165
+ "ADR-0039's own durable-fact example, verbatim: 'a lease was acquired'. The single largest non-telemetry type by far (28k+/mo) — the coordination plane's core primitive.",
166
+ ingestVerb: "coordination.publish",
167
+ wakes: { consumerClass: "dispatcher" },
168
+ },
169
+ "fleet.health.degraded": {
170
+ rationale: "A fleet-wide health boundary crossing — paired with fleet.health.recovered.",
171
+ ingestVerb: "coordination.publish",
172
+ wakes: { consumerClass: "host-channel" },
173
+ },
174
+ "fleet.health.recovered": {
175
+ rationale: "The paired boundary-crossing fact to fleet.health.degraded.",
176
+ ingestVerb: "coordination.publish",
177
+ wakes: false,
178
+ },
179
+ "github.check-suite.completed": {
180
+ rationale:
181
+ "A GitHub webhook changed a mirrored check suite — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
182
+ ingestVerb: "webhook.ingest",
183
+ wakes: false,
184
+ entity: "check_suite",
185
+ },
186
+ "github.deployment-status.failure": {
187
+ rationale:
188
+ "A GitHub webhook changed a mirrored deployment — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
189
+ ingestVerb: "webhook.ingest",
190
+ wakes: false,
191
+ entity: "deployment",
192
+ },
193
+ "github.deployment-status.in-progress": {
194
+ rationale:
195
+ "A GitHub webhook changed a mirrored deployment — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
196
+ ingestVerb: "webhook.ingest",
197
+ wakes: false,
198
+ entity: "deployment",
199
+ },
200
+ "github.deployment-status.queued": {
201
+ rationale:
202
+ "A GitHub webhook changed a mirrored deployment — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
203
+ ingestVerb: "webhook.ingest",
204
+ wakes: false,
205
+ entity: "deployment",
206
+ },
207
+ "github.deployment-status.success": {
208
+ rationale:
209
+ "A GitHub webhook changed a mirrored deployment — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
210
+ ingestVerb: "webhook.ingest",
211
+ wakes: false,
212
+ entity: "deployment",
213
+ },
214
+ "github.deployment.created": {
215
+ rationale:
216
+ "A GitHub webhook changed a mirrored deployment — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
217
+ ingestVerb: "webhook.ingest",
218
+ wakes: false,
219
+ entity: "deployment",
220
+ },
221
+ "github.issue-comment.created": {
222
+ rationale:
223
+ "A GitHub webhook changed a mirrored comment — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
224
+ ingestVerb: "webhook.ingest",
225
+ wakes: false,
226
+ entity: "comment",
227
+ },
228
+ "github.issue-comment.deleted": {
229
+ rationale:
230
+ "A GitHub webhook changed a mirrored comment — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
231
+ ingestVerb: "webhook.ingest",
232
+ wakes: false,
233
+ entity: "comment",
234
+ },
235
+ "github.issue-comment.edited": {
236
+ rationale:
237
+ "A GitHub webhook changed a mirrored comment — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
238
+ ingestVerb: "webhook.ingest",
239
+ wakes: false,
240
+ entity: "comment",
241
+ },
242
+ "github.pr-review-comment.created": {
243
+ rationale:
244
+ "A GitHub webhook changed a mirrored comment — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
245
+ ingestVerb: "webhook.ingest",
246
+ wakes: false,
247
+ entity: "comment",
248
+ },
249
+ "github.pr-review-comment.edited": {
250
+ rationale:
251
+ "A GitHub webhook changed a mirrored comment — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
252
+ ingestVerb: "webhook.ingest",
253
+ wakes: false,
254
+ entity: "comment",
255
+ },
256
+ "github.pr-review-thread.resolved": {
257
+ rationale:
258
+ "A GitHub webhook changed a mirrored pr review thread — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
259
+ ingestVerb: "webhook.ingest",
260
+ wakes: false,
261
+ entity: "pr_review_thread",
262
+ },
263
+ "github.pr-review.submitted": {
264
+ rationale:
265
+ "A GitHub webhook changed a mirrored review — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
266
+ ingestVerb: "webhook.ingest",
267
+ wakes: false,
268
+ entity: "review",
269
+ },
270
+ "github.pr.auto-merge-disabled": {
271
+ rationale:
272
+ "A GitHub webhook changed a mirrored pull request — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
273
+ ingestVerb: "webhook.ingest",
274
+ wakes: false,
275
+ entity: "pull_request",
276
+ },
277
+ "github.pr.auto-merge-enabled": {
278
+ rationale:
279
+ "A GitHub webhook changed a mirrored pull request — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
280
+ ingestVerb: "webhook.ingest",
281
+ wakes: false,
282
+ entity: "pull_request",
283
+ },
284
+ "github.pr.closed": {
285
+ rationale:
286
+ "A GitHub webhook changed a mirrored pull request — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
287
+ ingestVerb: "webhook.ingest",
288
+ wakes: false,
289
+ entity: "pull_request",
290
+ },
291
+ "github.pr.converted-to-draft": {
292
+ rationale:
293
+ "A GitHub webhook changed a mirrored pull request — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
294
+ ingestVerb: "webhook.ingest",
295
+ wakes: false,
296
+ entity: "pull_request",
297
+ },
298
+ "github.pr.edited": {
299
+ rationale:
300
+ "A GitHub webhook changed a mirrored pull request — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
301
+ ingestVerb: "webhook.ingest",
302
+ wakes: false,
303
+ entity: "pull_request",
304
+ },
305
+ "github.pr.labeled": {
306
+ rationale:
307
+ "A GitHub webhook changed a mirrored pull request — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
308
+ ingestVerb: "webhook.ingest",
309
+ wakes: false,
310
+ entity: "pull_request",
311
+ },
312
+ "github.pr.merged": {
313
+ rationale:
314
+ "A GitHub webhook changed a mirrored pull request — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
315
+ ingestVerb: "webhook.ingest",
316
+ wakes: false,
317
+ entity: "pull_request",
318
+ },
319
+ "github.pr.opened": {
320
+ rationale:
321
+ "A GitHub webhook changed a mirrored pull request — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
322
+ ingestVerb: "webhook.ingest",
323
+ wakes: false,
324
+ entity: "pull_request",
325
+ },
326
+ "github.pr.ready-for-review": {
327
+ rationale:
328
+ "A GitHub webhook changed a mirrored pull request — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
329
+ ingestVerb: "webhook.ingest",
330
+ wakes: false,
331
+ entity: "pull_request",
332
+ },
333
+ "github.pr.reopened": {
334
+ rationale:
335
+ "A GitHub webhook changed a mirrored pull request — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
336
+ ingestVerb: "webhook.ingest",
337
+ wakes: false,
338
+ entity: "pull_request",
339
+ },
340
+ "github.pr.synchronize": {
341
+ rationale:
342
+ "A GitHub webhook changed a mirrored pull request — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
343
+ ingestVerb: "webhook.ingest",
344
+ wakes: false,
345
+ entity: "pull_request",
346
+ },
347
+ "github.pr.unlabeled": {
348
+ rationale:
349
+ "A GitHub webhook changed a mirrored pull request — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
350
+ ingestVerb: "webhook.ingest",
351
+ wakes: false,
352
+ entity: "pull_request",
353
+ },
354
+ "github.push": {
355
+ rationale:
356
+ "A GitHub webhook changed a mirrored push — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
357
+ ingestVerb: "webhook.ingest",
358
+ wakes: false,
359
+ entity: "push",
360
+ },
361
+ "github.release.created": {
362
+ rationale:
363
+ "A GitHub webhook changed a mirrored release — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
364
+ ingestVerb: "webhook.ingest",
365
+ wakes: false,
366
+ entity: "release",
367
+ },
368
+ "github.release.published": {
369
+ rationale:
370
+ "A GitHub webhook changed a mirrored release — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
371
+ ingestVerb: "webhook.ingest",
372
+ wakes: false,
373
+ entity: "release",
374
+ },
375
+ "github.release.released": {
376
+ rationale:
377
+ "A GitHub webhook changed a mirrored release — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
378
+ ingestVerb: "webhook.ingest",
379
+ wakes: false,
380
+ entity: "release",
381
+ },
382
+ "github.workflow-run.completed": {
383
+ rationale:
384
+ "A GitHub webhook changed a mirrored check run — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
385
+ ingestVerb: "webhook.ingest",
386
+ wakes: false,
387
+ entity: "check_run",
388
+ },
389
+ "github.workflow-run.in-progress": {
390
+ rationale:
391
+ "A GitHub webhook changed a mirrored check run — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
392
+ ingestVerb: "webhook.ingest",
393
+ wakes: false,
394
+ entity: "check_run",
395
+ },
396
+ "github.workflow-run.requested": {
397
+ rationale:
398
+ "A GitHub webhook changed a mirrored check run — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
399
+ ingestVerb: "webhook.ingest",
400
+ wakes: false,
401
+ entity: "check_run",
402
+ },
403
+ "linear.comment.created": {
404
+ rationale:
405
+ "A Linear webhook changed a mirrored comment — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
406
+ ingestVerb: "webhook.ingest",
407
+ wakes: false,
408
+ entity: "comment",
409
+ },
410
+ "linear.comment.removed": {
411
+ rationale:
412
+ "A Linear webhook changed a mirrored comment — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
413
+ ingestVerb: "webhook.ingest",
414
+ wakes: false,
415
+ entity: "comment",
416
+ },
417
+ "linear.comment.updated": {
418
+ rationale:
419
+ "A Linear webhook changed a mirrored comment — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
420
+ ingestVerb: "webhook.ingest",
421
+ wakes: false,
422
+ entity: "comment",
423
+ },
424
+ "linear.cycle.created": {
425
+ rationale:
426
+ "A Linear webhook changed a mirrored cycle — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
427
+ ingestVerb: "webhook.ingest",
428
+ wakes: false,
429
+ entity: "cycle",
430
+ },
431
+ "linear.cycle.updated": {
432
+ rationale:
433
+ "A Linear webhook changed a mirrored cycle — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
434
+ ingestVerb: "webhook.ingest",
435
+ wakes: false,
436
+ entity: "cycle",
437
+ },
438
+ "linear.issue-label.created": {
439
+ rationale:
440
+ "A Linear webhook changed a mirrored label — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
441
+ ingestVerb: "webhook.ingest",
442
+ wakes: false,
443
+ entity: "label",
444
+ },
445
+ "linear.issue-label.updated": {
446
+ rationale:
447
+ "A Linear webhook changed a mirrored label — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
448
+ ingestVerb: "webhook.ingest",
449
+ wakes: false,
450
+ entity: "label",
451
+ },
452
+ "linear.issue.assignee-changed": {
453
+ rationale:
454
+ "A Linear webhook changed a mirrored ticket — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
455
+ ingestVerb: "webhook.ingest",
456
+ wakes: false,
457
+ entity: "ticket",
458
+ },
459
+ "linear.issue.created": {
460
+ rationale:
461
+ "A Linear webhook changed a mirrored ticket — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
462
+ ingestVerb: "webhook.ingest",
463
+ wakes: false,
464
+ entity: "ticket",
465
+ },
466
+ "linear.issue.delegate-changed": {
467
+ rationale:
468
+ "A Linear webhook changed a mirrored ticket — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
469
+ ingestVerb: "webhook.ingest",
470
+ wakes: false,
471
+ entity: "ticket",
472
+ },
473
+ "linear.issue.priority-changed": {
474
+ rationale:
475
+ "A Linear webhook changed a mirrored ticket — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
476
+ ingestVerb: "webhook.ingest",
477
+ wakes: false,
478
+ entity: "ticket",
479
+ },
480
+ "linear.issue.removed": {
481
+ rationale:
482
+ "A Linear webhook changed a mirrored ticket — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
483
+ ingestVerb: "webhook.ingest",
484
+ wakes: false,
485
+ entity: "ticket",
486
+ },
487
+ "linear.issue.state-changed": {
488
+ rationale:
489
+ "A Linear webhook changed a mirrored ticket — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
490
+ ingestVerb: "webhook.ingest",
491
+ wakes: false,
492
+ entity: "ticket",
493
+ },
494
+ "linear.issue.updated": {
495
+ rationale:
496
+ "A Linear webhook changed a mirrored ticket — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
497
+ ingestVerb: "webhook.ingest",
498
+ wakes: false,
499
+ entity: "ticket",
500
+ },
501
+ "linear.label.retry-exhausted": {
502
+ rationale:
503
+ "The TERMINAL fact after a label-apply retry budget was exhausted — the boundary Finding 3 describes ('the retry-storm-collapses-to-a-boundary-event case'), not the per-retry noise itself.",
504
+ ingestVerb: "coordination.publish",
505
+ wakes: false,
506
+ entity: "ticket",
507
+ },
508
+ "linear.ratelimit.breaker": {
509
+ rationale:
510
+ "A circuit breaker tripping on the Linear write path is a meaningful operational boundary — low volume (21/mo), worth knowing exactly when Linear write access was cut off.",
511
+ ingestVerb: "coordination.publish",
512
+ wakes: false,
513
+ },
514
+ "linear.reaction.created": {
515
+ rationale:
516
+ "A Linear webhook changed a mirrored reaction — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
517
+ ingestVerb: "webhook.ingest",
518
+ wakes: false,
519
+ entity: "reaction",
520
+ },
521
+ "linear.reaction.removed": {
522
+ rationale:
523
+ "A Linear webhook changed a mirrored reaction — ADR-0039's own durable-fact example ('a provider webhook changed a relevant mirrored entity'), verbatim.",
524
+ ingestVerb: "webhook.ingest",
525
+ wakes: false,
526
+ entity: "reaction",
527
+ },
528
+ "linear.state.write": {
529
+ rationale:
530
+ "The write-proxy's own committed state change at the mirror layer — a real, replay-worthy fact distinct from the inbound webhook facts above.",
531
+ ingestVerb: "coordination.publish",
532
+ wakes: false,
533
+ entity: "ticket",
534
+ },
535
+ "linear.write.proxy.applied": {
536
+ rationale:
537
+ "The write-proxy successfully applied a write — the durable counterpart to linear.write.proxy.failed's retry-storm telemetry.",
538
+ ingestVerb: "coordination.publish",
539
+ wakes: false,
540
+ entity: "ticket",
541
+ },
542
+ "linear.write.proxy.budget-exhausted": {
543
+ rationale:
544
+ "The terminal fact after a write-proxy retry budget was exhausted — same boundary shape as linear.label.retry-exhausted.",
545
+ ingestVerb: "coordination.publish",
546
+ wakes: false,
547
+ entity: "ticket",
548
+ },
549
+ "monitor.reconcile.failing": {
550
+ rationale:
551
+ "A per-team Linear reconcile loop crossed into a failing state — a real boundary fact (the team id belongs in `entity`, not `type`; see the phase-1 grammar this collapsing enforces).",
552
+ ingestVerb: "coordination.publish",
553
+ wakes: false,
554
+ entity: "team",
555
+ },
556
+ "monitor.reconcile.recovered": {
557
+ rationale: "The paired boundary-crossing fact to monitor.reconcile.failing.",
558
+ ingestVerb: "coordination.publish",
559
+ wakes: false,
560
+ entity: "team",
561
+ },
562
+ "node.boot": {
563
+ rationale:
564
+ "A worker node came online — the durable boundary fact ADR-0039 names as node.online's analogue.",
565
+ ingestVerb: "coordination.publish",
566
+ wakes: { consumerClass: "dispatcher" },
567
+ },
568
+ "node.capacity.changed": {
569
+ rationale:
570
+ "A node's declared capacity changed — a real, low-volume coordination fact affecting dispatch decisions.",
571
+ ingestVerb: "coordination.publish",
572
+ wakes: false,
573
+ },
574
+ "node.drain.changed": {
575
+ rationale:
576
+ "A node's drain state changed — a real coordination fact (the node is being taken out of rotation).",
577
+ ingestVerb: "coordination.publish",
578
+ wakes: false,
579
+ },
580
+ "node.drain.ignored": {
581
+ rationale: "A drain request was ignored — a real, very-low-volume fact worth an audit trail.",
582
+ ingestVerb: "coordination.publish",
583
+ wakes: false,
584
+ },
585
+ "phase.advance.applied": {
586
+ rationale:
587
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): an advance-gate decision was applied — the phase pipeline actually moved forward.",
588
+ ingestVerb: "coordination.publish",
589
+ wakes: false,
590
+ entity: "ticket",
591
+ },
592
+ "phase.advance.held": {
593
+ rationale:
594
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): an advance-gate decision held the phase back — the pipeline deliberately did not move forward.",
595
+ ingestVerb: "coordination.publish",
596
+ wakes: false,
597
+ entity: "ticket",
598
+ },
599
+ "phase.advance.suppressed-duplicate": {
600
+ rationale:
601
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a duplicate advance was suppressed — a dedup decision worth keeping for audit, low volume.",
602
+ ingestVerb: "coordination.publish",
603
+ wakes: false,
604
+ entity: "ticket",
605
+ },
606
+ "phase.dispatch.claim-lost": {
607
+ rationale:
608
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a dispatch claim was lost to a concurrent race — a real coordination fact about who owns the work.",
609
+ ingestVerb: "coordination.publish",
610
+ wakes: false,
611
+ entity: "ticket",
612
+ },
613
+ "phase.dispatch.escalated": {
614
+ rationale:
615
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase escalated to a human.",
616
+ ingestVerb: "coordination.publish",
617
+ wakes: { consumerClass: "host-channel" },
618
+ entity: "ticket",
619
+ },
620
+ "phase.dispatch.failed": {
621
+ rationale:
622
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported failure.",
623
+ ingestVerb: "coordination.publish",
624
+ wakes: false,
625
+ entity: "ticket",
626
+ },
627
+ "phase.dispatch.launched": {
628
+ rationale:
629
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase's worker actually started running.",
630
+ ingestVerb: "coordination.publish",
631
+ wakes: { consumerClass: "dispatcher" },
632
+ entity: "ticket",
633
+ },
634
+ "phase.dispatch.requested": {
635
+ rationale:
636
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): work became eligible for dispatch — the phase was requested.",
637
+ ingestVerb: "coordination.publish",
638
+ wakes: { consumerClass: "dispatcher" },
639
+ entity: "ticket",
640
+ },
641
+ "phase.dispatch.runaway": {
642
+ rationale:
643
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a dispatch safety guard fired (runaway detection) — a real operational fact.",
644
+ ingestVerb: "coordination.publish",
645
+ wakes: false,
646
+ entity: "ticket",
647
+ },
648
+ "phase.implement.abandoned": {
649
+ rationale:
650
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase's worker abandoned it — a lifecycle terminal fact.",
651
+ ingestVerb: "coordination.publish",
652
+ wakes: false,
653
+ entity: "ticket",
654
+ },
655
+ "phase.implement.auto-rebased": {
656
+ rationale:
657
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase's branch was automatically rebased onto a moving base — a real, replay-worthy git-state fact.",
658
+ ingestVerb: "coordination.publish",
659
+ wakes: false,
660
+ entity: "ticket",
661
+ },
662
+ "phase.implement.boot-resume": {
663
+ rationale:
664
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted and resumed this phase — a real coordination fact about continuity across a restart.",
665
+ ingestVerb: "coordination.publish",
666
+ wakes: false,
667
+ entity: "ticket",
668
+ },
669
+ "phase.implement.boot-resume-gated": {
670
+ rationale:
671
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted but gated (did not immediately resume) this phase.",
672
+ ingestVerb: "coordination.publish",
673
+ wakes: false,
674
+ entity: "ticket",
675
+ },
676
+ "phase.implement.complete": {
677
+ rationale:
678
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported success.",
679
+ ingestVerb: "coordination.publish",
680
+ wakes: false,
681
+ entity: "ticket",
682
+ },
683
+ "phase.implement.escalated": {
684
+ rationale:
685
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase escalated to a human.",
686
+ ingestVerb: "coordination.publish",
687
+ wakes: { consumerClass: "host-channel" },
688
+ entity: "ticket",
689
+ },
690
+ "phase.implement.failed": {
691
+ rationale:
692
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported failure.",
693
+ ingestVerb: "coordination.publish",
694
+ wakes: false,
695
+ entity: "ticket",
696
+ },
697
+ "phase.implement.failure-retracted": {
698
+ rationale:
699
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a previously-reported failure was retracted (corrected) — a real correction fact.",
700
+ ingestVerb: "coordination.publish",
701
+ wakes: false,
702
+ entity: "ticket",
703
+ },
704
+ "phase.implement.orphan-detected": {
705
+ rationale:
706
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): an orphaned phase-agent worker was detected — a coordination fact (state discovered), not a sample.",
707
+ ingestVerb: "coordination.publish",
708
+ wakes: false,
709
+ entity: "ticket",
710
+ },
711
+ "phase.implement.park": {
712
+ rationale:
713
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase parked pending a blocker or human input — a real coordination state, not a heartbeat.",
714
+ ingestVerb: "coordination.publish",
715
+ wakes: false,
716
+ entity: "ticket",
717
+ },
718
+ "phase.implement.preempted": {
719
+ rationale:
720
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a higher-priority worker preempted this phase.",
721
+ ingestVerb: "coordination.publish",
722
+ wakes: false,
723
+ entity: "ticket",
724
+ },
725
+ "phase.implement.rebase-conflict-categorized": {
726
+ rationale:
727
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a real blocking rebase conflict was discovered and categorized during the phase.",
728
+ ingestVerb: "coordination.publish",
729
+ wakes: false,
730
+ entity: "ticket",
731
+ },
732
+ "phase.implement.rebase-conflict-stalled": {
733
+ rationale:
734
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase stalled on an unresolved rebase conflict.",
735
+ ingestVerb: "coordination.publish",
736
+ wakes: false,
737
+ entity: "ticket",
738
+ },
739
+ "phase.implement.resumed-after-preemption": {
740
+ rationale:
741
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase resumed after being preempted earlier — the paired fact to *.preempted.",
742
+ ingestVerb: "coordination.publish",
743
+ wakes: false,
744
+ entity: "ticket",
745
+ },
746
+ "phase.implement.revive": {
747
+ rationale:
748
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a parked phase was revived.",
749
+ ingestVerb: "coordination.publish",
750
+ wakes: false,
751
+ entity: "ticket",
752
+ },
753
+ "phase.monitor-deploy.abandoned": {
754
+ rationale:
755
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase's worker abandoned it — a lifecycle terminal fact.",
756
+ ingestVerb: "coordination.publish",
757
+ wakes: false,
758
+ entity: "ticket",
759
+ },
760
+ "phase.monitor-deploy.boot-resume": {
761
+ rationale:
762
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted and resumed this phase — a real coordination fact about continuity across a restart.",
763
+ ingestVerb: "coordination.publish",
764
+ wakes: false,
765
+ entity: "ticket",
766
+ },
767
+ "phase.monitor-deploy.boot-resume-gated": {
768
+ rationale:
769
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted but gated (did not immediately resume) this phase.",
770
+ ingestVerb: "coordination.publish",
771
+ wakes: false,
772
+ entity: "ticket",
773
+ },
774
+ "phase.monitor-deploy.complete": {
775
+ rationale:
776
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported success.",
777
+ ingestVerb: "coordination.publish",
778
+ wakes: false,
779
+ entity: "ticket",
780
+ },
781
+ "phase.monitor-deploy.failed": {
782
+ rationale:
783
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported failure.",
784
+ ingestVerb: "coordination.publish",
785
+ wakes: false,
786
+ entity: "ticket",
787
+ },
788
+ "phase.monitor-deploy.failure-retracted": {
789
+ rationale:
790
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a previously-reported failure was retracted (corrected) — a real correction fact.",
791
+ ingestVerb: "coordination.publish",
792
+ wakes: false,
793
+ entity: "ticket",
794
+ },
795
+ "phase.monitor-deploy.orphan-detected": {
796
+ rationale:
797
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): an orphaned phase-agent worker was detected — a coordination fact (state discovered), not a sample.",
798
+ ingestVerb: "coordination.publish",
799
+ wakes: false,
800
+ entity: "ticket",
801
+ },
802
+ "phase.monitor-deploy.reclaim": {
803
+ rationale:
804
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): ownership of orphaned work was reclaimed by a new worker — an ownership transition akin to a lease reassignment.",
805
+ ingestVerb: "coordination.publish",
806
+ wakes: false,
807
+ entity: "ticket",
808
+ },
809
+ "phase.monitor-deploy.skipped": {
810
+ rationale:
811
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase decided to skip its normal action (e.g. no deploy event arrived) — a real terminal outcome, not a heartbeat.",
812
+ ingestVerb: "coordination.publish",
813
+ wakes: false,
814
+ entity: "ticket",
815
+ },
816
+ "phase.monitor-merge.abandoned": {
817
+ rationale:
818
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase's worker abandoned it — a lifecycle terminal fact.",
819
+ ingestVerb: "coordination.publish",
820
+ wakes: false,
821
+ entity: "ticket",
822
+ },
823
+ "phase.monitor-merge.boot-resume": {
824
+ rationale:
825
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted and resumed this phase — a real coordination fact about continuity across a restart.",
826
+ ingestVerb: "coordination.publish",
827
+ wakes: false,
828
+ entity: "ticket",
829
+ },
830
+ "phase.monitor-merge.boot-resume-gated": {
831
+ rationale:
832
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted but gated (did not immediately resume) this phase.",
833
+ ingestVerb: "coordination.publish",
834
+ wakes: false,
835
+ entity: "ticket",
836
+ },
837
+ "phase.monitor-merge.complete": {
838
+ rationale:
839
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported success.",
840
+ ingestVerb: "coordination.publish",
841
+ wakes: false,
842
+ entity: "ticket",
843
+ },
844
+ "phase.monitor-merge.escalated": {
845
+ rationale:
846
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase escalated to a human.",
847
+ ingestVerb: "coordination.publish",
848
+ wakes: { consumerClass: "host-channel" },
849
+ entity: "ticket",
850
+ },
851
+ "phase.monitor-merge.failed": {
852
+ rationale:
853
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported failure.",
854
+ ingestVerb: "coordination.publish",
855
+ wakes: false,
856
+ entity: "ticket",
857
+ },
858
+ "phase.monitor-merge.orphan-detected": {
859
+ rationale:
860
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): an orphaned phase-agent worker was detected — a coordination fact (state discovered), not a sample.",
861
+ ingestVerb: "coordination.publish",
862
+ wakes: false,
863
+ entity: "ticket",
864
+ },
865
+ "phase.monitor-merge.preempted": {
866
+ rationale:
867
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a higher-priority worker preempted this phase.",
868
+ ingestVerb: "coordination.publish",
869
+ wakes: false,
870
+ entity: "ticket",
871
+ },
872
+ "phase.monitor-merge.reclaim": {
873
+ rationale:
874
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): ownership of orphaned work was reclaimed by a new worker — an ownership transition akin to a lease reassignment.",
875
+ ingestVerb: "coordination.publish",
876
+ wakes: false,
877
+ entity: "ticket",
878
+ },
879
+ "phase.monitor-merge.resumed-after-preemption": {
880
+ rationale:
881
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase resumed after being preempted earlier — the paired fact to *.preempted.",
882
+ ingestVerb: "coordination.publish",
883
+ wakes: false,
884
+ entity: "ticket",
885
+ },
886
+ "phase.monitor-merge.revive": {
887
+ rationale:
888
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a parked phase was revived.",
889
+ ingestVerb: "coordination.publish",
890
+ wakes: false,
891
+ entity: "ticket",
892
+ },
893
+ "phase.orphan-pr.detected": {
894
+ rationale:
895
+ "A GitHub PR whose corresponding phase-agent worker directory no longer exists — a real orphaned-work detection fact worth replaying (the reclaim precondition), not a sample.",
896
+ ingestVerb: "coordination.publish",
897
+ wakes: { consumerClass: "dispatcher" },
898
+ entity: "pull_request",
899
+ },
900
+ "phase.plan.abandoned": {
901
+ rationale:
902
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase's worker abandoned it — a lifecycle terminal fact.",
903
+ ingestVerb: "coordination.publish",
904
+ wakes: false,
905
+ entity: "ticket",
906
+ },
907
+ "phase.plan.auto-rebased": {
908
+ rationale:
909
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase's branch was automatically rebased onto a moving base — a real, replay-worthy git-state fact.",
910
+ ingestVerb: "coordination.publish",
911
+ wakes: false,
912
+ entity: "ticket",
913
+ },
914
+ "phase.plan.boot-resume": {
915
+ rationale:
916
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted and resumed this phase — a real coordination fact about continuity across a restart.",
917
+ ingestVerb: "coordination.publish",
918
+ wakes: false,
919
+ entity: "ticket",
920
+ },
921
+ "phase.plan.complete": {
922
+ rationale:
923
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported success.",
924
+ ingestVerb: "coordination.publish",
925
+ wakes: false,
926
+ entity: "ticket",
927
+ },
928
+ "phase.plan.escalated": {
929
+ rationale:
930
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase escalated to a human.",
931
+ ingestVerb: "coordination.publish",
932
+ wakes: { consumerClass: "host-channel" },
933
+ entity: "ticket",
934
+ },
935
+ "phase.plan.failed": {
936
+ rationale:
937
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported failure.",
938
+ ingestVerb: "coordination.publish",
939
+ wakes: false,
940
+ entity: "ticket",
941
+ },
942
+ "phase.plan.orphan-detected": {
943
+ rationale:
944
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): an orphaned phase-agent worker was detected — a coordination fact (state discovered), not a sample.",
945
+ ingestVerb: "coordination.publish",
946
+ wakes: false,
947
+ entity: "ticket",
948
+ },
949
+ "phase.plan.park": {
950
+ rationale:
951
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase parked pending a blocker or human input — a real coordination state, not a heartbeat.",
952
+ ingestVerb: "coordination.publish",
953
+ wakes: false,
954
+ entity: "ticket",
955
+ },
956
+ "phase.plan.preempted": {
957
+ rationale:
958
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a higher-priority worker preempted this phase.",
959
+ ingestVerb: "coordination.publish",
960
+ wakes: false,
961
+ entity: "ticket",
962
+ },
963
+ "phase.plan.rebase-conflict-categorized": {
964
+ rationale:
965
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a real blocking rebase conflict was discovered and categorized during the phase.",
966
+ ingestVerb: "coordination.publish",
967
+ wakes: false,
968
+ entity: "ticket",
969
+ },
970
+ "phase.plan.rebase-conflict-stalled": {
971
+ rationale:
972
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase stalled on an unresolved rebase conflict.",
973
+ ingestVerb: "coordination.publish",
974
+ wakes: false,
975
+ entity: "ticket",
976
+ },
977
+ "phase.plan.reclaim": {
978
+ rationale:
979
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): ownership of orphaned work was reclaimed by a new worker — an ownership transition akin to a lease reassignment.",
980
+ ingestVerb: "coordination.publish",
981
+ wakes: false,
982
+ entity: "ticket",
983
+ },
984
+ "phase.plan.resumed-after-preemption": {
985
+ rationale:
986
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase resumed after being preempted earlier — the paired fact to *.preempted.",
987
+ ingestVerb: "coordination.publish",
988
+ wakes: false,
989
+ entity: "ticket",
990
+ },
991
+ "phase.plan.revive": {
992
+ rationale:
993
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a parked phase was revived.",
994
+ ingestVerb: "coordination.publish",
995
+ wakes: false,
996
+ entity: "ticket",
997
+ },
998
+ "phase.pr.boot-resume": {
999
+ rationale:
1000
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted and resumed this phase — a real coordination fact about continuity across a restart.",
1001
+ ingestVerb: "coordination.publish",
1002
+ wakes: false,
1003
+ entity: "ticket",
1004
+ },
1005
+ "phase.pr.boot-resume-gated": {
1006
+ rationale:
1007
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted but gated (did not immediately resume) this phase.",
1008
+ ingestVerb: "coordination.publish",
1009
+ wakes: false,
1010
+ entity: "ticket",
1011
+ },
1012
+ "phase.pr.complete": {
1013
+ rationale:
1014
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported success.",
1015
+ ingestVerb: "coordination.publish",
1016
+ wakes: false,
1017
+ entity: "ticket",
1018
+ },
1019
+ "phase.pr.failed": {
1020
+ rationale:
1021
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported failure.",
1022
+ ingestVerb: "coordination.publish",
1023
+ wakes: false,
1024
+ entity: "ticket",
1025
+ },
1026
+ "phase.pr.orphan-detected": {
1027
+ rationale:
1028
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): an orphaned phase-agent worker was detected — a coordination fact (state discovered), not a sample.",
1029
+ ingestVerb: "coordination.publish",
1030
+ wakes: false,
1031
+ entity: "ticket",
1032
+ },
1033
+ "phase.pr.preempted": {
1034
+ rationale:
1035
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a higher-priority worker preempted this phase.",
1036
+ ingestVerb: "coordination.publish",
1037
+ wakes: false,
1038
+ entity: "ticket",
1039
+ },
1040
+ "phase.pr.resumed-after-preemption": {
1041
+ rationale:
1042
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase resumed after being preempted earlier — the paired fact to *.preempted.",
1043
+ ingestVerb: "coordination.publish",
1044
+ wakes: false,
1045
+ entity: "ticket",
1046
+ },
1047
+ "phase.pr.revive": {
1048
+ rationale:
1049
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a parked phase was revived.",
1050
+ ingestVerb: "coordination.publish",
1051
+ wakes: false,
1052
+ entity: "ticket",
1053
+ },
1054
+ "phase.recovery-pass.abandoned": {
1055
+ rationale:
1056
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase's worker abandoned it — a lifecycle terminal fact.",
1057
+ ingestVerb: "coordination.publish",
1058
+ wakes: false,
1059
+ entity: "ticket",
1060
+ },
1061
+ "phase.recovery-pass.boot-resume": {
1062
+ rationale:
1063
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted and resumed this phase — a real coordination fact about continuity across a restart.",
1064
+ ingestVerb: "coordination.publish",
1065
+ wakes: false,
1066
+ entity: "ticket",
1067
+ },
1068
+ "phase.recovery-pass.boot-resume-gated": {
1069
+ rationale:
1070
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted but gated (did not immediately resume) this phase.",
1071
+ ingestVerb: "coordination.publish",
1072
+ wakes: false,
1073
+ entity: "ticket",
1074
+ },
1075
+ "phase.recovery-pass.complete": {
1076
+ rationale:
1077
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported success.",
1078
+ ingestVerb: "coordination.publish",
1079
+ wakes: false,
1080
+ entity: "ticket",
1081
+ },
1082
+ "phase.recovery-pass.failed": {
1083
+ rationale:
1084
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported failure.",
1085
+ ingestVerb: "coordination.publish",
1086
+ wakes: false,
1087
+ entity: "ticket",
1088
+ },
1089
+ "phase.recovery-pass.orphan-detected": {
1090
+ rationale:
1091
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): an orphaned phase-agent worker was detected — a coordination fact (state discovered), not a sample.",
1092
+ ingestVerb: "coordination.publish",
1093
+ wakes: false,
1094
+ entity: "ticket",
1095
+ },
1096
+ "phase.remediate.abandoned": {
1097
+ rationale:
1098
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase's worker abandoned it — a lifecycle terminal fact.",
1099
+ ingestVerb: "coordination.publish",
1100
+ wakes: false,
1101
+ entity: "ticket",
1102
+ },
1103
+ "phase.remediate.boot-resume": {
1104
+ rationale:
1105
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted and resumed this phase — a real coordination fact about continuity across a restart.",
1106
+ ingestVerb: "coordination.publish",
1107
+ wakes: false,
1108
+ entity: "ticket",
1109
+ },
1110
+ "phase.remediate.boot-resume-gated": {
1111
+ rationale:
1112
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted but gated (did not immediately resume) this phase.",
1113
+ ingestVerb: "coordination.publish",
1114
+ wakes: false,
1115
+ entity: "ticket",
1116
+ },
1117
+ "phase.remediate.complete": {
1118
+ rationale:
1119
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported success.",
1120
+ ingestVerb: "coordination.publish",
1121
+ wakes: false,
1122
+ entity: "ticket",
1123
+ },
1124
+ "phase.remediate.failed": {
1125
+ rationale:
1126
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported failure.",
1127
+ ingestVerb: "coordination.publish",
1128
+ wakes: false,
1129
+ entity: "ticket",
1130
+ },
1131
+ "phase.remediate.orphan-detected": {
1132
+ rationale:
1133
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): an orphaned phase-agent worker was detected — a coordination fact (state discovered), not a sample.",
1134
+ ingestVerb: "coordination.publish",
1135
+ wakes: false,
1136
+ entity: "ticket",
1137
+ },
1138
+ "phase.remediate.preempted": {
1139
+ rationale:
1140
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a higher-priority worker preempted this phase.",
1141
+ ingestVerb: "coordination.publish",
1142
+ wakes: false,
1143
+ entity: "ticket",
1144
+ },
1145
+ "phase.remediate.reclaim": {
1146
+ rationale:
1147
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): ownership of orphaned work was reclaimed by a new worker — an ownership transition akin to a lease reassignment.",
1148
+ ingestVerb: "coordination.publish",
1149
+ wakes: false,
1150
+ entity: "ticket",
1151
+ },
1152
+ "phase.remediate.resumed-after-preemption": {
1153
+ rationale:
1154
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase resumed after being preempted earlier — the paired fact to *.preempted.",
1155
+ ingestVerb: "coordination.publish",
1156
+ wakes: false,
1157
+ entity: "ticket",
1158
+ },
1159
+ "phase.rescue.dispatched": {
1160
+ rationale:
1161
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): work became eligible and was dispatched to a worker.",
1162
+ ingestVerb: "coordination.publish",
1163
+ wakes: { consumerClass: "dispatcher" },
1164
+ entity: "ticket",
1165
+ },
1166
+ "phase.rescue.escalated": {
1167
+ rationale:
1168
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase escalated to a human.",
1169
+ ingestVerb: "coordination.publish",
1170
+ wakes: { consumerClass: "host-channel" },
1171
+ entity: "ticket",
1172
+ },
1173
+ "phase.research.abandoned": {
1174
+ rationale:
1175
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase's worker abandoned it — a lifecycle terminal fact.",
1176
+ ingestVerb: "coordination.publish",
1177
+ wakes: false,
1178
+ entity: "ticket",
1179
+ },
1180
+ "phase.research.auto-rebased": {
1181
+ rationale:
1182
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase's branch was automatically rebased onto a moving base — a real, replay-worthy git-state fact.",
1183
+ ingestVerb: "coordination.publish",
1184
+ wakes: false,
1185
+ entity: "ticket",
1186
+ },
1187
+ "phase.research.boot-resume": {
1188
+ rationale:
1189
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted and resumed this phase — a real coordination fact about continuity across a restart.",
1190
+ ingestVerb: "coordination.publish",
1191
+ wakes: false,
1192
+ entity: "ticket",
1193
+ },
1194
+ "phase.research.complete": {
1195
+ rationale:
1196
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported success.",
1197
+ ingestVerb: "coordination.publish",
1198
+ wakes: false,
1199
+ entity: "ticket",
1200
+ },
1201
+ "phase.research.failed": {
1202
+ rationale:
1203
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported failure.",
1204
+ ingestVerb: "coordination.publish",
1205
+ wakes: false,
1206
+ entity: "ticket",
1207
+ },
1208
+ "phase.research.orphan-detected": {
1209
+ rationale:
1210
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): an orphaned phase-agent worker was detected — a coordination fact (state discovered), not a sample.",
1211
+ ingestVerb: "coordination.publish",
1212
+ wakes: false,
1213
+ entity: "ticket",
1214
+ },
1215
+ "phase.research.preempted": {
1216
+ rationale:
1217
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a higher-priority worker preempted this phase.",
1218
+ ingestVerb: "coordination.publish",
1219
+ wakes: false,
1220
+ entity: "ticket",
1221
+ },
1222
+ "phase.research.rebase-conflict-categorized": {
1223
+ rationale:
1224
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a real blocking rebase conflict was discovered and categorized during the phase.",
1225
+ ingestVerb: "coordination.publish",
1226
+ wakes: false,
1227
+ entity: "ticket",
1228
+ },
1229
+ "phase.research.rebase-conflict-stalled": {
1230
+ rationale:
1231
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase stalled on an unresolved rebase conflict.",
1232
+ ingestVerb: "coordination.publish",
1233
+ wakes: false,
1234
+ entity: "ticket",
1235
+ },
1236
+ "phase.research.resumed-after-preemption": {
1237
+ rationale:
1238
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase resumed after being preempted earlier — the paired fact to *.preempted.",
1239
+ ingestVerb: "coordination.publish",
1240
+ wakes: false,
1241
+ entity: "ticket",
1242
+ },
1243
+ "phase.review.abandoned": {
1244
+ rationale:
1245
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase's worker abandoned it — a lifecycle terminal fact.",
1246
+ ingestVerb: "coordination.publish",
1247
+ wakes: false,
1248
+ entity: "ticket",
1249
+ },
1250
+ "phase.review.auto-rebased": {
1251
+ rationale:
1252
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase's branch was automatically rebased onto a moving base — a real, replay-worthy git-state fact.",
1253
+ ingestVerb: "coordination.publish",
1254
+ wakes: false,
1255
+ entity: "ticket",
1256
+ },
1257
+ "phase.review.boot-resume": {
1258
+ rationale:
1259
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted and resumed this phase — a real coordination fact about continuity across a restart.",
1260
+ ingestVerb: "coordination.publish",
1261
+ wakes: false,
1262
+ entity: "ticket",
1263
+ },
1264
+ "phase.review.boot-resume-gated": {
1265
+ rationale:
1266
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted but gated (did not immediately resume) this phase.",
1267
+ ingestVerb: "coordination.publish",
1268
+ wakes: false,
1269
+ entity: "ticket",
1270
+ },
1271
+ "phase.review.complete": {
1272
+ rationale:
1273
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported success.",
1274
+ ingestVerb: "coordination.publish",
1275
+ wakes: false,
1276
+ entity: "ticket",
1277
+ },
1278
+ "phase.review.escalated": {
1279
+ rationale:
1280
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase escalated to a human.",
1281
+ ingestVerb: "coordination.publish",
1282
+ wakes: { consumerClass: "host-channel" },
1283
+ entity: "ticket",
1284
+ },
1285
+ "phase.review.failed": {
1286
+ rationale:
1287
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported failure.",
1288
+ ingestVerb: "coordination.publish",
1289
+ wakes: false,
1290
+ entity: "ticket",
1291
+ },
1292
+ "phase.review.orphan-detected": {
1293
+ rationale:
1294
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): an orphaned phase-agent worker was detected — a coordination fact (state discovered), not a sample.",
1295
+ ingestVerb: "coordination.publish",
1296
+ wakes: false,
1297
+ entity: "ticket",
1298
+ },
1299
+ "phase.review.preempted": {
1300
+ rationale:
1301
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a higher-priority worker preempted this phase.",
1302
+ ingestVerb: "coordination.publish",
1303
+ wakes: false,
1304
+ entity: "ticket",
1305
+ },
1306
+ "phase.review.rebase-conflict-categorized": {
1307
+ rationale:
1308
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a real blocking rebase conflict was discovered and categorized during the phase.",
1309
+ ingestVerb: "coordination.publish",
1310
+ wakes: false,
1311
+ entity: "ticket",
1312
+ },
1313
+ "phase.review.rebase-conflict-stalled": {
1314
+ rationale:
1315
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase stalled on an unresolved rebase conflict.",
1316
+ ingestVerb: "coordination.publish",
1317
+ wakes: false,
1318
+ entity: "ticket",
1319
+ },
1320
+ "phase.review.reclaim": {
1321
+ rationale:
1322
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): ownership of orphaned work was reclaimed by a new worker — an ownership transition akin to a lease reassignment.",
1323
+ ingestVerb: "coordination.publish",
1324
+ wakes: false,
1325
+ entity: "ticket",
1326
+ },
1327
+ "phase.review.resumed-after-preemption": {
1328
+ rationale:
1329
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase resumed after being preempted earlier — the paired fact to *.preempted.",
1330
+ ingestVerb: "coordination.publish",
1331
+ wakes: false,
1332
+ entity: "ticket",
1333
+ },
1334
+ "phase.review.revive": {
1335
+ rationale:
1336
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a parked phase was revived.",
1337
+ ingestVerb: "coordination.publish",
1338
+ wakes: false,
1339
+ entity: "ticket",
1340
+ },
1341
+ "phase.teardown.boot-resume": {
1342
+ rationale:
1343
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted and resumed this phase — a real coordination fact about continuity across a restart.",
1344
+ ingestVerb: "coordination.publish",
1345
+ wakes: false,
1346
+ entity: "ticket",
1347
+ },
1348
+ "phase.teardown.boot-resume-gated": {
1349
+ rationale:
1350
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted but gated (did not immediately resume) this phase.",
1351
+ ingestVerb: "coordination.publish",
1352
+ wakes: false,
1353
+ entity: "ticket",
1354
+ },
1355
+ "phase.teardown.complete": {
1356
+ rationale:
1357
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported success.",
1358
+ ingestVerb: "coordination.publish",
1359
+ wakes: false,
1360
+ entity: "ticket",
1361
+ },
1362
+ "phase.teardown.failed": {
1363
+ rationale:
1364
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported failure.",
1365
+ ingestVerb: "coordination.publish",
1366
+ wakes: false,
1367
+ entity: "ticket",
1368
+ },
1369
+ "phase.teardown.orphan-detected": {
1370
+ rationale:
1371
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): an orphaned phase-agent worker was detected — a coordination fact (state discovered), not a sample.",
1372
+ ingestVerb: "coordination.publish",
1373
+ wakes: false,
1374
+ entity: "ticket",
1375
+ },
1376
+ "phase.teardown.reclaim": {
1377
+ rationale:
1378
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): ownership of orphaned work was reclaimed by a new worker — an ownership transition akin to a lease reassignment.",
1379
+ ingestVerb: "coordination.publish",
1380
+ wakes: false,
1381
+ entity: "ticket",
1382
+ },
1383
+ "phase.triage.abandoned": {
1384
+ rationale:
1385
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase's worker abandoned it — a lifecycle terminal fact.",
1386
+ ingestVerb: "coordination.publish",
1387
+ wakes: false,
1388
+ entity: "ticket",
1389
+ },
1390
+ "phase.triage.boot-resume": {
1391
+ rationale:
1392
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted and resumed this phase — a real coordination fact about continuity across a restart.",
1393
+ ingestVerb: "coordination.publish",
1394
+ wakes: false,
1395
+ entity: "ticket",
1396
+ },
1397
+ "phase.triage.complete": {
1398
+ rationale:
1399
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported success.",
1400
+ ingestVerb: "coordination.publish",
1401
+ wakes: false,
1402
+ entity: "ticket",
1403
+ },
1404
+ "phase.triage.escalated": {
1405
+ rationale:
1406
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase escalated to a human.",
1407
+ ingestVerb: "coordination.publish",
1408
+ wakes: { consumerClass: "host-channel" },
1409
+ entity: "ticket",
1410
+ },
1411
+ "phase.triage.failed": {
1412
+ rationale:
1413
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported failure.",
1414
+ ingestVerb: "coordination.publish",
1415
+ wakes: false,
1416
+ entity: "ticket",
1417
+ },
1418
+ "phase.triage.failure-retracted": {
1419
+ rationale:
1420
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a previously-reported failure was retracted (corrected) — a real correction fact.",
1421
+ ingestVerb: "coordination.publish",
1422
+ wakes: false,
1423
+ entity: "ticket",
1424
+ },
1425
+ "phase.triage.linear-transition": {
1426
+ rationale:
1427
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase performed a real Linear ticket-state transition as part of its own execution.",
1428
+ ingestVerb: "coordination.publish",
1429
+ wakes: false,
1430
+ entity: "ticket",
1431
+ },
1432
+ "phase.triage.orphan-detected": {
1433
+ rationale:
1434
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): an orphaned phase-agent worker was detected — a coordination fact (state discovered), not a sample.",
1435
+ ingestVerb: "coordination.publish",
1436
+ wakes: false,
1437
+ entity: "ticket",
1438
+ },
1439
+ "phase.triage.revive": {
1440
+ rationale:
1441
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a parked phase was revived.",
1442
+ ingestVerb: "coordination.publish",
1443
+ wakes: false,
1444
+ entity: "ticket",
1445
+ },
1446
+ "phase.verify.abandoned": {
1447
+ rationale:
1448
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase's worker abandoned it — a lifecycle terminal fact.",
1449
+ ingestVerb: "coordination.publish",
1450
+ wakes: false,
1451
+ entity: "ticket",
1452
+ },
1453
+ "phase.verify.auto-rebased": {
1454
+ rationale:
1455
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase's branch was automatically rebased onto a moving base — a real, replay-worthy git-state fact.",
1456
+ ingestVerb: "coordination.publish",
1457
+ wakes: false,
1458
+ entity: "ticket",
1459
+ },
1460
+ "phase.verify.boot-resume": {
1461
+ rationale:
1462
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted and resumed this phase — a real coordination fact about continuity across a restart.",
1463
+ ingestVerb: "coordination.publish",
1464
+ wakes: false,
1465
+ entity: "ticket",
1466
+ },
1467
+ "phase.verify.boot-resume-gated": {
1468
+ rationale:
1469
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the daemon restarted but gated (did not immediately resume) this phase.",
1470
+ ingestVerb: "coordination.publish",
1471
+ wakes: false,
1472
+ entity: "ticket",
1473
+ },
1474
+ "phase.verify.complete": {
1475
+ rationale:
1476
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported success.",
1477
+ ingestVerb: "coordination.publish",
1478
+ wakes: false,
1479
+ entity: "ticket",
1480
+ },
1481
+ "phase.verify.failed": {
1482
+ rationale:
1483
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported failure.",
1484
+ ingestVerb: "coordination.publish",
1485
+ wakes: false,
1486
+ entity: "ticket",
1487
+ },
1488
+ "phase.verify.orphan-detected": {
1489
+ rationale:
1490
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): an orphaned phase-agent worker was detected — a coordination fact (state discovered), not a sample.",
1491
+ ingestVerb: "coordination.publish",
1492
+ wakes: false,
1493
+ entity: "ticket",
1494
+ },
1495
+ "phase.verify.preempted": {
1496
+ rationale:
1497
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a higher-priority worker preempted this phase.",
1498
+ ingestVerb: "coordination.publish",
1499
+ wakes: false,
1500
+ entity: "ticket",
1501
+ },
1502
+ "phase.verify.rebase-conflict-categorized": {
1503
+ rationale:
1504
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a real blocking rebase conflict was discovered and categorized during the phase.",
1505
+ ingestVerb: "coordination.publish",
1506
+ wakes: false,
1507
+ entity: "ticket",
1508
+ },
1509
+ "phase.verify.rebase-conflict-stalled": {
1510
+ rationale:
1511
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase stalled on an unresolved rebase conflict.",
1512
+ ingestVerb: "coordination.publish",
1513
+ wakes: false,
1514
+ entity: "ticket",
1515
+ },
1516
+ "phase.verify.resumed-after-preemption": {
1517
+ rationale:
1518
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase resumed after being preempted earlier — the paired fact to *.preempted.",
1519
+ ingestVerb: "coordination.publish",
1520
+ wakes: false,
1521
+ entity: "ticket",
1522
+ },
1523
+ "phase.verify.revive": {
1524
+ rationale:
1525
+ "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): a parked phase was revived.",
1526
+ ingestVerb: "coordination.publish",
1527
+ wakes: false,
1528
+ entity: "ticket",
1529
+ },
1530
+ "plugin.checkout.deps-audit-inconclusive": {
1531
+ rationale:
1532
+ "A dependency audit during plugin checkout could not reach a verdict — a real, low-volume fact worth recording.",
1533
+ ingestVerb: "coordination.publish",
1534
+ wakes: false,
1535
+ },
1536
+ "plugin.checkout.refresh-failed": {
1537
+ rationale: "A plugin checkout refresh failed — a real operational failure fact.",
1538
+ ingestVerb: "coordination.publish",
1539
+ wakes: false,
1540
+ },
1541
+ "plugin.checkout.updated": {
1542
+ rationale:
1543
+ "A plugin checkout was updated — a real distribution-health fact (which version each host is running).",
1544
+ ingestVerb: "coordination.publish",
1545
+ wakes: false,
1546
+ },
1547
+ "pr.merged.cleanup-failed": {
1548
+ rationale:
1549
+ "A post-merge cleanup step failed for a specific PR — an actionable fact an operator or retry job must eventually address. ⚠️ Volume (6,529/mo) is high enough to warrant watching for a retry-storm shape in a future census; kept durable pending that evidence.",
1550
+ ingestVerb: "coordination.publish",
1551
+ wakes: false,
1552
+ entity: "pull_request",
1553
+ },
1554
+ "recovery.deferred": {
1555
+ rationale:
1556
+ "A real, ENACTED deferral — much lower volume (2,894/mo) than recovery.would-defer's 505k dry-run evaluations, confirming this is the actual decision, not the counterfactual.",
1557
+ ingestVerb: "coordination.publish",
1558
+ wakes: false,
1559
+ entity: "ticket",
1560
+ },
1561
+ "recovery.done-applied": {
1562
+ rationale:
1563
+ "A real recovery action was applied — ADR-0039's own example, 'an arbiter made a decision', enacted.",
1564
+ ingestVerb: "coordination.publish",
1565
+ wakes: false,
1566
+ entity: "ticket",
1567
+ },
1568
+ "recovery.done-applied-with-open-pr": {
1569
+ rationale:
1570
+ "Same enacted-decision fact as recovery.done-applied, with an open PR still pending.",
1571
+ ingestVerb: "coordination.publish",
1572
+ wakes: false,
1573
+ entity: "ticket",
1574
+ },
1575
+ "recovery.escalated": {
1576
+ rationale:
1577
+ "A real, enacted escalation to a human — the low-volume (104/mo) counterpart to recovery.would-escalate's 26k dry-run evaluations.",
1578
+ ingestVerb: "coordination.publish",
1579
+ wakes: { consumerClass: "host-channel" },
1580
+ entity: "ticket",
1581
+ },
1582
+ "recovery.fix-failed": {
1583
+ rationale:
1584
+ "A real, enacted fix attempt that failed — very low volume (2/mo), a genuine outcome fact.",
1585
+ ingestVerb: "coordination.publish",
1586
+ wakes: false,
1587
+ entity: "ticket",
1588
+ },
1589
+ "recovery.fixed": {
1590
+ rationale:
1591
+ "A real, enacted fix that succeeded — the low-volume (46/mo) counterpart to recovery.would-fix.",
1592
+ ingestVerb: "coordination.publish",
1593
+ wakes: false,
1594
+ entity: "ticket",
1595
+ },
1596
+ "recovery.verdict": {
1597
+ rationale:
1598
+ "A real, enacted recovery-cycle outcome — 30/mo, orders of magnitude below recovery.decision's 535k per-pass evaluations, confirming this is the rare meaningful verdict, not the routine scan.",
1599
+ ingestVerb: "coordination.publish",
1600
+ wakes: false,
1601
+ entity: "ticket",
1602
+ },
1603
+ "session.ended": {
1604
+ rationale: "An agent session ended — a real lifecycle boundary fact.",
1605
+ ingestVerb: "coordination.publish",
1606
+ wakes: false,
1607
+ },
1608
+ "session.phase": {
1609
+ rationale:
1610
+ "A phase transition within an agent session — very low volume (8/mo), a real discrete fact.",
1611
+ ingestVerb: "coordination.publish",
1612
+ wakes: false,
1613
+ },
1614
+ "session.started": {
1615
+ rationale: "An agent session started — the paired fact to session.ended.",
1616
+ ingestVerb: "coordination.publish",
1617
+ wakes: false,
1618
+ },
1619
+ "stack.reload.complete": {
1620
+ rationale:
1621
+ "The dev stack finished reloading — a real, replay-worthy operational lifecycle fact.",
1622
+ ingestVerb: "coordination.publish",
1623
+ wakes: false,
1624
+ },
1625
+ "stack.reload.degraded": {
1626
+ rationale:
1627
+ "A stack reload completed in a degraded state — very low volume (3/mo), a genuine fact worth an audit trail.",
1628
+ ingestVerb: "coordination.publish",
1629
+ wakes: false,
1630
+ },
1631
+ "stack.reload.started": {
1632
+ rationale: "The dev stack began reloading — the paired fact to stack.reload.complete.",
1633
+ ingestVerb: "coordination.publish",
1634
+ wakes: false,
1635
+ },
1636
+ "thoughts.sync.failed.verify": {
1637
+ rationale:
1638
+ "A thoughts-repo sync failure during the verify phase — low volume (9/mo), a real operational failure fact worth history.",
1639
+ ingestVerb: "coordination.publish",
1640
+ wakes: false,
1641
+ },
1642
+ "ticket.completion.declared": {
1643
+ rationale:
1644
+ "A ticket was declared complete — one of the most consequential coordination facts in the whole system.",
1645
+ ingestVerb: "coordination.publish",
1646
+ wakes: { consumerClass: "dispatcher" },
1647
+ entity: "ticket",
1648
+ },
1649
+ "ticket.escalated": {
1650
+ rationale:
1651
+ "A ticket was escalated to a human — ADR-0039's own 'a human answer was received' example, the request side.",
1652
+ ingestVerb: "coordination.publish",
1653
+ wakes: { consumerClass: "host-channel" },
1654
+ entity: "ticket",
1655
+ },
1656
+ "unstuck.escalated": {
1657
+ rationale:
1658
+ "An unstuck-detection escalation to a human — low volume (16/mo), a real coordination fact.",
1659
+ ingestVerb: "coordination.publish",
1660
+ wakes: { consumerClass: "host-channel" },
1661
+ },
1662
+ "worker.memory.warn": {
1663
+ rationale:
1664
+ "A worker crossed a memory WARNING threshold — a discrete boundary-crossing fact, distinct from the raw worker.memory.sampled gauge.",
1665
+ ingestVerb: "coordination.publish",
1666
+ wakes: false,
1667
+ },
1668
+ "worker.session.resumed": {
1669
+ rationale:
1670
+ "A phase worker's session resumed — a real lifecycle fact, matches ADR-0039's 'a runner reported an outcome' family.",
1671
+ ingestVerb: "coordination.publish",
1672
+ wakes: false,
1673
+ },
1674
+ "worker.session.started": {
1675
+ rationale: "A phase worker's session started.",
1676
+ ingestVerb: "coordination.publish",
1677
+ wakes: false,
1678
+ },
1679
+ "worker.session.stopped": {
1680
+ rationale: "A phase worker's session stopped — the paired fact to worker.session.started.",
1681
+ ingestVerb: "coordination.publish",
1682
+ wakes: false,
1683
+ },
1684
+ "worker.transition": {
1685
+ rationale:
1686
+ "A worker's state-machine transition — the general coordination fact ADR-0039's phase-lifecycle bullet generalizes to worker level.",
1687
+ ingestVerb: "coordination.publish",
1688
+ wakes: false,
1689
+ },
1690
+ "worktree.salvage.created": {
1691
+ rationale:
1692
+ "A worktree was actually salvaged from an interrupted run — a real recovery action, the low-volume (1,448/mo) counterpart to worktree.salvage.skipped's 14k no-op checks.",
1693
+ ingestVerb: "coordination.publish",
1694
+ wakes: false,
1695
+ },
1696
+ } as const satisfies Record<string, DurableEventSpec>;
1697
+
1698
+ /** Why a heartbeat-shaped signal updates mutable NOW instead of the immutable history, and which
1699
+ * durable type names the boundary-crossing it eventually produces. */
1700
+ export interface CurrentStateEventSpec {
1701
+ /** Why this UPDATES mutable NOW in the DO rather than appending to history (ADR-0039 §2). */
1702
+ rationale: string;
1703
+ /** The durable type(s) a boundary crossing of this signal produces (may be aspirational — Finding
1704
+ * 4 found NOTHING filters or derives a boundary event from a heartbeat today; this is the target
1705
+ * a future derivation is typed against, and where a real observed boundary fact already exists in
1706
+ * durableEventTypes, this names it). */
1707
+ boundaryEvents: string[];
1708
+ }
1709
+
1710
+ /**
1711
+ * Heartbeat-shaped: these UPDATE mutable NOW in the DO and emit a durable event only when state
1712
+ * crosses a boundary (node.online / node.offline / lease.expired). Measured (Finding 4):
1713
+ * monitor.heartbeat 66,669 + node.heartbeat 62,426 + broker.daemon.heartbeat 33,478 lines in the
1714
+ * committed August census alone — 162,573 lines/mo that would otherwise flood the durable history
1715
+ * for zero replay value.
1716
+ */
1717
+ export const currentStateEventTypes = {
1718
+ "broker.daemon.heartbeat": {
1719
+ rationale:
1720
+ "The coordination broker daemon's own liveness pulse — updates mutable NOW; startup/shutdown are the durable boundary facts.",
1721
+ boundaryEvents: ["broker.daemon.startup", "broker.daemon.shutdown"],
1722
+ },
1723
+ "monitor.heartbeat": {
1724
+ rationale:
1725
+ "The per-host monitor daemon's liveness pulse — updates mutable NOW; only a fleet.health boundary crossing is durable.",
1726
+ boundaryEvents: ["fleet.health.degraded", "fleet.health.recovered"],
1727
+ },
1728
+ "node.heartbeat": {
1729
+ rationale:
1730
+ "A worker node's liveness pulse — updates mutable NOW; a node.boot is the durable boundary fact this crossing would produce.",
1731
+ boundaryEvents: ["node.boot"],
1732
+ },
1733
+ } as const satisfies Record<string, CurrentStateEventSpec>;
1734
+
1735
+ /** Why a type is excluded from the durable contract — the fact a consumer would lose if this reason
1736
+ * is wrong, per the phase-3 producer-inventory bar ("names the failure someone would notice"). */
1737
+ export interface TelemetryEventSpec {
1738
+ reason: string;
1739
+ }
1740
+
1741
+ /**
1742
+ * ⛔ EXILED from the durable contract (ADR-0039 binding condition 1). 73 types, the volume-dominant
1743
+ * side of Finding 3's split (92.3% of August's named lines were telemetry-shaped in the plan's
1744
+ * measurement) — ticks, gauges, process samples, read traces, forwarding lag, "would-*" dry-run
1745
+ * counterfactuals, and retry-storm noise that collapses to a single durable boundary fact elsewhere
1746
+ * in this registry (e.g. linear.write.proxy.failed's 140k+ lines/mo collapses to the ONE durable
1747
+ * linear.label.retry-exhausted terminal fact).
1748
+ */
1749
+ export const telemetryEventTypes = {
1750
+ "account.ratelimit.sampled": {
1751
+ reason: "A periodic provider rate-limit budget reading — a gauge, not a state transition.",
1752
+ },
1753
+ "account.ratelimit.unsampled": {
1754
+ reason:
1755
+ "The raw (pre-sampling) rate-limit reading behind account.ratelimit.sampled — same gauge family.",
1756
+ },
1757
+ "catalyst.linear.read": {
1758
+ reason:
1759
+ "A Linear API read trace — ADR-0039's own telemetry example ('read traces'). By far the single largest type in the census (1.36M lines/mo); replaying every poll would archive the poll loop, not the coordination history.",
1760
+ },
1761
+ "catalyst.observability.forward-dropped": {
1762
+ reason:
1763
+ "A single forward-attempt drop in the observability pipe — same family as forward-failed/forward-lag.",
1764
+ },
1765
+ "catalyst.observability.forward-failed": {
1766
+ reason:
1767
+ "A single forward-attempt failure in the observability pipe — an internal delivery retry signal, not a coordination fact.",
1768
+ },
1769
+ "catalyst.observability.forward-lag": {
1770
+ reason: "Forwarding-lag sample — ADR-0039's own telemetry example ('forwarding lag') verbatim.",
1771
+ },
1772
+ "catalyst.replica.dep-skew-would-restart": {
1773
+ reason:
1774
+ "A 'would-*' counterfactual: what the replica would do about dependency skew, not an action it took. Dry-run diagnostics are excluded from the durable contract (Assumption 4).",
1775
+ },
1776
+ "catalyst.replica.read-fallback": {
1777
+ reason:
1778
+ "A replica read falling back to a secondary path — an internal routing diagnostic, not a ticket/phase coordination fact.",
1779
+ },
1780
+ "catalyst.service.health": { reason: "A periodic service health-check gauge." },
1781
+ "cloud-feed.would-dispatch": {
1782
+ reason:
1783
+ "A 'would-*' counterfactual dispatch evaluation — the dry-run analogue of phase.dispatch.requested, never an actual dispatch.",
1784
+ },
1785
+ "delegate.would-route": {
1786
+ reason: "A 'would-*' counterfactual routing evaluation — never an actual delegation.",
1787
+ },
1788
+ "execution-core.sdk.child-pid-inconclusive": {
1789
+ reason:
1790
+ "A diagnostic edge case in child-process liveness detection — a single observed occurrence, not a coordination fact.",
1791
+ },
1792
+ "execution-core.sdk.overloaded": {
1793
+ reason:
1794
+ "A provider-overloaded response from the model API. AGENTS.md treats this as ONE fleet-wide capacity signal, not a per-ticket coordination fact worth individual replay.",
1795
+ },
1796
+ "execution-core.sdk.phase-turns": {
1797
+ reason:
1798
+ "A per-turn counter sample of the agent SDK loop — a gauge, not a discrete coordination fact.",
1799
+ },
1800
+ "github-feed.would-dispatch": {
1801
+ reason:
1802
+ "Same 'would-*' counterfactual shape as cloud-feed.would-dispatch, for the GitHub-sourced feed.",
1803
+ },
1804
+ "host.metrics.sampled": {
1805
+ reason:
1806
+ "A periodic host resource-metrics sample — same 'process samples' family as host.process.sampled.",
1807
+ },
1808
+ "host.process.sampled": {
1809
+ reason: "ADR-0039's own telemetry example ('process samples') verbatim.",
1810
+ },
1811
+ "infra-retry.retry": {
1812
+ reason: "The retry attempt itself in the same backoff loop as infra-retry.wait.",
1813
+ },
1814
+ "infra-retry.wait": {
1815
+ reason:
1816
+ "A retry/backoff loop's wait tick — 42k lines/mo from a single backoff loop, the same retry-storm shape as linear.write.proxy.failed.",
1817
+ },
1818
+ "janitor.signals.gc": {
1819
+ reason:
1820
+ "Periodic process/worktree housekeeping sweep — same generic-GC shape as the phase.*.reap-* family, not a ticket/phase coordination fact.",
1821
+ },
1822
+ "janitor.worktree.deferred": {
1823
+ reason:
1824
+ "Periodic process/worktree housekeeping sweep — same generic-GC shape as the phase.*.reap-* family, not a ticket/phase coordination fact.",
1825
+ },
1826
+ "jobs.gc.swept": {
1827
+ reason:
1828
+ "Periodic process/worktree housekeeping sweep — same generic-GC shape as the phase.*.reap-* family, not a ticket/phase coordination fact.",
1829
+ },
1830
+ "linear.write.proxy.failed": {
1831
+ reason:
1832
+ "Finding 3's own quantified retry-storm example: 140k+ lines/mo from ONE boundary condition (the write-proxy backing off and retrying). linear.label.retry-exhausted is the durable terminal fact this collapses to.",
1833
+ },
1834
+ "linear.write.proxy.would-write": {
1835
+ reason:
1836
+ "A 'would-*' counterfactual write evaluation — never an actual write (linear.write.proxy.applied is the real one).",
1837
+ },
1838
+ "malformed.empty-event-name": {
1839
+ reason:
1840
+ "A producer bug: 14 lines shipped with an empty `event.name`. Not a real type — flagged in the phase-3 producer inventory as a defect for the sibling repo to fix (a JSONL writer must never emit an unnamed line), not something the durable registry can carry forward as a name.",
1841
+ },
1842
+ "orphans.reap-requested": {
1843
+ reason:
1844
+ "Phase-agent worker-directory garbage collection. phase.terminal.reap-requested alone is 10,015 lines/mo — a periodic sweep re-requesting cleanup of already-terminal workers, not a discrete coordination fact worth replay.",
1845
+ },
1846
+ "phase.abort.reap-complete": {
1847
+ reason:
1848
+ "Phase-agent worker-directory garbage collection. phase.terminal.reap-requested alone is 10,015 lines/mo — a periodic sweep re-requesting cleanup of already-terminal workers, not a discrete coordination fact worth replay.",
1849
+ },
1850
+ "phase.abort.reap-requested": {
1851
+ reason:
1852
+ "Phase-agent worker-directory garbage collection. phase.terminal.reap-requested alone is 10,015 lines/mo — a periodic sweep re-requesting cleanup of already-terminal workers, not a discrete coordination fact worth replay.",
1853
+ },
1854
+ "phase.predecessor.reap-complete": {
1855
+ reason:
1856
+ "Phase-agent worker-directory garbage collection. phase.terminal.reap-requested alone is 10,015 lines/mo — a periodic sweep re-requesting cleanup of already-terminal workers, not a discrete coordination fact worth replay.",
1857
+ },
1858
+ "phase.predecessor.reap-requested": {
1859
+ reason:
1860
+ "Phase-agent worker-directory garbage collection. phase.terminal.reap-requested alone is 10,015 lines/mo — a periodic sweep re-requesting cleanup of already-terminal workers, not a discrete coordination fact worth replay.",
1861
+ },
1862
+ "phase.reclaim.reap-requested": {
1863
+ reason:
1864
+ "Phase-agent worker-directory garbage collection. phase.terminal.reap-requested alone is 10,015 lines/mo — a periodic sweep re-requesting cleanup of already-terminal workers, not a discrete coordination fact worth replay.",
1865
+ },
1866
+ "phase.reconcile.reap-complete": {
1867
+ reason:
1868
+ "Phase-agent worker-directory garbage collection. phase.terminal.reap-requested alone is 10,015 lines/mo — a periodic sweep re-requesting cleanup of already-terminal workers, not a discrete coordination fact worth replay.",
1869
+ },
1870
+ "phase.reconcile.reap-requested": {
1871
+ reason:
1872
+ "Phase-agent worker-directory garbage collection. phase.terminal.reap-requested alone is 10,015 lines/mo — a periodic sweep re-requesting cleanup of already-terminal workers, not a discrete coordination fact worth replay.",
1873
+ },
1874
+ "phase.rescue.escalation-unconfirmed": {
1875
+ reason:
1876
+ "1,088 lines/mo against phase.rescue.escalated's single occurrence — the volume gap indicates this re-emits the SAME 'still unconfirmed' status on every retry pass rather than recording a discrete fact.",
1877
+ },
1878
+ "phase.revive.reap-requested": {
1879
+ reason:
1880
+ "Phase-agent worker-directory garbage collection. phase.terminal.reap-requested alone is 10,015 lines/mo — a periodic sweep re-requesting cleanup of already-terminal workers, not a discrete coordination fact worth replay.",
1881
+ },
1882
+ "phase.scheduler.autotune-gauge.execution-core": {
1883
+ reason: "Named 'gauge' — ADR-0039's own telemetry example, verbatim category.",
1884
+ },
1885
+ "phase.scheduler.cooldown-gc": {
1886
+ reason:
1887
+ "A periodic garbage-collection sweep of scheduler cooldown state — housekeeping, not a coordination fact.",
1888
+ },
1889
+ "phase.scheduler.parallelism-adjusted.execution-core": {
1890
+ reason:
1891
+ "The scheduler's own resource-tuning adjustment — useful for capacity-planning dashboards, not for replaying ticket/phase coordination history.",
1892
+ },
1893
+ "phase.scheduler.parallelism-sampled.execution-core": {
1894
+ reason: "Named 'sampled' — ADR-0039's own telemetry example, verbatim category.",
1895
+ },
1896
+ "phase.supersede.reap-requested": {
1897
+ reason:
1898
+ "Phase-agent worker-directory garbage collection. phase.terminal.reap-requested alone is 10,015 lines/mo — a periodic sweep re-requesting cleanup of already-terminal workers, not a discrete coordination fact worth replay.",
1899
+ },
1900
+ "phase.terminal.reap-complete": {
1901
+ reason:
1902
+ "Phase-agent worker-directory garbage collection. phase.terminal.reap-requested alone is 10,015 lines/mo — a periodic sweep re-requesting cleanup of already-terminal workers, not a discrete coordination fact worth replay.",
1903
+ },
1904
+ "phase.terminal.reap-requested": {
1905
+ reason:
1906
+ "Phase-agent worker-directory garbage collection. phase.terminal.reap-requested alone is 10,015 lines/mo — a periodic sweep re-requesting cleanup of already-terminal workers, not a discrete coordination fact worth replay.",
1907
+ },
1908
+ "phase.yield.reap-requested": {
1909
+ reason:
1910
+ "Phase-agent worker-directory garbage collection. phase.terminal.reap-requested alone is 10,015 lines/mo — a periodic sweep re-requesting cleanup of already-terminal workers, not a discrete coordination fact worth replay.",
1911
+ },
1912
+ "plugin.checkout.lag": {
1913
+ reason:
1914
+ "A single observed timing-lag sample during plugin checkout — the 'forwarding lag' telemetry shape, not a discrete fact.",
1915
+ },
1916
+ "proc-orphans.reap-requested": {
1917
+ reason:
1918
+ "Phase-agent worker-directory garbage collection. phase.terminal.reap-requested alone is 10,015 lines/mo — a periodic sweep re-requesting cleanup of already-terminal workers, not a discrete coordination fact worth replay.",
1919
+ },
1920
+ "proc-orphans.spared": {
1921
+ reason:
1922
+ "Periodic process/worktree housekeeping sweep — same generic-GC shape as the phase.*.reap-* family, not a ticket/phase coordination fact.",
1923
+ },
1924
+ "proc-orphans.would-reap": {
1925
+ reason:
1926
+ "Periodic process/worktree housekeeping sweep — same generic-GC shape as the phase.*.reap-* family, not a ticket/phase coordination fact.",
1927
+ },
1928
+ "recovery.board-scan": {
1929
+ reason:
1930
+ "The recovery loop's periodic board-scan pass — same sweep-tick family as recovery.tick.",
1931
+ },
1932
+ "recovery.decision": {
1933
+ reason:
1934
+ "535k lines/mo — near-identical volume to recovery.tick, confirming this logs the sweep's per-ticket evaluation on EVERY pass regardless of outcome, not a rare meaningful arbiter decision. recovery.verdict is the much lower-volume (30/mo) durable analogue for an actually-enacted outcome.",
1935
+ },
1936
+ "recovery.skipped": {
1937
+ reason:
1938
+ "Part of the recovery.skipped.* family: The bare fallback skip marker with no reason suffix (1 line) — same family.",
1939
+ },
1940
+ "recovery.skipped.already-shipped-pr-3750-merged-head-matches-origin-main": {
1941
+ reason:
1942
+ "Part of the recovery.skipped.* family: Same free-text-reason-in-type defect as the pr-1071 sibling, for a different PR — flagged for phase-3.",
1943
+ },
1944
+ "recovery.skipped.artifact-not-gate-visible": {
1945
+ reason:
1946
+ "Part of the recovery.skipped.* family: A recurring pre-condition check ('is the artifact visible to the gate yet') re-logged on every sweep pass until it resolves — 14,710 lines/mo.",
1947
+ },
1948
+ "recovery.skipped.cluster-fence-unverified": {
1949
+ reason:
1950
+ "Part of the recovery.skipped.* family: A recurring pre-condition check re-logged every sweep pass — 12,181 lines/mo.",
1951
+ },
1952
+ "recovery.skipped.continue-failed": {
1953
+ reason:
1954
+ "Part of the recovery.skipped.* family: A recurring retry-outcome check re-logged every sweep pass — 14,482 lines/mo.",
1955
+ },
1956
+ "recovery.skipped.ended-without-declaration": {
1957
+ reason:
1958
+ "Part of the recovery.skipped.* family: A recurring pre-condition check re-logged every sweep pass — 19,750 lines/mo.",
1959
+ },
1960
+ "recovery.skipped.mid-flight-replan-needed": {
1961
+ reason:
1962
+ "Part of the recovery.skipped.* family: A recurring pre-condition check, lower volume (48/mo) but same repeating-sweep shape as its siblings.",
1963
+ },
1964
+ "recovery.skipped.orphan-sweep-stale": {
1965
+ reason:
1966
+ "Part of the recovery.skipped.* family: A recurring pre-condition check re-logged every sweep pass — 14,699 lines/mo.",
1967
+ },
1968
+ "recovery.skipped.pr-1071-blocked-by-a-pre-existing-repo-wide-ci-failure-on-main-n": {
1969
+ reason:
1970
+ "Part of the recovery.skipped.* family: ⚠️ The clearest evidence of the family's defect: a full free-text incident explanation baked directly into the event NAME (confirmed against the raw log line) and re-logged 3,960 times for one PR. This is a producer bug flagged for the phase-3 inventory — the reason belongs in payload, never in `type`.",
1971
+ },
1972
+ "recovery.skipped.prior-artifact-missing": {
1973
+ reason:
1974
+ "Part of the recovery.skipped.* family: A recurring pre-condition check re-logged every sweep pass — 35,141 lines/mo, the largest of the skip-reason family.",
1975
+ },
1976
+ "recovery.skipped.rebase-refused-dirty-tree": {
1977
+ reason:
1978
+ "Part of the recovery.skipped.* family: A recurring pre-condition check re-logged every sweep pass — 28,906 lines/mo.",
1979
+ },
1980
+ "recovery.skipped.source-conflict-ctl708-unavailable": {
1981
+ reason:
1982
+ "Part of the recovery.skipped.* family: Same free-text-reason-in-type defect, embedding a specific ticket's conflict detail in the type — flagged for phase-3.",
1983
+ },
1984
+ "recovery.skipped.ticket-already-merged-pipeline-regressed": {
1985
+ reason:
1986
+ "Part of the recovery.skipped.* family: A recurring pre-condition check re-logged every sweep pass — 14,868 lines/mo.",
1987
+ },
1988
+ "recovery.skipped.worker-vanished": {
1989
+ reason:
1990
+ "Part of the recovery.skipped.* family: A recurring pre-condition check, moderate volume (861/mo), same repeating-sweep shape.",
1991
+ },
1992
+ "recovery.skipped.worktree-live-handle-guard-refused": {
1993
+ reason:
1994
+ "Part of the recovery.skipped.* family: A single observed occurrence of the same repeating-sweep-check family.",
1995
+ },
1996
+ "recovery.tick": {
1997
+ reason:
1998
+ "The recovery loop's own scan-pass tick (489k lines/mo) — a heartbeat for the sweep, not a fact about any ticket.",
1999
+ },
2000
+ "recovery.would-defer": {
2001
+ reason:
2002
+ "Finding 3's dominant counterfactual: 505k lines/mo of 'would defer' evaluations. recovery.deferred is the durable fact when a deferral is actually enacted.",
2003
+ },
2004
+ "recovery.would-escalate": {
2005
+ reason:
2006
+ "Same 'would-*' counterfactual shape as recovery.would-defer; recovery.escalated is the durable fact when an escalation is actually sent.",
2007
+ },
2008
+ "recovery.would-fix": {
2009
+ reason:
2010
+ "Same 'would-*' counterfactual shape; recovery.fixed/recovery.fix-failed are the durable facts when a fix is actually attempted.",
2011
+ },
2012
+ "session.context": {
2013
+ reason:
2014
+ "A periodic context-usage/size sample logged during an agent session — a gauge, not a discrete session-lifecycle fact (contrast session.started/session.ended, which ARE durable).",
2015
+ },
2016
+ "worker.memory.sampled": {
2017
+ reason:
2018
+ "ADR-0039's own telemetry example ('process samples') applied to a phase worker's own process.",
2019
+ },
2020
+ "worktree.cleanup-deferred": {
2021
+ reason:
2022
+ "A routine cleanup-scheduling note (6,724 lines/mo) — the same generic-housekeeping shape as the *.reap-requested family, not a ticket/phase coordination fact.",
2023
+ },
2024
+ "worktree.presweep.reap-requested": {
2025
+ reason:
2026
+ "Phase-agent worker-directory garbage collection. phase.terminal.reap-requested alone is 10,015 lines/mo — a periodic sweep re-requesting cleanup of already-terminal workers, not a discrete coordination fact worth replay.",
2027
+ },
2028
+ "worktree.salvage.skipped": {
2029
+ reason:
2030
+ "14,391 lines/mo — logged on every recovery pass that finds nothing to salvage (mirrors the recovery.skipped.* retry-storm shape). worktree.salvage.created is the durable fact when a salvage actually happens.",
2031
+ },
2032
+ } as const satisfies Record<string, TelemetryEventSpec>;
2033
+
2034
+ /** The wire `type` of a DURABLE event — the keys of durableEventTypes, as a runtime array. */
2035
+ export const DURABLE_EVENT_TYPES: readonly string[] = keysOf(durableEventTypes);
2036
+
2037
+ /** The wire `type` of a CURRENT-STATE (heartbeat-shaped) signal — the keys of currentStateEventTypes. */
2038
+ export const CURRENT_STATE_EVENT_TYPES: readonly string[] = keysOf(currentStateEventTypes);
2039
+
2040
+ /** The wire `type` of a TELEMETRY-excluded signal — the keys of telemetryEventTypes. */
2041
+ export const TELEMETRY_EVENT_TYPES: readonly string[] = keysOf(telemetryEventTypes);
2042
+
2043
+ /** Every classified event type across all three buckets — the closed universe this registry covers. */
2044
+ export const ALL_CLASSIFIED_EVENT_TYPES: readonly string[] = [
2045
+ ...DURABLE_EVENT_TYPES,
2046
+ ...CURRENT_STATE_EVENT_TYPES,
2047
+ ...TELEMETRY_EVENT_TYPES,
2048
+ ];
2049
+
2050
+ /** The durable types that may create a Queue wake-up pointer — a strict subset of DURABLE_EVENT_TYPES. */
2051
+ export const WAKE_ELIGIBLE_EVENT_TYPES: readonly string[] = DURABLE_EVENT_TYPES.filter(
2052
+ (t) => durableEventTypes[t as keyof typeof durableEventTypes].wakes !== false,
2053
+ );
2054
+
2055
+ export type EventClassification = "durable" | "current-state" | "telemetry" | "unclassified";
2056
+
2057
+ /**
2058
+ * Classify an event type against the closed registry. Returns `"unclassified"` for anything not in
2059
+ * one of the three buckets — NEVER a durable default (AGENTS.md: a helper that degrades to a falsy
2060
+ * or over-permissive sentinel reads as "fine" to every caller; here the unsafe direction is defaulting
2061
+ * an unknown type to durable, which this function refuses to do).
2062
+ */
2063
+ export function classifyEventType(t: string): EventClassification {
2064
+ if (Object.prototype.hasOwnProperty.call(durableEventTypes, t)) return "durable";
2065
+ if (Object.prototype.hasOwnProperty.call(currentStateEventTypes, t)) return "current-state";
2066
+ if (Object.prototype.hasOwnProperty.call(telemetryEventTypes, t)) return "telemetry";
2067
+ return "unclassified";
2068
+ }