@moltzap/protocol 2026.503.3 → 2026.504.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/dist/brands.d.ts +11 -0
  2. package/dist/brands.d.ts.map +1 -0
  3. package/dist/brands.js +14 -0
  4. package/dist/brands.js.map +1 -0
  5. package/dist/helpers.d.ts +29 -26
  6. package/dist/helpers.d.ts.map +1 -1
  7. package/dist/helpers.js +34 -16
  8. package/dist/helpers.js.map +1 -1
  9. package/dist/index.d.ts +6 -3
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +6 -3
  12. package/dist/index.js.map +1 -1
  13. package/dist/internal/ajv.d.ts +5 -0
  14. package/dist/internal/ajv.d.ts.map +1 -0
  15. package/dist/internal/ajv.js +22 -0
  16. package/dist/internal/ajv.js.map +1 -0
  17. package/dist/notification.d.ts +14 -0
  18. package/dist/notification.d.ts.map +1 -0
  19. package/dist/notification.js +11 -0
  20. package/dist/notification.js.map +1 -0
  21. package/dist/rpc-errors.d.ts +30 -0
  22. package/dist/rpc-errors.d.ts.map +1 -0
  23. package/dist/rpc-errors.js +23 -0
  24. package/dist/rpc-errors.js.map +1 -0
  25. package/dist/rpc-groups.d.ts +120 -0
  26. package/dist/rpc-groups.d.ts.map +1 -0
  27. package/dist/rpc-groups.js +131 -0
  28. package/dist/rpc-groups.js.map +1 -0
  29. package/dist/rpc-registry.d.ts +1238 -278
  30. package/dist/rpc-registry.d.ts.map +1 -1
  31. package/dist/rpc-registry.js +11 -22
  32. package/dist/rpc-registry.js.map +1 -1
  33. package/dist/rpc.d.ts +26 -5
  34. package/dist/rpc.d.ts.map +1 -1
  35. package/dist/rpc.js +21 -11
  36. package/dist/rpc.js.map +1 -1
  37. package/dist/schema/apps.d.ts +13 -23
  38. package/dist/schema/apps.d.ts.map +1 -1
  39. package/dist/schema/apps.js +2 -12
  40. package/dist/schema/apps.js.map +1 -1
  41. package/dist/schema/contacts.d.ts +6 -2
  42. package/dist/schema/contacts.d.ts.map +1 -1
  43. package/dist/schema/conversations.d.ts +15 -5
  44. package/dist/schema/conversations.d.ts.map +1 -1
  45. package/dist/schema/delivery.d.ts +9 -3
  46. package/dist/schema/delivery.d.ts.map +1 -1
  47. package/dist/schema/errors.d.ts +0 -4
  48. package/dist/schema/errors.d.ts.map +1 -1
  49. package/dist/schema/errors.js +0 -4
  50. package/dist/schema/errors.js.map +1 -1
  51. package/dist/schema/frames.d.ts +48 -51
  52. package/dist/schema/frames.d.ts.map +1 -1
  53. package/dist/schema/frames.js +28 -50
  54. package/dist/schema/frames.js.map +1 -1
  55. package/dist/schema/identity.d.ts +17 -9
  56. package/dist/schema/identity.d.ts.map +1 -1
  57. package/dist/schema/index.d.ts +3 -4
  58. package/dist/schema/index.d.ts.map +1 -1
  59. package/dist/schema/index.js +3 -4
  60. package/dist/schema/index.js.map +1 -1
  61. package/dist/schema/internal-frames.d.ts +10 -0
  62. package/dist/schema/internal-frames.d.ts.map +1 -0
  63. package/dist/schema/internal-frames.js +5 -0
  64. package/dist/schema/internal-frames.js.map +1 -0
  65. package/dist/schema/invites.d.ts +6 -2
  66. package/dist/schema/invites.d.ts.map +1 -1
  67. package/dist/schema/json-rpc.d.ts +27 -0
  68. package/dist/schema/json-rpc.d.ts.map +1 -0
  69. package/dist/schema/json-rpc.js +32 -0
  70. package/dist/schema/json-rpc.js.map +1 -0
  71. package/dist/schema/messages.d.ts +15 -5
  72. package/dist/schema/messages.d.ts.map +1 -1
  73. package/dist/schema/methods/apps.d.ts +138 -85
  74. package/dist/schema/methods/apps.d.ts.map +1 -1
  75. package/dist/schema/methods/apps.js +4 -45
  76. package/dist/schema/methods/apps.js.map +1 -1
  77. package/dist/schema/methods/auth.d.ts +62 -34
  78. package/dist/schema/methods/auth.d.ts.map +1 -1
  79. package/dist/schema/methods/contacts.d.ts +27 -9
  80. package/dist/schema/methods/contacts.d.ts.map +1 -1
  81. package/dist/schema/methods/conversations.d.ts +91 -18
  82. package/dist/schema/methods/conversations.d.ts.map +1 -1
  83. package/dist/schema/methods/conversations.js +2 -2
  84. package/dist/schema/methods/conversations.js.map +1 -1
  85. package/dist/schema/methods/messages.d.ts +39 -13
  86. package/dist/schema/methods/messages.d.ts.map +1 -1
  87. package/dist/schema/methods/presence.d.ts +6 -2
  88. package/dist/schema/methods/presence.d.ts.map +1 -1
  89. package/dist/schema/notifications.d.ts +791 -0
  90. package/dist/schema/notifications.d.ts.map +1 -0
  91. package/dist/schema/notifications.js +173 -0
  92. package/dist/schema/notifications.js.map +1 -0
  93. package/dist/schema/presence.d.ts +3 -1
  94. package/dist/schema/presence.d.ts.map +1 -1
  95. package/dist/schema/primitives.d.ts +21 -5
  96. package/dist/schema/primitives.d.ts.map +1 -1
  97. package/dist/schema/primitives.js +6 -0
  98. package/dist/schema/primitives.js.map +1 -1
  99. package/dist/test-fixtures/seed-data.d.ts +0 -1388
  100. package/dist/test-fixtures/seed-data.d.ts.map +1 -1
  101. package/dist/test-fixtures/seed-data.js +34 -990
  102. package/dist/test-fixtures/seed-data.js.map +1 -1
  103. package/dist/testing/agent-registration.d.ts +3 -1
  104. package/dist/testing/agent-registration.d.ts.map +1 -1
  105. package/dist/testing/agent-registration.js +6 -15
  106. package/dist/testing/agent-registration.js.map +1 -1
  107. package/dist/testing/arbitraries/frames.d.ts +2 -2
  108. package/dist/testing/arbitraries/frames.d.ts.map +1 -1
  109. package/dist/testing/arbitraries/frames.js +9 -7
  110. package/dist/testing/arbitraries/frames.js.map +1 -1
  111. package/dist/testing/arbitraries/from-typebox.d.ts.map +1 -1
  112. package/dist/testing/arbitraries/from-typebox.js +19 -10
  113. package/dist/testing/arbitraries/from-typebox.js.map +1 -1
  114. package/dist/testing/arbitraries/index.d.ts +1 -1
  115. package/dist/testing/arbitraries/index.d.ts.map +1 -1
  116. package/dist/testing/arbitraries/index.js +1 -1
  117. package/dist/testing/arbitraries/index.js.map +1 -1
  118. package/dist/testing/arbitraries/rpc.d.ts +3 -2
  119. package/dist/testing/arbitraries/rpc.d.ts.map +1 -1
  120. package/dist/testing/arbitraries/rpc.js +13 -3
  121. package/dist/testing/arbitraries/rpc.js.map +1 -1
  122. package/dist/testing/captures.d.ts.map +1 -1
  123. package/dist/testing/captures.js +4 -3
  124. package/dist/testing/captures.js.map +1 -1
  125. package/dist/testing/codec.d.ts +13 -11
  126. package/dist/testing/codec.d.ts.map +1 -1
  127. package/dist/testing/codec.js +43 -50
  128. package/dist/testing/codec.js.map +1 -1
  129. package/dist/testing/conformance/__divergence_proofs__/executable-proof-helpers.d.ts.map +1 -1
  130. package/dist/testing/conformance/__divergence_proofs__/executable-proof-helpers.js +15 -5
  131. package/dist/testing/conformance/__divergence_proofs__/executable-proof-helpers.js.map +1 -1
  132. package/dist/testing/conformance/_helpers.d.ts +12 -7
  133. package/dist/testing/conformance/_helpers.d.ts.map +1 -1
  134. package/dist/testing/conformance/_helpers.js +30 -7
  135. package/dist/testing/conformance/_helpers.js.map +1 -1
  136. package/dist/testing/conformance/adversity.d.ts.map +1 -1
  137. package/dist/testing/conformance/adversity.js +83 -90
  138. package/dist/testing/conformance/adversity.js.map +1 -1
  139. package/dist/testing/conformance/boundary.d.ts +1 -1
  140. package/dist/testing/conformance/boundary.d.ts.map +1 -1
  141. package/dist/testing/conformance/boundary.js +55 -50
  142. package/dist/testing/conformance/boundary.js.map +1 -1
  143. package/dist/testing/conformance/client/_fixtures.d.ts +7 -5
  144. package/dist/testing/conformance/client/_fixtures.d.ts.map +1 -1
  145. package/dist/testing/conformance/client/_fixtures.js +17 -8
  146. package/dist/testing/conformance/client/_fixtures.js.map +1 -1
  147. package/dist/testing/conformance/client/adversity.d.ts.map +1 -1
  148. package/dist/testing/conformance/client/adversity.js +28 -22
  149. package/dist/testing/conformance/client/adversity.js.map +1 -1
  150. package/dist/testing/conformance/client/boundary.d.ts +2 -2
  151. package/dist/testing/conformance/client/boundary.d.ts.map +1 -1
  152. package/dist/testing/conformance/client/boundary.js +19 -16
  153. package/dist/testing/conformance/client/boundary.js.map +1 -1
  154. package/dist/testing/conformance/client/delivery.d.ts +5 -5
  155. package/dist/testing/conformance/client/delivery.d.ts.map +1 -1
  156. package/dist/testing/conformance/client/delivery.js +77 -73
  157. package/dist/testing/conformance/client/delivery.js.map +1 -1
  158. package/dist/testing/conformance/client/index.d.ts +2 -2
  159. package/dist/testing/conformance/client/index.d.ts.map +1 -1
  160. package/dist/testing/conformance/client/index.js +1 -1
  161. package/dist/testing/conformance/client/index.js.map +1 -1
  162. package/dist/testing/conformance/client/rpc-semantics.d.ts.map +1 -1
  163. package/dist/testing/conformance/client/rpc-semantics.js +31 -37
  164. package/dist/testing/conformance/client/rpc-semantics.js.map +1 -1
  165. package/dist/testing/conformance/client/runner.d.ts +38 -32
  166. package/dist/testing/conformance/client/runner.d.ts.map +1 -1
  167. package/dist/testing/conformance/client/runner.js +36 -45
  168. package/dist/testing/conformance/client/runner.js.map +1 -1
  169. package/dist/testing/conformance/client/schema-conformance.d.ts +8 -8
  170. package/dist/testing/conformance/client/schema-conformance.d.ts.map +1 -1
  171. package/dist/testing/conformance/client/schema-conformance.js +37 -35
  172. package/dist/testing/conformance/client/schema-conformance.js.map +1 -1
  173. package/dist/testing/conformance/client/suite.d.ts.map +1 -1
  174. package/dist/testing/conformance/client/suite.js +4 -3
  175. package/dist/testing/conformance/client/suite.js.map +1 -1
  176. package/dist/testing/conformance/delivery.d.ts.map +1 -1
  177. package/dist/testing/conformance/delivery.js +127 -140
  178. package/dist/testing/conformance/delivery.js.map +1 -1
  179. package/dist/testing/conformance/dispatcher-concurrency.js +12 -12
  180. package/dist/testing/conformance/dispatcher-concurrency.js.map +1 -1
  181. package/dist/testing/conformance/env.d.ts +9 -0
  182. package/dist/testing/conformance/env.d.ts.map +1 -1
  183. package/dist/testing/conformance/env.js +16 -3
  184. package/dist/testing/conformance/env.js.map +1 -1
  185. package/dist/testing/conformance/presence.d.ts.map +1 -1
  186. package/dist/testing/conformance/presence.js +35 -24
  187. package/dist/testing/conformance/presence.js.map +1 -1
  188. package/dist/testing/conformance/registry.d.ts +1 -1
  189. package/dist/testing/conformance/registry.d.ts.map +1 -1
  190. package/dist/testing/conformance/registry.js +1 -1
  191. package/dist/testing/conformance/registry.js.map +1 -1
  192. package/dist/testing/conformance/rpc-semantics.d.ts +12 -12
  193. package/dist/testing/conformance/rpc-semantics.d.ts.map +1 -1
  194. package/dist/testing/conformance/rpc-semantics.js +131 -90
  195. package/dist/testing/conformance/rpc-semantics.js.map +1 -1
  196. package/dist/testing/conformance/runner.d.ts +2 -2
  197. package/dist/testing/conformance/runner.d.ts.map +1 -1
  198. package/dist/testing/conformance/runner.js +5 -10
  199. package/dist/testing/conformance/runner.js.map +1 -1
  200. package/dist/testing/conformance/schema-conformance.d.ts +3 -40
  201. package/dist/testing/conformance/schema-conformance.d.ts.map +1 -1
  202. package/dist/testing/conformance/schema-conformance.js +75 -235
  203. package/dist/testing/conformance/schema-conformance.js.map +1 -1
  204. package/dist/testing/conformance/suite.d.ts +1 -1
  205. package/dist/testing/conformance/suite.d.ts.map +1 -1
  206. package/dist/testing/conformance/suite.js +17 -18
  207. package/dist/testing/conformance/suite.js.map +1 -1
  208. package/dist/testing/index.d.ts +1 -1
  209. package/dist/testing/index.d.ts.map +1 -1
  210. package/dist/testing/models/dispatch.d.ts +5 -5
  211. package/dist/testing/models/dispatch.d.ts.map +1 -1
  212. package/dist/testing/models/dispatch.js +50 -59
  213. package/dist/testing/models/dispatch.js.map +1 -1
  214. package/dist/testing/models/state.d.ts +5 -5
  215. package/dist/testing/models/state.d.ts.map +1 -1
  216. package/dist/testing/models/state.js +14 -1
  217. package/dist/testing/models/state.js.map +1 -1
  218. package/dist/testing/test-client.d.ts +51 -40
  219. package/dist/testing/test-client.d.ts.map +1 -1
  220. package/dist/testing/test-client.js +154 -122
  221. package/dist/testing/test-client.js.map +1 -1
  222. package/dist/testing/test-server.d.ts +5 -5
  223. package/dist/testing/test-server.d.ts.map +1 -1
  224. package/dist/testing/test-server.js +11 -15
  225. package/dist/testing/test-server.js.map +1 -1
  226. package/dist/testing/toxics/client.d.ts.map +1 -1
  227. package/dist/testing/toxics/client.js +9 -3
  228. package/dist/testing/toxics/client.js.map +1 -1
  229. package/dist/testing/toxics/profile.d.ts.map +1 -1
  230. package/dist/testing/toxics/profile.js +4 -1
  231. package/dist/testing/toxics/profile.js.map +1 -1
  232. package/dist/types.d.ts +3 -5
  233. package/dist/types.d.ts.map +1 -1
  234. package/dist/types.js.map +1 -1
  235. package/dist/validators.d.ts +366 -101
  236. package/dist/validators.d.ts.map +1 -1
  237. package/dist/validators.js +23 -30
  238. package/dist/validators.js.map +1 -1
  239. package/dist/version.d.ts +1 -1
  240. package/dist/version.js +1 -1
  241. package/package.json +2 -2
  242. package/dist/schema/events.d.ts +0 -213
  243. package/dist/schema/events.d.ts.map +0 -1
  244. package/dist/schema/events.js +0 -122
  245. package/dist/schema/events.js.map +0 -1
  246. package/dist/schema/methods/push.d.ts +0 -21
  247. package/dist/schema/methods/push.d.ts.map +0 -1
  248. package/dist/schema/methods/push.js +0 -28
  249. package/dist/schema/methods/push.js.map +0 -1
  250. package/dist/schema/surfaces.d.ts +0 -55
  251. package/dist/schema/surfaces.d.ts.map +0 -1
  252. package/dist/schema/surfaces.js +0 -55
  253. package/dist/schema/surfaces.js.map +0 -1
@@ -9,23 +9,30 @@
9
9
  * Principle 3: every property body is `Effect<void, PropertyFailure>`.
10
10
  */
11
11
  import * as fc from "fast-check";
12
- import { Effect, Ref } from "effect";
12
+ import { Effect, Either, Ref } from "effect";
13
13
  import { ErrorCodes } from "../../schema/errors.js";
14
- import { EventNames } from "../../schema/events.js";
14
+ import { AppSessionClosedNotificationDefinition, ConversationArchivedNotificationDefinition, ConversationCreatedNotificationDefinition, ConversationUnarchivedNotificationDefinition, ConversationUpdatedNotificationDefinition, MessageReceivedNotificationDefinition, } from "../../schema/notifications.js";
15
15
  import { AppsCloseSession, AppsCreate, AppsRegister, } from "../../schema/methods/apps.js";
16
16
  import { ConversationsArchive, ConversationsCreate, ConversationsUnarchive, ConversationsUpdate, } from "../../schema/methods/conversations.js";
17
17
  import { MessagesSend } from "../../schema/methods/messages.js";
18
+ import { AgentId, ConversationId, conversationId as makeConversationId, } from "../../schema/primitives.js";
19
+ import { RpcResponseError } from "../errors.js";
20
+ import { isNotificationFrame } from "../codec.js";
18
21
  import { makeTestClient } from "../test-client.js";
19
22
  import { registerTestAgent } from "../agent-registration.js";
20
23
  import { PropertyDeferred, PropertyInvariantViolation, PropertyUnavailable, assertProperty, registerProperty, } from "./registry.js";
21
- import { sendUntypedRpc } from "./_helpers.js";
24
+ import { leftOrNull, requireRight, sendUntypedRpc } from "./_helpers.js";
22
25
  const CATEGORY = "delivery";
23
26
  const DEFAULT_TIMEOUT_MS = 5000;
24
27
  const DEFAULT_CAPTURE_CAPACITY = 256;
28
+ const DEFAULT_PROPERTY_NUM_RUNS = 3;
29
+ const DATE_ID_RADIX = 36;
25
30
  const MAX_N = 4;
26
31
  const CONVERSATION_LIFECYCLE_PROPERTY = "conversation-lifecycle";
27
32
  const APP_SESSION_CLOSE_LIFECYCLE_PROPERTY = "app-session-close-lifecycle";
28
33
  const ARCHIVE_LIFECYCLE_PROPERTY = "archive-lifecycle";
34
+ const STORE_AND_REPLAY_PROPERTY = "store-and-replay";
35
+ const TASK_BOUNDARY_ISOLATION_PROPERTY = "task-boundary-isolation";
29
36
  function violation(name, reason) {
30
37
  return new PropertyInvariantViolation({ category: CATEGORY, name, reason });
31
38
  }
@@ -39,104 +46,110 @@ function firstParticipant(fixture, propertyName) {
39
46
  : Effect.succeed(participant);
40
47
  }
41
48
  function sendText(actor, conversationId, text) {
42
- return actor.client.sendRpc(MessagesSend.name, {
49
+ return actor.client.sendRpc(MessagesSend, {
43
50
  conversationId,
44
51
  parts: [{ type: "text", text }],
45
52
  });
46
53
  }
47
54
  function archiveConversation(actor, conversationId) {
48
- return actor.client.sendRpc(ConversationsArchive.name, { conversationId });
55
+ return actor.client.sendRpc(ConversationsArchive, { conversationId });
49
56
  }
50
57
  function updateConversationName(actor, conversationId, name) {
51
- return actor.client.sendRpc(ConversationsUpdate.name, {
58
+ return actor.client.sendRpc(ConversationsUpdate, {
52
59
  conversationId,
53
60
  name,
54
61
  });
55
62
  }
56
63
  function unarchiveConversation(actor, conversationId) {
57
- return actor.client.sendRpc(ConversationsUnarchive.name, { conversationId });
64
+ return actor.client.sendRpc(ConversationsUnarchive, { conversationId });
58
65
  }
59
- function waitForConversationCreatedEvent(observer, conversationId, propertyName) {
66
+ function waitForConversationCreatedNotification(observer, conversationId, propertyName) {
60
67
  return Effect.gen(function* () {
61
68
  const event = yield* observer.client
62
- .waitForEvent(EventNames.ConversationCreated, DEFAULT_TIMEOUT_MS)
69
+ .waitForNotification(ConversationCreatedNotificationDefinition, DEFAULT_TIMEOUT_MS)
63
70
  .pipe(Effect.mapError((e) => violation(propertyName, `created event missing: ${e.message}`)));
64
- const data = event.data;
71
+ const data = event.params;
65
72
  if (data?.conversation?.id !== conversationId) {
66
- return yield* Effect.fail(violation(propertyName, `bad created event payload: ${JSON.stringify(event.data)}`));
73
+ return yield* Effect.fail(violation(propertyName, `bad created event payload: ${JSON.stringify(event.params)}`));
67
74
  }
68
75
  });
69
76
  }
70
- function waitForConversationUpdatedEvent(observer, conversationId, name, propertyName) {
77
+ function waitForConversationUpdatedNotification(observer, conversationId, name, propertyName) {
71
78
  return Effect.gen(function* () {
72
79
  const event = yield* observer.client
73
- .waitForEvent(EventNames.ConversationUpdated, DEFAULT_TIMEOUT_MS)
80
+ .waitForNotification(ConversationUpdatedNotificationDefinition, DEFAULT_TIMEOUT_MS)
74
81
  .pipe(Effect.mapError((e) => violation(propertyName, `updated event missing: ${e.message}`)));
75
- const data = event.data;
82
+ const data = event.params;
76
83
  if (data?.conversation?.id !== conversationId ||
77
84
  data.conversation.name !== name) {
78
- return yield* Effect.fail(violation(propertyName, `bad updated event payload: ${JSON.stringify(event.data)}`));
85
+ return yield* Effect.fail(violation(propertyName, `bad updated event payload: ${JSON.stringify(event.params)}`));
79
86
  }
80
87
  });
81
88
  }
82
- function waitForMessageReceivedEvent(observer, conversationId, propertyName) {
89
+ function waitForMessageReceivedNotification(observer, conversationId, propertyName) {
83
90
  return Effect.gen(function* () {
84
91
  const event = yield* observer.client
85
- .waitForEvent(EventNames.MessageReceived, DEFAULT_TIMEOUT_MS)
92
+ .waitForNotification(MessageReceivedNotificationDefinition, DEFAULT_TIMEOUT_MS)
86
93
  .pipe(Effect.mapError((e) => violation(propertyName, `message event missing: ${e.message}`)));
87
- const data = event.data;
94
+ const data = event.params;
88
95
  if (data?.message?.conversationId !== conversationId) {
89
- return yield* Effect.fail(violation(propertyName, `bad message event payload: ${JSON.stringify(event.data)}`));
96
+ return yield* Effect.fail(violation(propertyName, `bad message event payload: ${JSON.stringify(event.params)}`));
90
97
  }
91
98
  });
92
99
  }
93
- function waitForAppSessionClosedEvent(observer, sessionId, closedBy, propertyName) {
100
+ function waitForAppSessionClosedNotification(observer, sessionId, closedBy, propertyName) {
94
101
  return Effect.gen(function* () {
95
102
  const event = yield* observer.client
96
- .waitForEvent(EventNames.AppSessionClosed, DEFAULT_TIMEOUT_MS)
103
+ .waitForNotification(AppSessionClosedNotificationDefinition, DEFAULT_TIMEOUT_MS)
97
104
  .pipe(Effect.mapError((e) => violation(propertyName, `session closed event missing: ${e.message}`)));
98
- const data = event.data;
105
+ const data = event.params;
99
106
  if (data?.sessionId !== sessionId || data.closedBy !== closedBy) {
100
- return yield* Effect.fail(violation(propertyName, `bad session closed event payload: ${JSON.stringify(event.data)}`));
107
+ return yield* Effect.fail(violation(propertyName, `bad session closed event payload: ${JSON.stringify(event.params)}`));
101
108
  }
102
109
  });
103
110
  }
104
111
  function waitForArchivedEvent(observer, conversationId, byAgentId, propertyName) {
105
112
  return Effect.gen(function* () {
106
113
  const event = yield* observer.client
107
- .waitForEvent(EventNames.ConversationArchived, DEFAULT_TIMEOUT_MS)
114
+ .waitForNotification(ConversationArchivedNotificationDefinition, DEFAULT_TIMEOUT_MS)
108
115
  .pipe(Effect.mapError((e) => violation(propertyName, `archive event missing: ${e.message}`)));
109
- const data = event.data;
116
+ const data = event.params;
110
117
  if (data?.conversationId !== conversationId ||
111
118
  typeof data.archivedAt !== "string" ||
112
119
  data.by !== byAgentId) {
113
- return yield* Effect.fail(violation(propertyName, `bad archive event payload: ${JSON.stringify(event.data)}`));
120
+ return yield* Effect.fail(violation(propertyName, `bad archive event payload: ${JSON.stringify(event.params)}`));
114
121
  }
115
122
  });
116
123
  }
117
124
  function waitForUnarchivedEvent(observer, conversationId, byAgentId, propertyName) {
118
125
  return Effect.gen(function* () {
119
126
  const event = yield* observer.client
120
- .waitForEvent(EventNames.ConversationUnarchived, DEFAULT_TIMEOUT_MS)
127
+ .waitForNotification(ConversationUnarchivedNotificationDefinition, DEFAULT_TIMEOUT_MS)
121
128
  .pipe(Effect.mapError((e) => violation(propertyName, `unarchive event missing: ${e.message}`)));
122
- const data = event.data;
129
+ const data = event.params;
123
130
  if (data?.conversationId !== conversationId || data.by !== byAgentId) {
124
- return yield* Effect.fail(violation(propertyName, `bad unarchive event payload: ${JSON.stringify(event.data)}`));
131
+ return yield* Effect.fail(violation(propertyName, `bad unarchive event payload: ${JSON.stringify(event.params)}`));
125
132
  }
126
133
  });
127
134
  }
128
135
  function assertConversationRejectsMessages(actor, conversationId, propertyName) {
129
136
  return Effect.gen(function* () {
130
137
  const outcome = yield* sendText(actor, conversationId, "must-fail-while-archived").pipe(Effect.either);
131
- if (outcome._tag === "Right") {
132
- return yield* Effect.fail(violation(propertyName, "messages/send succeeded while archived"));
133
- }
134
- if (outcome.left._tag !== "TestingRpcResponseError" ||
135
- outcome.left.code !== ErrorCodes.ConversationArchived) {
136
- const errorLabel = outcome.left._tag === "TestingRpcResponseError"
137
- ? `${outcome.left._tag}/${outcome.left.code}`
138
- : outcome.left._tag;
139
- return yield* Effect.fail(violation(propertyName, `messages/send returned ${errorLabel}, expected ConversationArchived`));
138
+ const outcomeViolation = Either.match(outcome, {
139
+ onRight: () => violation(propertyName, "messages/send succeeded while archived"),
140
+ onLeft: (error) => {
141
+ if (error instanceof RpcResponseError &&
142
+ error.code === ErrorCodes.ConversationArchived) {
143
+ return null;
144
+ }
145
+ const errorLabel = error instanceof RpcResponseError
146
+ ? `${error._tag}/${error.code}`
147
+ : error._tag;
148
+ return violation(propertyName, `messages/send returned ${errorLabel}, expected ConversationArchived`);
149
+ },
150
+ });
151
+ if (outcomeViolation !== null) {
152
+ return yield* Effect.fail(outcomeViolation);
140
153
  }
141
154
  });
142
155
  }
@@ -162,7 +175,7 @@ function acquireConversation(ctx, n, namePrefix) {
162
175
  const owner = yield* acquireClient(ctx, `${namePrefix}-owner`);
163
176
  const participants = yield* Effect.forEach(Array.from({ length: clamped }, (_, i) => i), (i) => acquireClient(ctx, `${namePrefix}-p${i}`), { concurrency: clamped });
164
177
  const createResult = yield* owner.client
165
- .sendRpc(ConversationsCreate.name, {
178
+ .sendRpc(ConversationsCreate, {
166
179
  type: "group",
167
180
  name: `${namePrefix}-conv`,
168
181
  participants: participants.map((p) => ({
@@ -171,15 +184,16 @@ function acquireConversation(ctx, n, namePrefix) {
171
184
  })),
172
185
  })
173
186
  .pipe(Effect.either);
174
- if (createResult._tag === "Left") {
175
- return yield* Effect.fail(`conversations/create failed: ${createResult.left._tag}`);
176
- }
177
- const created = createResult.right;
187
+ const created = (yield* requireRight(createResult, (error) => `conversations/create failed: ${error._tag}`));
178
188
  const conversationId = created.conversation?.id;
179
189
  if (typeof conversationId !== "string" || conversationId.length === 0) {
180
190
  return yield* Effect.fail(`conversations/create returned no conversation.id`);
181
191
  }
182
- return { owner, participants, conversationId };
192
+ return {
193
+ owner,
194
+ participants,
195
+ conversationId: makeConversationId(conversationId),
196
+ };
183
197
  });
184
198
  }
185
199
  /**
@@ -192,22 +206,22 @@ function acquireConversation(ctx, n, namePrefix) {
192
206
  */
193
207
  export function registerFanOutCardinality(ctx) {
194
208
  registerProperty(ctx, CATEGORY, "fan-out-cardinality", "messages/send ⇒ exactly N inbound message events (one per connection)", assertProperty(CATEGORY, "fan-out-cardinality", () => fc.assert(fc.asyncProperty(fc.integer({ min: 2, max: 3 }), (n) => Effect.runPromise(Effect.scoped(Effect.gen(function* () {
195
- const fixture = yield* acquireConversation(ctx, n, "fan").pipe(Effect.mapError((e) => new Error(e)));
209
+ const fixture = yield* acquireConversation(ctx, n, "fan").pipe(Effect.mapError((e) => violation("fan-out-cardinality", `fixture: ${e}`)));
196
210
  const send = yield* fixture.owner.client
197
- .sendRpc(MessagesSend.name, {
211
+ .sendRpc(MessagesSend, {
198
212
  conversationId: fixture.conversationId,
199
213
  parts: [{ type: "text", text: "fan-out-ping" }],
200
214
  })
201
215
  .pipe(Effect.either);
202
- if (send._tag === "Left") {
216
+ if (leftOrNull(send) !== null) {
203
217
  return { kind: "send-failed" };
204
218
  }
205
219
  yield* Effect.sleep("250 millis");
206
220
  const observed = yield* Effect.forEach(fixture.participants, (p) => p.client.snapshot);
207
221
  const counts = observed.map((snap) => snap.filter((s) => s.kind === "inbound" &&
208
- s.frame?.type === "event" &&
209
- typeof s.frame.event === "string" &&
210
- s.frame.event.includes("message")).length);
222
+ s.frame !== null &&
223
+ isNotificationFrame(s.frame) &&
224
+ s.frame.method.includes("message")).length);
211
225
  return { kind: "ok", counts };
212
226
  })).pipe(Effect.map((result) => {
213
227
  if (result.kind !== "ok")
@@ -215,7 +229,10 @@ export function registerFanOutCardinality(ctx) {
215
229
  // Exact-cardinality predicate. Duplicates and drops both fail.
216
230
  return (result.counts.length === fixture_n(n) &&
217
231
  result.counts.every((c) => c === 1));
218
- })))), { seed: ctx.seed, numRuns: ctx.opts.numRuns ?? 3 })));
232
+ })))), {
233
+ seed: ctx.seed,
234
+ numRuns: ctx.opts.numRuns ?? DEFAULT_PROPERTY_NUM_RUNS,
235
+ })));
219
236
  }
220
237
  function fixture_n(requested) {
221
238
  return Math.min(Math.max(1, requested), MAX_N);
@@ -245,24 +262,24 @@ function fixture_n(requested) {
245
262
  * from the git history and remove the #186 pointer.
246
263
  */
247
264
  export function registerStoreAndReplay(ctx) {
248
- registerProperty(ctx, CATEGORY, "store-and-replay", "every messages/send lands in a live participant's capture buffer (basic-delivery-landing; #186 tracks C2 offline-replay)", Effect.scoped(Effect.gen(function* () {
265
+ registerProperty(ctx, CATEGORY, STORE_AND_REPLAY_PROPERTY, "every messages/send lands in a live participant's capture buffer (basic-delivery-landing; #186 tracks C2 offline-replay)", Effect.scoped(Effect.gen(function* () {
249
266
  const fixture = yield* acquireConversation(ctx, 1, "sr").pipe(Effect.mapError((e) => new PropertyInvariantViolation({
250
267
  category: CATEGORY,
251
- name: "store-and-replay",
268
+ name: STORE_AND_REPLAY_PROPERTY,
252
269
  reason: `fixture: ${e}`,
253
270
  })));
254
271
  const participant = fixture.participants[0];
255
272
  if (participant === undefined) {
256
273
  return yield* Effect.fail(new PropertyInvariantViolation({
257
274
  category: CATEGORY,
258
- name: "store-and-replay",
275
+ name: STORE_AND_REPLAY_PROPERTY,
259
276
  reason: "fixture missing participant",
260
277
  }));
261
278
  }
262
279
  const sent = 3;
263
280
  for (let i = 0; i < sent; i++) {
264
281
  yield* fixture.owner.client
265
- .sendRpc(MessagesSend.name, {
282
+ .sendRpc(MessagesSend, {
266
283
  conversationId: fixture.conversationId,
267
284
  parts: [{ type: "text", text: `sr-${i}` }],
268
285
  })
@@ -271,13 +288,13 @@ export function registerStoreAndReplay(ctx) {
271
288
  yield* Effect.sleep("350 millis");
272
289
  const snap = yield* participant.client.snapshot;
273
290
  const delivered = snap.filter((s) => s.kind === "inbound" &&
274
- s.frame?.type === "event" &&
275
- typeof s.frame.event === "string" &&
276
- s.frame.event.includes("message")).length;
291
+ s.frame !== null &&
292
+ isNotificationFrame(s.frame) &&
293
+ s.frame.method.includes("message")).length;
277
294
  if (delivered < sent) {
278
295
  return yield* Effect.fail(new PropertyInvariantViolation({
279
296
  category: CATEGORY,
280
- name: "store-and-replay",
297
+ name: STORE_AND_REPLAY_PROPERTY,
281
298
  reason: `sent ${sent}, live participant observed ${delivered}`,
282
299
  }));
283
300
  }
@@ -290,22 +307,24 @@ export function registerPayloadOpacity(ctx) {
290
307
  fc
291
308
  .string({ minLength: 4, maxLength: 24 })
292
309
  .filter((s) => !/[\\" \n\r\t]/.test(s)), (text) => Effect.runPromise(Effect.scoped(Effect.gen(function* () {
293
- const fixture = yield* acquireConversation(ctx, 1, "po").pipe(Effect.mapError((e) => new Error(e)));
310
+ const fixture = yield* acquireConversation(ctx, 1, "po").pipe(Effect.mapError((e) => violation("payload-opacity", `fixture: ${e}`)));
294
311
  const participant = fixture.participants[0];
295
312
  if (participant === undefined)
296
313
  return false;
297
- yield* fixture.owner.client
298
- .sendRpc(MessagesSend.name, {
314
+ yield* fixture.owner.client.sendRpc(MessagesSend, {
299
315
  conversationId: fixture.conversationId,
300
316
  parts: [{ type: "text", text }],
301
- })
302
- .pipe(Effect.either);
317
+ });
303
318
  yield* Effect.sleep("250 millis");
304
319
  const snap = yield* participant.client.snapshot;
305
320
  return snap.some((s) => s.kind === "inbound" &&
306
- s.frame?.type === "event" &&
321
+ s.frame !== null &&
322
+ isNotificationFrame(s.frame) &&
307
323
  s.raw.includes(text));
308
- })).pipe(Effect.catchAll(() => Effect.succeed(false))))), { seed: ctx.seed, numRuns: ctx.opts.numRuns ?? 3 })));
324
+ })).pipe(Effect.catchAll(() => Effect.succeed(false))))), {
325
+ seed: ctx.seed,
326
+ numRuns: ctx.opts.numRuns ?? DEFAULT_PROPERTY_NUM_RUNS,
327
+ })));
309
328
  }
310
329
  /**
311
330
  * Hook-gated delivery — admission verbs are awaitable, the verdict
@@ -332,13 +351,11 @@ export function registerPayloadOpacity(ctx) {
332
351
  export function registerHookGatedDelivery(ctx) {
333
352
  registerProperty(ctx, CATEGORY, "hook-gated-delivery", "deny drops; patch mutates recipient view; attached conv enters hooks", Effect.scoped(Effect.gen(function* () {
334
353
  const fixture = yield* acquireAppSessionFixture(ctx, "hgd", "hook-gated-delivery").pipe(Effect.either);
335
- if (fixture._tag === "Left") {
336
- return yield* Effect.fail(fixture.left);
337
- }
354
+ yield* requireRight(fixture, (error) => error);
338
355
  // Codex review (#327, finding 4): the protocol fixture cannot
339
356
  // drive the deny/patch/attach scenarios end-to-end (no DB seam
340
357
  // to inspect the recipient view; `apps/attachConversation` is a
341
- // c2s RPC but the assertion needs a server-internal observation
358
+ // client-originated RPC but the assertion needs a server-internal observation
342
359
  // the conformance contract does not expose). When a future
343
360
  // fixture extension makes apps/create reachable, surface a
344
361
  // typed Deferred so the suite reports honest coverage instead
@@ -363,9 +380,7 @@ export function registerHookGatedDelivery(ctx) {
363
380
  export function registerMultiAppFifoShortCircuit(ctx) {
364
381
  registerProperty(ctx, CATEGORY, "multi-app-fifo-short-circuit", "two apps; first denies; second hook is NOT invoked", Effect.scoped(Effect.gen(function* () {
365
382
  const fixture = yield* acquireAppSessionFixture(ctx, "mfs", "multi-app-fifo-short-circuit").pipe(Effect.either);
366
- if (fixture._tag === "Left") {
367
- return yield* Effect.fail(fixture.left);
368
- }
383
+ yield* requireRight(fixture, (error) => error);
369
384
  // Codex review (#327, finding 5): once apps/create succeeds, the
370
385
  // FIFO short-circuit assertion requires registering a SECOND
371
386
  // app on the same hook and observing the second handler is NOT
@@ -393,12 +408,11 @@ function acquireAppSessionFixture(ctx, namePrefix, propertyName) {
393
408
  defaultTimeoutMs: DEFAULT_TIMEOUT_MS,
394
409
  captureCapacity: DEFAULT_CAPTURE_CAPACITY,
395
410
  }).pipe(Effect.mapError((e) => unavailable(`app client acquire: ${String(e)}`)));
396
- const appId = `${namePrefix}-${Date.now().toString(36)}`;
397
- const registerOutcome = yield* sendUntypedRpc(appClient, AppsRegister.name, {
411
+ const appId = `${namePrefix}-${Date.now().toString(DATE_ID_RADIX)}`;
412
+ const registerOutcome = yield* sendUntypedRpc(appClient, AppsRegister, {
398
413
  manifest: {
399
414
  appId,
400
415
  name: `Hook-gated app ${appId}`,
401
- permissions: { required: [], optional: [] },
402
416
  conversations: [
403
417
  { key: "main", name: "Main", participantFilter: "all" },
404
418
  ],
@@ -408,9 +422,7 @@ function acquireAppSessionFixture(ctx, namePrefix, propertyName) {
408
422
  },
409
423
  },
410
424
  }).pipe(Effect.either);
411
- if (registerOutcome._tag === "Left") {
412
- return yield* Effect.fail(unavailable(`apps/register failed: ${registerOutcome.left._tag}`));
413
- }
425
+ yield* requireRight(registerOutcome, (error) => unavailable(`apps/register failed: ${error._tag}`));
414
426
  const senderAgent = yield* registerTestAgent({
415
427
  baseUrl: ctx.realServer.baseUrl,
416
428
  name: `${namePrefix}-sender`,
@@ -423,16 +435,14 @@ function acquireAppSessionFixture(ctx, namePrefix, propertyName) {
423
435
  captureCapacity: DEFAULT_CAPTURE_CAPACITY,
424
436
  }).pipe(Effect.mapError((e) => unavailable(`sender client acquire: ${String(e)}`)));
425
437
  const createOutcome = yield* senderClient
426
- .sendRpc(AppsCreate.name, { appId, invitedAgentIds: [] })
438
+ .sendRpc(AppsCreate, { appId, invitedAgentIds: [] })
427
439
  .pipe(Effect.either);
428
- if (createOutcome._tag === "Left") {
429
- // Most common cause: owner_user_id is null on the sender (see
430
- // app-host.ts:629). The default `startCoreTestServer` does not
431
- // configure `devModeUserId`; B.9 fills the gap via DB seeding.
432
- return yield* Effect.fail(unavailable(`apps/create failed (likely sender owner_user_id null; B.9 covers via DB seeding): ${createOutcome.left._tag}`));
433
- }
434
- const session = createOutcome.right
435
- .session;
440
+ const createResult = yield* requireRight(createOutcome, (error) => unavailable(
441
+ // Most common cause: owner_user_id is null on the sender (see
442
+ // app-host.ts:629). The default `startCoreTestServer` does not
443
+ // configure `devModeUserId`; B.9 fills the gap via DB seeding.
444
+ `apps/create failed (likely sender owner_user_id null; B.9 covers via DB seeding): ${error._tag}`));
445
+ const session = createResult.session;
436
446
  const sessionId = session?.id;
437
447
  if (typeof sessionId !== "string" || sessionId.length === 0) {
438
448
  return yield* Effect.fail(unavailable(`apps/create returned no session.id`));
@@ -462,20 +472,17 @@ function acquireAppSessionCloseFixture(ctx) {
462
472
  defaultTimeoutMs: DEFAULT_TIMEOUT_MS,
463
473
  captureCapacity: DEFAULT_CAPTURE_CAPACITY,
464
474
  }).pipe(Effect.mapError((e) => unavailable(`app client acquire: ${String(e)}`)));
465
- const appId = `close-life-${Date.now().toString(36)}`;
466
- const registerOutcome = yield* sendUntypedRpc(appClient, AppsRegister.name, {
475
+ const appId = `close-life-${Date.now().toString(DATE_ID_RADIX)}`;
476
+ const registerOutcome = yield* sendUntypedRpc(appClient, AppsRegister, {
467
477
  manifest: {
468
478
  appId,
469
479
  name: `Close lifecycle app ${appId}`,
470
- permissions: { required: [], optional: [] },
471
480
  conversations: [
472
481
  { key: "main", name: "Main", participantFilter: "all" },
473
482
  ],
474
483
  },
475
484
  }).pipe(Effect.either);
476
- if (registerOutcome._tag === "Left") {
477
- return yield* Effect.fail(unavailable(`apps/register failed: ${registerOutcome.left._tag}`));
478
- }
485
+ yield* requireRight(registerOutcome, (error) => unavailable(`apps/register failed: ${error._tag}`));
479
486
  const initiatorAgent = yield* registerTestAgent({
480
487
  baseUrl: ctx.realServer.baseUrl,
481
488
  name: "clinit",
@@ -501,44 +508,42 @@ function acquireAppSessionCloseFixture(ctx) {
501
508
  captureCapacity: DEFAULT_CAPTURE_CAPACITY,
502
509
  }).pipe(Effect.mapError((e) => unavailable(`invitee client acquire: ${String(e)}`)));
503
510
  const createOutcome = yield* initiatorClient
504
- .sendRpc(AppsCreate.name, {
511
+ .sendRpc(AppsCreate, {
505
512
  appId,
506
513
  invitedAgentIds: [inviteeAgent.agentId],
507
514
  })
508
515
  .pipe(Effect.either);
509
- if (createOutcome._tag === "Left") {
510
- return yield* Effect.fail(unavailable(`apps/create failed (likely agents lack owner_user_id): ${createOutcome.left._tag}`));
511
- }
512
- const session = createOutcome.right.session;
516
+ const createResult = yield* requireRight(createOutcome, (error) => unavailable(`apps/create failed (likely agents lack owner_user_id): ${error._tag}`));
517
+ const session = createResult.session;
513
518
  const sessionId = session?.id;
514
519
  const mainConversationId = session?.conversations?.["main"];
515
520
  if (typeof sessionId !== "string" ||
516
521
  typeof mainConversationId !== "string") {
517
- return yield* Effect.fail(violation(propertyName, `apps/create response missing session id or main conversation: ${JSON.stringify(createOutcome.right)}`));
522
+ return yield* Effect.fail(violation(propertyName, `apps/create response missing session id or main conversation: ${JSON.stringify(createResult)}`));
518
523
  }
519
524
  return {
520
525
  initiator: { agent: initiatorAgent, client: initiatorClient },
521
526
  invitee: { agent: inviteeAgent, client: inviteeClient },
522
527
  sessionId,
523
- conversationId: mainConversationId,
528
+ conversationId: makeConversationId(mainConversationId),
524
529
  };
525
530
  });
526
531
  }
527
532
  /** Task-boundary isolation — conversation A's events don't leak into B. */
528
533
  export function registerTaskBoundaryIsolation(ctx) {
529
- registerProperty(ctx, CATEGORY, "task-boundary-isolation", "participants in conversation B observe zero leaks from conversation A", Effect.scoped(Effect.gen(function* () {
534
+ registerProperty(ctx, CATEGORY, TASK_BOUNDARY_ISOLATION_PROPERTY, "participants in conversation B observe zero leaks from conversation A", Effect.scoped(Effect.gen(function* () {
530
535
  const fxA = yield* acquireConversation(ctx, 1, "iso-a").pipe(Effect.mapError((e) => new PropertyInvariantViolation({
531
536
  category: CATEGORY,
532
- name: "task-boundary-isolation",
537
+ name: TASK_BOUNDARY_ISOLATION_PROPERTY,
533
538
  reason: `fixture A: ${e}`,
534
539
  })));
535
540
  const fxB = yield* acquireConversation(ctx, 1, "iso-b").pipe(Effect.mapError((e) => new PropertyInvariantViolation({
536
541
  category: CATEGORY,
537
- name: "task-boundary-isolation",
542
+ name: TASK_BOUNDARY_ISOLATION_PROPERTY,
538
543
  reason: `fixture B: ${e}`,
539
544
  })));
540
545
  yield* fxA.owner.client
541
- .sendRpc(MessagesSend.name, {
546
+ .sendRpc(MessagesSend, {
542
547
  conversationId: fxA.conversationId,
543
548
  parts: [{ type: "text", text: "iso-leak-canary" }],
544
549
  })
@@ -552,7 +557,7 @@ export function registerTaskBoundaryIsolation(ctx) {
552
557
  if (leaked) {
553
558
  return yield* Effect.fail(new PropertyInvariantViolation({
554
559
  category: CATEGORY,
555
- name: "task-boundary-isolation",
560
+ name: TASK_BOUNDARY_ISOLATION_PROPERTY,
556
561
  reason: `conversation ${fxA.conversationId} leaked into outsider ${outsider.agent.agentId}`,
557
562
  }));
558
563
  }
@@ -572,33 +577,23 @@ export function registerConversationLifecycle(ctx) {
572
577
  registerProperty(ctx, CATEGORY, CONVERSATION_LIFECYCLE_PROPERTY, "create/send/update/archive/unarchive lifecycle is observable and enforced", Effect.scoped(Effect.gen(function* () {
573
578
  const fixture = yield* acquirePropertyConversation(ctx, CONVERSATION_LIFECYCLE_PROPERTY, "life");
574
579
  const participant = yield* firstParticipant(fixture, CONVERSATION_LIFECYCLE_PROPERTY);
575
- yield* waitForConversationCreatedEvent(participant, fixture.conversationId, CONVERSATION_LIFECYCLE_PROPERTY);
580
+ yield* waitForConversationCreatedNotification(participant, fixture.conversationId, CONVERSATION_LIFECYCLE_PROPERTY);
576
581
  const firstSend = yield* sendText(fixture.owner, fixture.conversationId, "lifecycle-before-update").pipe(Effect.either);
577
- if (firstSend._tag === "Left") {
578
- return yield* Effect.fail(violation(CONVERSATION_LIFECYCLE_PROPERTY, `messages/send failed before archive: ${firstSend.left._tag}`));
579
- }
580
- yield* waitForMessageReceivedEvent(participant, fixture.conversationId, CONVERSATION_LIFECYCLE_PROPERTY);
582
+ yield* requireRight(firstSend, (error) => violation(CONVERSATION_LIFECYCLE_PROPERTY, `messages/send failed before archive: ${error._tag}`));
583
+ yield* waitForMessageReceivedNotification(participant, fixture.conversationId, CONVERSATION_LIFECYCLE_PROPERTY);
581
584
  const updatedName = `Lifecycle ${ctx.seed}`;
582
585
  const update = yield* updateConversationName(fixture.owner, fixture.conversationId, updatedName).pipe(Effect.either);
583
- if (update._tag === "Left") {
584
- return yield* Effect.fail(violation(CONVERSATION_LIFECYCLE_PROPERTY, `conversations/update failed: ${update.left._tag}`));
585
- }
586
- yield* waitForConversationUpdatedEvent(participant, fixture.conversationId, updatedName, CONVERSATION_LIFECYCLE_PROPERTY);
586
+ yield* requireRight(update, (error) => violation(CONVERSATION_LIFECYCLE_PROPERTY, `conversations/update failed: ${error._tag}`));
587
+ yield* waitForConversationUpdatedNotification(participant, fixture.conversationId, updatedName, CONVERSATION_LIFECYCLE_PROPERTY);
587
588
  const archive = yield* archiveConversation(fixture.owner, fixture.conversationId).pipe(Effect.either);
588
- if (archive._tag === "Left") {
589
- return yield* Effect.fail(violation(CONVERSATION_LIFECYCLE_PROPERTY, `archive failed: ${archive.left._tag}`));
590
- }
589
+ yield* requireRight(archive, (error) => violation(CONVERSATION_LIFECYCLE_PROPERTY, `archive failed: ${error._tag}`));
591
590
  yield* waitForArchivedEvent(participant, fixture.conversationId, fixture.owner.agent.agentId, CONVERSATION_LIFECYCLE_PROPERTY);
592
591
  yield* assertConversationRejectsMessages(participant, fixture.conversationId, CONVERSATION_LIFECYCLE_PROPERTY);
593
592
  const unarchive = yield* unarchiveConversation(fixture.owner, fixture.conversationId).pipe(Effect.either);
594
- if (unarchive._tag === "Left") {
595
- return yield* Effect.fail(violation(CONVERSATION_LIFECYCLE_PROPERTY, `unarchive failed: ${unarchive.left._tag}`));
596
- }
593
+ yield* requireRight(unarchive, (error) => violation(CONVERSATION_LIFECYCLE_PROPERTY, `unarchive failed: ${error._tag}`));
597
594
  yield* waitForUnarchivedEvent(participant, fixture.conversationId, fixture.owner.agent.agentId, CONVERSATION_LIFECYCLE_PROPERTY);
598
595
  const resumedSend = yield* sendText(participant, fixture.conversationId, "lifecycle-after-unarchive").pipe(Effect.either);
599
- if (resumedSend._tag === "Left") {
600
- return yield* Effect.fail(violation(CONVERSATION_LIFECYCLE_PROPERTY, `messages/send failed after unarchive: ${resumedSend.left._tag}`));
601
- }
596
+ yield* requireRight(resumedSend, (error) => violation(CONVERSATION_LIFECYCLE_PROPERTY, `messages/send failed after unarchive: ${error._tag}`));
602
597
  })));
603
598
  }
604
599
  /**
@@ -610,16 +605,14 @@ export function registerAppSessionCloseLifecycle(ctx) {
610
605
  registerProperty(ctx, CATEGORY, APP_SESSION_CLOSE_LIFECYCLE_PROPERTY, "apps/closeSession archives app conversations and broadcasts session close", Effect.scoped(Effect.gen(function* () {
611
606
  const fixture = yield* acquireAppSessionCloseFixture(ctx);
612
607
  const close = yield* fixture.initiator.client
613
- .sendRpc(AppsCloseSession.name, { sessionId: fixture.sessionId })
608
+ .sendRpc(AppsCloseSession, { sessionId: fixture.sessionId })
614
609
  .pipe(Effect.either);
615
- if (close._tag === "Left") {
616
- return yield* Effect.fail(violation(APP_SESSION_CLOSE_LIFECYCLE_PROPERTY, `apps/closeSession failed: ${close.left._tag}`));
617
- }
618
- if (close.right.closed !== true) {
619
- return yield* Effect.fail(violation(APP_SESSION_CLOSE_LIFECYCLE_PROPERTY, `apps/closeSession returned unexpected result: ${JSON.stringify(close.right)}`));
610
+ const closeResult = yield* requireRight(close, (error) => violation(APP_SESSION_CLOSE_LIFECYCLE_PROPERTY, `apps/closeSession failed: ${error._tag}`));
611
+ if (closeResult.closed !== true) {
612
+ return yield* Effect.fail(violation(APP_SESSION_CLOSE_LIFECYCLE_PROPERTY, `apps/closeSession returned unexpected result: ${JSON.stringify(closeResult)}`));
620
613
  }
621
614
  yield* waitForArchivedEvent(fixture.invitee, fixture.conversationId, fixture.initiator.agent.agentId, APP_SESSION_CLOSE_LIFECYCLE_PROPERTY);
622
- yield* waitForAppSessionClosedEvent(fixture.invitee, fixture.sessionId, fixture.initiator.agent.agentId, APP_SESSION_CLOSE_LIFECYCLE_PROPERTY);
615
+ yield* waitForAppSessionClosedNotification(fixture.invitee, fixture.sessionId, fixture.initiator.agent.agentId, APP_SESSION_CLOSE_LIFECYCLE_PROPERTY);
623
616
  yield* assertConversationRejectsMessages(fixture.initiator, fixture.conversationId, APP_SESSION_CLOSE_LIFECYCLE_PROPERTY);
624
617
  })));
625
618
  }
@@ -636,20 +629,14 @@ export function registerArchiveLifecycle(ctx) {
636
629
  const fixture = yield* acquirePropertyConversation(ctx, ARCHIVE_LIFECYCLE_PROPERTY, "arch");
637
630
  const participant = yield* firstParticipant(fixture, ARCHIVE_LIFECYCLE_PROPERTY);
638
631
  const archive = yield* archiveConversation(fixture.owner, fixture.conversationId).pipe(Effect.either);
639
- if (archive._tag === "Left") {
640
- return yield* Effect.fail(violation(ARCHIVE_LIFECYCLE_PROPERTY, `archive failed: ${archive.left._tag}`));
641
- }
632
+ yield* requireRight(archive, (error) => violation(ARCHIVE_LIFECYCLE_PROPERTY, `archive failed: ${error._tag}`));
642
633
  yield* waitForArchivedEvent(participant, fixture.conversationId, fixture.owner.agent.agentId, ARCHIVE_LIFECYCLE_PROPERTY);
643
634
  yield* assertConversationRejectsMessages(participant, fixture.conversationId, ARCHIVE_LIFECYCLE_PROPERTY);
644
635
  const unarchive = yield* unarchiveConversation(fixture.owner, fixture.conversationId).pipe(Effect.either);
645
- if (unarchive._tag === "Left") {
646
- return yield* Effect.fail(violation(ARCHIVE_LIFECYCLE_PROPERTY, `unarchive failed: ${unarchive.left._tag}`));
647
- }
636
+ yield* requireRight(unarchive, (error) => violation(ARCHIVE_LIFECYCLE_PROPERTY, `unarchive failed: ${error._tag}`));
648
637
  yield* waitForUnarchivedEvent(participant, fixture.conversationId, fixture.owner.agent.agentId, ARCHIVE_LIFECYCLE_PROPERTY);
649
638
  const resumedSend = yield* sendText(participant, fixture.conversationId, "must-succeed-after-unarchive").pipe(Effect.either);
650
- if (resumedSend._tag === "Left") {
651
- return yield* Effect.fail(violation(ARCHIVE_LIFECYCLE_PROPERTY, `messages/send failed after unarchive: ${resumedSend.left._tag}`));
652
- }
639
+ yield* requireRight(resumedSend, (error) => violation(ARCHIVE_LIFECYCLE_PROPERTY, `messages/send failed after unarchive: ${error._tag}`));
653
640
  })));
654
641
  }
655
642
  //# sourceMappingURL=delivery.js.map