@catalyst-cloud/schema 0.1.43 → 0.1.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@catalyst-cloud/schema",
3
- "version": "0.1.43",
3
+ "version": "0.1.45",
4
4
  "type": "module",
5
5
  "description": "Typed Drizzle schema = single source of truth for the per-tenant Mirror DO SQLite store (CTC-13 / ADR-0002). Shared by the mirror Worker, the host-sync replica, and the browser OPFS replica.",
6
6
  "license": "MIT",
@@ -76,6 +76,27 @@ export const durableEventTypes = {
76
76
  ingestVerb: "coordination.publish",
77
77
  wakes: false,
78
78
  },
79
+ // CTC-838 — a long-lived coordination agent (concierge/steward/worker) announcing which ROLE it
80
+ // holds, so the fleet's own agent_roster (apps/mirror/src/do/agent-roster.ts) can answer "who holds
81
+ // which role, and are they alive" without inventing a heartbeat-shaped table of its own. See
82
+ // ADR-20260903T011701 for why this is observational only.
83
+ "agent.role.started": {
84
+ rationale:
85
+ "A long-lived coordination agent announced the ROLE it holds (concierge / steward / worker) and, when it has one, its parent — a discrete boundary fact, not a sampled reading. The paired terminal fact is agent.role.stopped.",
86
+ ingestVerb: "coordination.publish",
87
+ // ⛔ CTC-838 / ADR-20260903T011701 — a roster row is observational only. Waking a dispatcher on it would
88
+ // make a heartbeat-derived signal load-bearing for scheduling, which this repo's lease and
89
+ // entitlement planes explicitly refuse (lease-verbs.ts:10-13).
90
+ wakes: false,
91
+ entity: "agent",
92
+ },
93
+ "agent.role.stopped": {
94
+ rationale:
95
+ "A coordination agent released its role — the paired terminal fact to agent.role.started, and the only thing that distinguishes 'went away cleanly' from 'stopped pulsing'.",
96
+ ingestVerb: "coordination.publish",
97
+ wakes: false,
98
+ entity: "agent",
99
+ },
79
100
  "agent.waiting-on-user": {
80
101
  rationale:
81
102
  "The agent is now blocked awaiting human input — a coordination fact a host must act on.",
@@ -1141,6 +1162,13 @@ export const durableEventTypes = {
1141
1162
  wakes: false,
1142
1163
  entity: "ticket",
1143
1164
  },
1165
+ "phase.remediate.blocked": {
1166
+ rationale:
1167
+ "ADR-0039 durable-fact example: an escalated remediate round's exhaustion (or its own declared block) raised a catalyst-ask decision ticket that BLOCKS the remediated ticket (CTC-1373) — a confirmed, terminal-until-answered designation, distinct from `phase.remediate.escalation-exhausted`, which merely requested it.",
1168
+ ingestVerb: "coordination.publish",
1169
+ wakes: false,
1170
+ entity: "ticket",
1171
+ },
1144
1172
  "phase.remediate.boot-resume": {
1145
1173
  rationale:
1146
1174
  "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.",
@@ -1162,6 +1190,20 @@ export const durableEventTypes = {
1162
1190
  wakes: false,
1163
1191
  entity: "ticket",
1164
1192
  },
1193
+ "phase.remediate.escalated": {
1194
+ rationale:
1195
+ "ADR-0039 durable-fact example: a remediate round's cap-exhaustion escalated to a second, broader-purview attempt instead of parking (CTC-1373) — a distinct lifecycle transition from an ordinary `phase.remediate.failed`, and one that creates newly claimable work.",
1196
+ ingestVerb: "coordination.publish",
1197
+ wakes: { consumerClass: "dispatcher" },
1198
+ entity: "ticket",
1199
+ },
1200
+ "phase.remediate.escalation-exhausted": {
1201
+ rationale:
1202
+ "ADR-0039 durable-fact example: the escalated (broader-purview) remediate round also failed, or declared itself blocked (CTC-1373) — the terminal signal that requests a blocking ASK ticket be raised; see the paired `phase.remediate.blocked` once one is confirmed.",
1203
+ ingestVerb: "coordination.publish",
1204
+ wakes: false,
1205
+ entity: "ticket",
1206
+ },
1165
1207
  "phase.remediate.failed": {
1166
1208
  rationale:
1167
1209
  "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): the phase reported failure.",
@@ -1211,6 +1253,20 @@ export const durableEventTypes = {
1211
1253
  wakes: false,
1212
1254
  entity: "ticket",
1213
1255
  },
1256
+ "phase.remediate.rewind": {
1257
+ rationale:
1258
+ "ADR-0039 durable-fact example: a successful remediate round's own ladder-rewind request was applied (CTC-1373) — earlier relay_phase_state rows were reset to `ready`, creating newly claimable work for the reset span.",
1259
+ ingestVerb: "coordination.publish",
1260
+ wakes: { consumerClass: "dispatcher" },
1261
+ entity: "ticket",
1262
+ },
1263
+ "phase.remediate.rewind-requested": {
1264
+ rationale:
1265
+ "ADR-0039 durable-fact example: a successful remediate round recommended the ladder start over rather than advance (CTC-1373's adjudication) — a request the mirror applies under its own fence and budget; see the paired `phase.remediate.rewind` once applied.",
1266
+ ingestVerb: "coordination.publish",
1267
+ wakes: false,
1268
+ entity: "ticket",
1269
+ },
1214
1270
  "phase.rescue.dispatched": {
1215
1271
  rationale:
1216
1272
  "ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'): work became eligible and was dispatched to a worker.",
@@ -1861,6 +1917,13 @@ export interface CurrentStateEventSpec {
1861
1917
  * for zero replay value.
1862
1918
  */
1863
1919
  export const currentStateEventTypes = {
1920
+ // CTC-838 — the pulse half of the agent-role pair above: updates the agent_roster row's
1921
+ // last_seen_at in place rather than growing the durable history on every pulse.
1922
+ "agent.role.heartbeat": {
1923
+ rationale:
1924
+ "A coordination agent's role liveness pulse — updates mutable NOW (the agent_roster row's last_seen_at); agent.role.started/stopped are the durable boundary facts.",
1925
+ boundaryEvents: ["agent.role.started", "agent.role.stopped"],
1926
+ },
1864
1927
  "broker.daemon.heartbeat": {
1865
1928
  rationale:
1866
1929
  "The coordination broker daemon's own liveness pulse — updates mutable NOW; startup/shutdown are the durable boundary facts.",
@@ -1905,8 +1968,12 @@ export interface TelemetryEventSpec {
1905
1968
  * telemetry-shaped in the plan's measurement) — ticks, gauges, process samples, read traces,
1906
1969
  * forwarding lag, "would-*" dry-run counterfactuals, and retry-storm noise that collapses to a single
1907
1970
  * durable boundary fact elsewhere in this registry (e.g. linear.write.proxy.failed's 140k+ lines/mo
1908
- * collapses to the ONE durable linear.label.retry-exhausted terminal fact). CTC-962 (ADR-0048) added
1909
- * 5 mirror-ingress names on top of those 70 (measured total: 75) — see the `mirror.*` entries below.
1971
+ * collapses to the ONE durable linear.label.retry-exhausted terminal fact). CTC-962 (ADR-0048) started
1972
+ * the `mirror.*` family; it now carries 7 names (CTC-289's mirror.webhook.out-of-scope and CTC-1510's
1973
+ * mirror.dispatch-queue.derive-refused both rode the same sink after CTC-962 landed) — see those
1974
+ * entries below. ⚠️ The "70 fleet/orchestrator-origin types" figure above is this comment's OWN prior
1975
+ * measurement, already stale against the live count (Object.keys(telemetryEventTypes).length) by the
1976
+ * time CTC-1510 read it — re-measure before citing it, don't re-derive it from this text.
1910
1977
  */
1911
1978
  export const telemetryEventTypes = {
1912
1979
  "account.ratelimit.sampled": {
@@ -2075,6 +2142,11 @@ export const telemetryEventTypes = {
2075
2142
  "CTC-289 — a verified, tenant-routable delivery whose repo/team is not a provisioned `projects` row. Carries the account, the scope key and the fence mode: the scope key is the entire diagnostic value (it answers 'why is repo Y in my mirror' and 'why is repo Y missing'), and the mode distinguishes an observed would-drop from an actual drop. Unsampled while the fence rolls out — the `observe` soak that gates enforcement reads exactly this signal, and a sampled soak cannot support a data-discarding flip. Revisit the class once enforce has been stable.",
2076
2143
  sampling: { kind: "always" },
2077
2144
  },
2145
+ "mirror.dispatch-queue.derive-refused": {
2146
+ reason:
2147
+ "CTC-1510 — one point per fail-closed `deriveDispatchQueue` refusal (an unresolved, missing or ambiguous team_workflow_mapping), carrying the team and WHICH resolution failed. Not durable: the refusal is a description of a configuration state, not a state transition, and it repeats every pass until the mapping is fixed — the durable fact is the mapping row itself. `always`-sampled: rare by design (a healthy tenant never emits it) and it is the ONLY machine-readable signal that a team's queue stopped advancing on purpose, which is exactly what a sampled-away point would hide. Repeats inside the DO's announce window are folded into `count`, never dropped.",
2148
+ sampling: { kind: "always" },
2149
+ },
2078
2150
  "orphans.reap-requested": {
2079
2151
  reason:
2080
2152
  "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.",