@mnemom/mnemom 0.17.34 → 0.17.36

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 (177) hide show
  1. package/dist/commands/agent-config.js +3 -0
  2. package/dist/commands/agent-goal.d.ts +8 -3
  3. package/dist/commands/agent-goal.js +22 -8
  4. package/dist/commands/agent-run.d.ts +14 -2
  5. package/dist/commands/agent-run.js +28 -7
  6. package/dist/commands/agent-share-render.js +1 -1
  7. package/dist/commands/agent-slack.js +32 -0
  8. package/dist/commands/durable-inbox.d.ts +51 -0
  9. package/dist/commands/durable-inbox.js +134 -0
  10. package/dist/commands/durable-questions.d.ts +64 -0
  11. package/dist/commands/durable-questions.js +161 -0
  12. package/dist/commands/scan.d.ts +13 -3
  13. package/dist/commands/scan.js +48 -10
  14. package/dist/durable/seat-proxy.d.ts +12 -1
  15. package/dist/durable/seat-proxy.js +55 -9
  16. package/dist/durable/seat-socket.d.ts +20 -2
  17. package/dist/durable/seat-socket.js +58 -0
  18. package/dist/durable/turn-chain.d.ts +8 -0
  19. package/dist/durable/turn-chain.js +25 -4
  20. package/dist/host/client.d.ts +41 -0
  21. package/dist/host/client.js +7 -0
  22. package/dist/host/control.d.ts +7 -0
  23. package/dist/host/control.js +15 -0
  24. package/dist/host/daemon.d.ts +20 -0
  25. package/dist/host/daemon.js +74 -1
  26. package/dist/host/inbox-delivery.d.ts +174 -0
  27. package/dist/host/inbox-delivery.js +453 -0
  28. package/dist/host/run.d.ts +18 -0
  29. package/dist/host/run.js +61 -0
  30. package/dist/host/s1-names.d.ts +2 -0
  31. package/dist/host/s1-names.js +2 -0
  32. package/dist/host/tmux.d.ts +7 -0
  33. package/dist/host/tmux.js +19 -0
  34. package/dist/index.js +62 -3
  35. package/dist/lib/api.d.ts +5 -0
  36. package/dist/lib/api.js +16 -0
  37. package/dist/lib/config.d.ts +7 -0
  38. package/dist/lib/config.js +21 -0
  39. package/dist/lib/durable/api.d.ts +11 -0
  40. package/dist/lib/durable/api.js +28 -3
  41. package/dist/lib/durable/gate.d.ts +1 -1
  42. package/dist/lib/durable/gate.js +8 -1
  43. package/dist/lib/durable/live.d.ts +5 -0
  44. package/dist/lib/durable/live.js +19 -0
  45. package/dist/lib/experimental.js +3 -0
  46. package/dist/lib/goal-api.d.ts +11 -4
  47. package/dist/lib/goal-api.js +4 -3
  48. package/dist/lib/launcher-config.d.ts +5 -0
  49. package/dist/lib/launcher-config.js +17 -2
  50. package/dist/lib/prompt.d.ts +4 -2
  51. package/dist/lib/prompt.js +15 -5
  52. package/dist/lib/runner/job.d.ts +2 -2
  53. package/dist/lib/runner/job.js +16 -3
  54. package/dist/lib/runner/pr-body.d.ts +17 -0
  55. package/dist/lib/runner/pr-body.js +42 -0
  56. package/dist/lib/runner/proxy.d.ts +18 -3
  57. package/dist/lib/runner/proxy.js +24 -5
  58. package/dist/lib/scan/pr-source.js +2 -0
  59. package/dist/lib/scan/record.d.ts +60 -9
  60. package/dist/lib/scan/record.js +157 -39
  61. package/dist/lib/scan/repo-picker.d.ts +32 -0
  62. package/dist/lib/scan/repo-picker.js +80 -0
  63. package/dist/lib/scan/report.d.ts +6 -8
  64. package/dist/lib/scan/report.js +21 -7
  65. package/dist/lib/scan/share.d.ts +5 -1
  66. package/dist/lib/scan/share.js +15 -5
  67. package/dist/lib/slack-durable.d.ts +123 -0
  68. package/dist/lib/slack-durable.js +237 -0
  69. package/dist/lib/slack-router.d.ts +7 -0
  70. package/dist/lib/slack-router.js +50 -4
  71. package/dist/vendor/durable-contract/index.js +992 -34
  72. package/dist/vendor/shared/durable-contract/admission.d.ts +81 -2
  73. package/dist/vendor/shared/durable-contract/admission.js +319 -2
  74. package/dist/vendor/shared/durable-contract/cli-surface.js +21 -0
  75. package/dist/vendor/shared/durable-contract/codes.d.ts +60 -0
  76. package/dist/vendor/shared/durable-contract/codes.js +22 -0
  77. package/dist/vendor/shared/durable-contract/events.d.ts +4 -2
  78. package/dist/vendor/shared/durable-contract/events.js +55 -1
  79. package/dist/vendor/shared/durable-contract/freeze-record.d.ts +14 -0
  80. package/dist/vendor/shared/durable-contract/inbox.d.ts +299 -0
  81. package/dist/vendor/shared/durable-contract/inbox.js +462 -0
  82. package/dist/vendor/shared/durable-contract/index.d.ts +2 -0
  83. package/dist/vendor/shared/durable-contract/index.js +2 -0
  84. package/dist/vendor/shared/durable-contract/question.d.ts +218 -0
  85. package/dist/vendor/shared/durable-contract/question.js +373 -0
  86. package/dist/vendor/shared/durable-contract/routes.d.ts +44 -2
  87. package/dist/vendor/shared/durable-contract/routes.js +43 -1
  88. package/dist/vendor/shared/durable-contract/turn.d.ts +15 -1
  89. package/dist/vendor/shared/durable-contract/turn.js +33 -1
  90. package/dist/vendor/shared/durable-contract/vectors.d.ts +45 -0
  91. package/dist/vendor/shared/durable-contract/vectors.js +49 -0
  92. package/node_modules/@mnemom/aip-verifier/LICENSE +190 -0
  93. package/node_modules/@mnemom/aip-verifier/dist/claim-lint-CVITIRcU.d.cts +478 -0
  94. package/node_modules/@mnemom/aip-verifier/dist/claim-lint-CVITIRcU.d.ts +478 -0
  95. package/node_modules/@mnemom/aip-verifier/dist/index.cjs +971 -0
  96. package/node_modules/@mnemom/aip-verifier/dist/index.cjs.map +1 -0
  97. package/node_modules/@mnemom/aip-verifier/dist/index.d.cts +330 -0
  98. package/node_modules/@mnemom/aip-verifier/dist/index.d.ts +330 -0
  99. package/node_modules/@mnemom/aip-verifier/dist/index.js +933 -0
  100. package/node_modules/@mnemom/aip-verifier/dist/index.js.map +1 -0
  101. package/node_modules/@mnemom/aip-verifier/dist/render-lines.cjs +879 -0
  102. package/node_modules/@mnemom/aip-verifier/dist/render-lines.cjs.map +1 -0
  103. package/node_modules/@mnemom/aip-verifier/dist/render-lines.d.cts +96 -0
  104. package/node_modules/@mnemom/aip-verifier/dist/render-lines.d.ts +96 -0
  105. package/node_modules/@mnemom/aip-verifier/dist/render-lines.js +875 -0
  106. package/node_modules/@mnemom/aip-verifier/dist/render-lines.js.map +1 -0
  107. package/node_modules/@mnemom/aip-verifier/package.json +86 -0
  108. package/node_modules/@noble/ed25519/LICENSE +21 -0
  109. package/node_modules/@noble/ed25519/README.md +371 -0
  110. package/node_modules/@noble/ed25519/index.d.ts +391 -0
  111. package/node_modules/@noble/ed25519/index.js +933 -0
  112. package/node_modules/@noble/ed25519/index.ts +1134 -0
  113. package/node_modules/@noble/ed25519/package.json +54 -0
  114. package/node_modules/@noble/hashes/LICENSE +21 -0
  115. package/node_modules/@noble/hashes/README.md +478 -0
  116. package/node_modules/@noble/hashes/_blake.d.ts +20 -0
  117. package/node_modules/@noble/hashes/_blake.js +59 -0
  118. package/node_modules/@noble/hashes/_md.d.ts +95 -0
  119. package/node_modules/@noble/hashes/_md.js +209 -0
  120. package/node_modules/@noble/hashes/_u64.d.ts +36 -0
  121. package/node_modules/@noble/hashes/_u64.js +77 -0
  122. package/node_modules/@noble/hashes/argon2.d.ts +148 -0
  123. package/node_modules/@noble/hashes/argon2.js +577 -0
  124. package/node_modules/@noble/hashes/blake1.d.ts +162 -0
  125. package/node_modules/@noble/hashes/blake1.js +630 -0
  126. package/node_modules/@noble/hashes/blake2.d.ts +203 -0
  127. package/node_modules/@noble/hashes/blake2.js +573 -0
  128. package/node_modules/@noble/hashes/blake3.d.ts +68 -0
  129. package/node_modules/@noble/hashes/blake3.js +310 -0
  130. package/node_modules/@noble/hashes/eskdf.d.ts +91 -0
  131. package/node_modules/@noble/hashes/eskdf.js +225 -0
  132. package/node_modules/@noble/hashes/hkdf.d.ts +70 -0
  133. package/node_modules/@noble/hashes/hkdf.js +152 -0
  134. package/node_modules/@noble/hashes/hmac.d.ts +50 -0
  135. package/node_modules/@noble/hashes/hmac.js +93 -0
  136. package/node_modules/@noble/hashes/index.d.ts +1 -0
  137. package/node_modules/@noble/hashes/index.js +34 -0
  138. package/node_modules/@noble/hashes/legacy.d.ts +107 -0
  139. package/node_modules/@noble/hashes/legacy.js +348 -0
  140. package/node_modules/@noble/hashes/package.json +91 -0
  141. package/node_modules/@noble/hashes/pbkdf2.d.ts +66 -0
  142. package/node_modules/@noble/hashes/pbkdf2.js +176 -0
  143. package/node_modules/@noble/hashes/scrypt.d.ts +98 -0
  144. package/node_modules/@noble/hashes/scrypt.js +304 -0
  145. package/node_modules/@noble/hashes/sha2.d.ts +176 -0
  146. package/node_modules/@noble/hashes/sha2.js +446 -0
  147. package/node_modules/@noble/hashes/sha3-addons.d.ts +533 -0
  148. package/node_modules/@noble/hashes/sha3-addons.js +973 -0
  149. package/node_modules/@noble/hashes/sha3.d.ts +208 -0
  150. package/node_modules/@noble/hashes/sha3.js +475 -0
  151. package/node_modules/@noble/hashes/src/_blake.ts +67 -0
  152. package/node_modules/@noble/hashes/src/_md.ts +227 -0
  153. package/node_modules/@noble/hashes/src/_u64.ts +111 -0
  154. package/node_modules/@noble/hashes/src/argon2.ts +693 -0
  155. package/node_modules/@noble/hashes/src/blake1.ts +677 -0
  156. package/node_modules/@noble/hashes/src/blake2.ts +648 -0
  157. package/node_modules/@noble/hashes/src/blake3.ts +344 -0
  158. package/node_modules/@noble/hashes/src/eskdf.ts +265 -0
  159. package/node_modules/@noble/hashes/src/hkdf.ts +161 -0
  160. package/node_modules/@noble/hashes/src/hmac.ts +130 -0
  161. package/node_modules/@noble/hashes/src/index.ts +33 -0
  162. package/node_modules/@noble/hashes/src/legacy.ts +361 -0
  163. package/node_modules/@noble/hashes/src/pbkdf2.ts +219 -0
  164. package/node_modules/@noble/hashes/src/scrypt.ts +375 -0
  165. package/node_modules/@noble/hashes/src/sha2.ts +486 -0
  166. package/node_modules/@noble/hashes/src/sha3-addons.ts +1157 -0
  167. package/node_modules/@noble/hashes/src/sha3.ts +525 -0
  168. package/node_modules/@noble/hashes/src/utils.ts +978 -0
  169. package/node_modules/@noble/hashes/src/webcrypto.ts +283 -0
  170. package/node_modules/@noble/hashes/utils.d.ts +560 -0
  171. package/node_modules/@noble/hashes/utils.js +687 -0
  172. package/node_modules/@noble/hashes/webcrypto.d.ts +121 -0
  173. package/node_modules/@noble/hashes/webcrypto.js +228 -0
  174. package/package.json +5 -2
  175. package/plugins/integrity-manifest.json +6 -2
  176. package/plugins/mnemom/hooks/hooks.json +12 -0
  177. package/plugins/mnemom/hooks/seat-ask.mjs +221 -0
@@ -15,7 +15,11 @@
15
15
  * 7 fenced (unless nofence) -> 409 durable_lease_fenced
16
16
  * 8 paused or non-admitting suspended -> 423 durable_session_stopped {state, state_reason}
17
17
  * 9 posture: attended admits; unattended -> 503 durable_guard_unavailable on a guard fault,
18
- * else 503 durable_unattended_unavailable (M1 refuses all unattended work).
18
+ * else 503 durable_unattended_unavailable, except (amendment 58) a locked pool session whose
19
+ * unfenced key holds its live lease, sealed with a charter, with a valid C08-R13 guard: that
20
+ * unattended chain is admitted, and G2's charter ceilings bind it as they bind an attended one;
21
+ * and (amendment 60) a locked homed session answering an open inbox message, its org's host
22
+ * policy and its owner both allowing unattended work, admitted the same way.
19
23
  * The one exception (wave-0 fix ruling 22): a POST /v1/messages/count_tokens with no chain= (header
20
24
  * absent, or no chain on the newest entry) runs steps 1-8 and skips step 9: it is admitted as
21
25
  * admit_unchained, with no chain row and no posture insert. Every other request is unchanged.
@@ -77,6 +81,18 @@ export interface ResolverDurable {
77
81
  charter_hash: string | null;
78
82
  guard_state: Record<string, unknown> | null;
79
83
  has_pointer: boolean;
84
+ /**
85
+ * Amendment 58, optional: the session has a dispatch_jobs row (a pool session). Absent reads as
86
+ * false, so an api that does not send it decides exactly as before.
87
+ */
88
+ pool?: boolean;
89
+ /** A1's charter field, optional here: the session's current charter version (amendment 58 (d)). */
90
+ charter_version?: number | null;
91
+ /**
92
+ * Amendment 60, optional: the sha256 hex of every inbox message delivered to this session and not
93
+ * yet acked or dead. Absent reads as none, so an api that does not send it decides as before.
94
+ */
95
+ inbox_open?: readonly string[] | null;
80
96
  }
81
97
  /** One resolver field against its spec (pure; exported for its direct test). */
82
98
  export declare function fieldOk(spec: FieldSpec, v: unknown): boolean;
@@ -99,6 +115,17 @@ export declare const GUARD_STATE_OK: Readonly<{
99
115
  export declare const GUARD_STATE_FAULT: Readonly<{
100
116
  spend_usd: string;
101
117
  }>;
118
+ /**
119
+ * Amendment 58 (e): the unattended pool branch's guard check, the C08-R13 shape the gateway guard
120
+ * enforces: schema_version 1, finite non-negative `turns` and `spend_usd` (numbers, never strings).
121
+ * Used for that branch only; guardStateOk and every other verdict are unchanged.
122
+ */
123
+ export declare function guardStateV1Ok(guard: Record<string, unknown> | null): boolean;
124
+ /**
125
+ * Amendment 58 (a)-(d): a locked pool session whose unfenced key holds its live lease (whatever
126
+ * DURABLE_ADMIT says), sealed with a charter of current version >= 1. The guard, (e), is separate.
127
+ */
128
+ export declare function unattendedPoolEligible(d: ResolverDurable): boolean;
102
129
  /** Whether DURABLE_ADMIT is honoured: only the exact bytes "nofence" (NOFENCE_M1, r3 I01). */
103
130
  export declare function nofenceHonoured(durableAdmit: string | undefined): boolean;
104
131
  export type AdmissionStep = "unknown_key" | "resolver_fault" | "revoked" | "identity" | "tracked" | "terminal" | "fenced" | "stopped" | "posture" | "admit";
@@ -136,6 +163,8 @@ export interface AdmissionInput {
136
163
  durableAdmit: string | undefined;
137
164
  /** The request (ruling 22). Absent: decided as any request other than an unchained count_tokens. */
138
165
  request?: AdmissionRequest;
166
+ /** Amendment 60: the newest x-mnemom-turn entry's `inbox=<sha>` value, when it carried one. */
167
+ inboxSha?: string | null;
139
168
  }
140
169
  export type AdmissionVerdict = {
141
170
  kind: "baseline_unknown_key";
@@ -151,7 +180,8 @@ export type AdmissionVerdict = {
151
180
  } | {
152
181
  kind: "admit";
153
182
  step: "admit";
154
- posture: "attended";
183
+ /** "unattended" only for amendment 58's pool branch. */
184
+ posture: Posture;
155
185
  guardFault: boolean;
156
186
  fenceSource: FenceSource;
157
187
  /** True when the session is effectively resuming: this request moves it to running. */
@@ -171,6 +201,15 @@ export type AdmissionVerdict = {
171
201
  };
172
202
  export declare const RESOLVER_FAULT: "fault";
173
203
  /** The admission function. Total: every input maps to exactly one verdict; it never throws. */
204
+ /** At most this many open inbox messages are read from a resolver answer (amendment 60 (e)). */
205
+ export declare const INBOX_OPEN_MAX = 64;
206
+ /**
207
+ * Amendment 60 (a)-(e): a locked homed session (no pool row) whose unfenced key holds its live
208
+ * lease, sealed with a charter of version >= 1, whose org host policy and owner both allow unattended
209
+ * work, answering an inbox message the api delivered and nobody has acked yet. The guard, (f), is
210
+ * separate, as in 58.
211
+ */
212
+ export declare function unattendedHomedInboxEligible(d: ResolverDurable, inboxSha: string | null | undefined): boolean;
174
213
  export declare function admit(input: AdmissionInput): AdmissionVerdict;
175
214
  export declare const ADMISSION_REQUEST_KINDS: readonly ["standard", "count_tokens_unchained"];
176
215
  export type AdmissionRequestKind = (typeof ADMISSION_REQUEST_KINDS)[number];
@@ -205,6 +244,25 @@ export declare function stateRows(): {
205
244
  }[];
206
245
  /** The full cross product over the admission dimensions, each row decided by `admit`. */
207
246
  export declare function admissionTruthTable(): TruthRow[];
247
+ /** The guard_state the amendment 58 vectors call valid (C08-R13 shape). */
248
+ export declare const GUARD_STATE_V1_OK: Readonly<Record<string, number>>;
249
+ export interface UnattendedPoolVector {
250
+ readonly name: string;
251
+ /** Overrides on the eligible base (fixtureResolver + pool, unattended, charter v1, a v1 guard). */
252
+ readonly over: Readonly<Partial<ResolverDurable>> & {
253
+ readonly pool?: boolean | undefined;
254
+ };
255
+ readonly nofence: boolean;
256
+ /** "admit" (unattended) or the refusal code. */
257
+ readonly outcome: string;
258
+ }
259
+ /**
260
+ * The base row admits an unattended chain; each other row flips exactly one condition. Every
261
+ * missing condition keeps the pre-58 refusal; (e) answers durable_guard_unavailable.
262
+ */
263
+ export declare const UNATTENDED_POOL_VECTORS: readonly UnattendedPoolVector[];
264
+ /** Decide one amendment 58 vector (the posture is the resolver's, as the gateway passes it). */
265
+ export declare function decideUnattendedPoolVector(v: UnattendedPoolVector): AdmissionVerdict;
208
266
  /** Golden vectors: a 3-dim toy sweep (every line) and C06 SWEEP_A (count, first 3 lines, digest). */
209
267
  export declare const ADMIT_SWEEP_VECTORS_PATH = "src/vectors/admit-sweep-vectors.json";
210
268
  /**
@@ -238,3 +296,24 @@ export declare function admitSweepDigest(sweep: AdmitSweep): Promise<{
238
296
  tuples: number;
239
297
  verdicts_sha256: string;
240
298
  }>;
299
+ /** The inbox message the amendment 60 vectors answer: sha256 hex, open on the base row. */
300
+ export declare const INBOX_SHA_FIXTURE: string;
301
+ export interface HomedInboxVector {
302
+ readonly name: string;
303
+ /** Overrides on the eligible base (fixtureResolver + unattended, charter v1, open inbox). */
304
+ readonly over: Readonly<Partial<ResolverDurable>> & {
305
+ readonly pool?: boolean | undefined;
306
+ };
307
+ /** The newest turn entry's inbox value (base: INBOX_SHA_FIXTURE). */
308
+ readonly inboxSha?: string | null;
309
+ readonly nofence: boolean;
310
+ /** "admit" (unattended) or the refusal code. */
311
+ readonly outcome: string;
312
+ }
313
+ /**
314
+ * The base row admits an unattended inbox turn on a homed session; each other row flips exactly one
315
+ * condition. Every missing condition keeps the pre-60 refusal; (f) answers durable_guard_unavailable.
316
+ */
317
+ export declare const HOMED_INBOX_VECTORS: readonly HomedInboxVector[];
318
+ /** Decide one amendment 60 vector (the posture is the resolver's, as the gateway passes it). */
319
+ export declare function decideHomedInboxVector(v: HomedInboxVector): AdmissionVerdict;
@@ -16,7 +16,11 @@
16
16
  * 7 fenced (unless nofence) -> 409 durable_lease_fenced
17
17
  * 8 paused or non-admitting suspended -> 423 durable_session_stopped {state, state_reason}
18
18
  * 9 posture: attended admits; unattended -> 503 durable_guard_unavailable on a guard fault,
19
- * else 503 durable_unattended_unavailable (M1 refuses all unattended work).
19
+ * else 503 durable_unattended_unavailable, except (amendment 58) a locked pool session whose
20
+ * unfenced key holds its live lease, sealed with a charter, with a valid C08-R13 guard: that
21
+ * unattended chain is admitted, and G2's charter ceilings bind it as they bind an attended one;
22
+ * and (amendment 60) a locked homed session answering an open inbox message, its org's host
23
+ * policy and its owner both allowing unattended work, admitted the same way.
20
24
  * The one exception (wave-0 fix ruling 22): a POST /v1/messages/count_tokens with no chain= (header
21
25
  * absent, or no chain on the newest entry) runs steps 1-8 and skips step 9: it is admitted as
22
26
  * admit_unchained, with no chain row and no posture insert. Every other request is unchanged.
@@ -52,7 +56,8 @@ export const RESOLVER_SCHEMA = {
52
56
  },
53
57
  epoch: { type: "integer", nullable: false },
54
58
  fenced: { type: "boolean", nullable: false },
55
- agent_id: { type: "uuid", nullable: false },
59
+ // The opaque agents.id text, e.g. "mnm-<hex>" (ruling 33.29), never a uuid.
60
+ agent_id: { type: "string", nullable: false },
56
61
  home_cell: { type: "enum", nullable: false, values: CANONICAL_CELL_IDS },
57
62
  posture: {
58
63
  type: "enum",
@@ -141,6 +146,30 @@ export const GUARD_STATE_OK = Object.freeze({ spend_usd: 0 });
141
146
  export const GUARD_STATE_FAULT = Object.freeze({
142
147
  spend_usd: "unparseable",
143
148
  });
149
+ /**
150
+ * Amendment 58 (e): the unattended pool branch's guard check, the C08-R13 shape the gateway guard
151
+ * enforces: schema_version 1, finite non-negative `turns` and `spend_usd` (numbers, never strings).
152
+ * Used for that branch only; guardStateOk and every other verdict are unchanged.
153
+ */
154
+ export function guardStateV1Ok(guard) {
155
+ if (guard === null || guard.schema_version !== 1)
156
+ return false;
157
+ return [guard.turns, guard.spend_usd].every((v) => typeof v === "number" && Number.isFinite(v) && v >= 0);
158
+ }
159
+ /**
160
+ * Amendment 58 (a)-(d): a locked pool session whose unfenced key holds its live lease (whatever
161
+ * DURABLE_ADMIT says), sealed with a charter of current version >= 1. The guard, (e), is separate.
162
+ */
163
+ export function unattendedPoolEligible(d) {
164
+ return (d.durable_mode === "locked" &&
165
+ d.pool === true &&
166
+ !d.fenced &&
167
+ d.lease_executor_id !== null &&
168
+ (d.effective_state === "running" || d.effective_state === "resuming") &&
169
+ d.sealed &&
170
+ Number.isSafeInteger(d.charter_version) &&
171
+ d.charter_version >= 1);
172
+ }
144
173
  /** Whether DURABLE_ADMIT is honoured: only the exact bytes "nofence" (NOFENCE_M1, r3 I01). */
145
174
  export function nofenceHonoured(durableAdmit) {
146
175
  return durableAdmit === NOFENCE_ADMIT_VALUE;
@@ -195,6 +224,32 @@ export function isUnchainedCountTokens(r) {
195
224
  }
196
225
  export const RESOLVER_FAULT = "fault";
197
226
  /** The admission function. Total: every input maps to exactly one verdict; it never throws. */
227
+ /** At most this many open inbox messages are read from a resolver answer (amendment 60 (e)). */
228
+ export const INBOX_OPEN_MAX = 64;
229
+ const INBOX_SHA_RE = /^[0-9a-f]{64}$/;
230
+ /**
231
+ * Amendment 60 (a)-(e): a locked homed session (no pool row) whose unfenced key holds its live
232
+ * lease, sealed with a charter of version >= 1, whose org host policy and owner both allow unattended
233
+ * work, answering an inbox message the api delivered and nobody has acked yet. The guard, (f), is
234
+ * separate, as in 58.
235
+ */
236
+ export function unattendedHomedInboxEligible(d, inboxSha) {
237
+ const open = d.inbox_open;
238
+ return (d.durable_mode === "locked" &&
239
+ d.pool !== true &&
240
+ !d.fenced &&
241
+ d.lease_executor_id !== null &&
242
+ (d.effective_state === "running" || d.effective_state === "resuming") &&
243
+ d.sealed &&
244
+ Number.isSafeInteger(d.charter_version) &&
245
+ d.charter_version >= 1 &&
246
+ d.host_unattended === true &&
247
+ typeof inboxSha === "string" &&
248
+ INBOX_SHA_RE.test(inboxSha) &&
249
+ Array.isArray(open) &&
250
+ open.length <= INBOX_OPEN_MAX &&
251
+ open.includes(inboxSha));
252
+ }
198
253
  export function admit(input) {
199
254
  const fenceSource = nofenceHonoured(input.durableAdmit) ? "nofence" : "fresh";
200
255
  const posture = input.posture ?? "unattended";
@@ -240,6 +295,24 @@ export function admit(input) {
240
295
  writes: false,
241
296
  };
242
297
  if (posture === "unattended") {
298
+ if (unattendedPoolEligible(d) || unattendedHomedInboxEligible(d, input.inboxSha)) {
299
+ if (guardStateV1Ok(d.guard_state))
300
+ return {
301
+ kind: "admit",
302
+ step: "admit",
303
+ posture: "unattended",
304
+ guardFault: false,
305
+ fenceSource,
306
+ helloTransition: false,
307
+ };
308
+ return {
309
+ kind: "refuse",
310
+ step: "posture",
311
+ code: "durable_guard_unavailable",
312
+ posture,
313
+ fenceSource,
314
+ };
315
+ }
243
316
  return {
244
317
  kind: "refuse",
245
318
  step: "posture",
@@ -396,6 +469,128 @@ export function admissionTruthTable() {
396
469
  }
397
470
  return out;
398
471
  }
472
+ // ---- Amendment 58 vectors: the unattended pool branch, one condition flipped per row -------------
473
+ /** The guard_state the amendment 58 vectors call valid (C08-R13 shape). */
474
+ export const GUARD_STATE_V1_OK = Object.freeze({
475
+ schema_version: 1,
476
+ turns: 0,
477
+ spend_usd: 0,
478
+ });
479
+ /**
480
+ * The base row admits an unattended chain; each other row flips exactly one condition. Every
481
+ * missing condition keeps the pre-58 refusal; (e) answers durable_guard_unavailable.
482
+ */
483
+ export const UNATTENDED_POOL_VECTORS = Object.freeze([
484
+ { name: "all hold: admitted unattended", over: {}, nofence: false, outcome: "admit" },
485
+ {
486
+ name: "all hold, resuming: admitted, no hello",
487
+ over: { effective_state: "resuming", state: "resuming" },
488
+ nofence: false,
489
+ outcome: "admit",
490
+ },
491
+ {
492
+ name: "(b) pool absent",
493
+ over: { pool: undefined },
494
+ nofence: false,
495
+ outcome: "durable_unattended_unavailable",
496
+ },
497
+ {
498
+ name: "(b) pool false",
499
+ over: { pool: false },
500
+ nofence: false,
501
+ outcome: "durable_unattended_unavailable",
502
+ },
503
+ {
504
+ name: "(c) fenced key under nofence",
505
+ over: { fenced: true },
506
+ nofence: true,
507
+ outcome: "durable_unattended_unavailable",
508
+ },
509
+ {
510
+ name: "(c) no lease executor",
511
+ over: { lease_executor_id: null },
512
+ nofence: false,
513
+ outcome: "durable_unattended_unavailable",
514
+ },
515
+ {
516
+ name: "(c) lease lapsed (detached)",
517
+ over: { effective_state: "detached" },
518
+ nofence: false,
519
+ outcome: "durable_unattended_unavailable",
520
+ },
521
+ {
522
+ name: "(d) not sealed",
523
+ over: { sealed: false },
524
+ nofence: false,
525
+ outcome: "durable_unattended_unavailable",
526
+ },
527
+ {
528
+ name: "(d) no charter version",
529
+ over: { charter_version: null },
530
+ nofence: false,
531
+ outcome: "durable_unattended_unavailable",
532
+ },
533
+ {
534
+ name: "(d) charter version 0",
535
+ over: { charter_version: 0 },
536
+ nofence: false,
537
+ outcome: "durable_unattended_unavailable",
538
+ },
539
+ {
540
+ name: "(d) charter version not an integer",
541
+ over: { charter_version: 1.5 },
542
+ nofence: false,
543
+ outcome: "durable_unattended_unavailable",
544
+ },
545
+ {
546
+ name: "(e) guard null",
547
+ over: { guard_state: null },
548
+ nofence: false,
549
+ outcome: "durable_guard_unavailable",
550
+ },
551
+ {
552
+ name: "(e) guard without schema_version",
553
+ over: { guard_state: { turns: 0, spend_usd: 0 } },
554
+ nofence: false,
555
+ outcome: "durable_guard_unavailable",
556
+ },
557
+ {
558
+ name: "(e) guard without turns",
559
+ over: { guard_state: { schema_version: 1, spend_usd: 0 } },
560
+ nofence: false,
561
+ outcome: "durable_guard_unavailable",
562
+ },
563
+ {
564
+ name: "(e) guard turns as a string",
565
+ over: { guard_state: { schema_version: 1, turns: "0", spend_usd: 0 } },
566
+ nofence: false,
567
+ outcome: "durable_guard_unavailable",
568
+ },
569
+ {
570
+ name: "attended on a pool session: unchanged",
571
+ over: { posture: "attended" },
572
+ nofence: false,
573
+ outcome: "admit",
574
+ },
575
+ ]);
576
+ /** Decide one amendment 58 vector (the posture is the resolver's, as the gateway passes it). */
577
+ export function decideUnattendedPoolVector(v) {
578
+ const base = {
579
+ posture: "unattended",
580
+ pool: true,
581
+ charter_version: 1,
582
+ guard_state: { ...GUARD_STATE_V1_OK },
583
+ };
584
+ const resolver = { ...fixtureResolver(base), ...v.over };
585
+ if (v.over.pool === undefined && "pool" in v.over)
586
+ delete resolver.pool;
587
+ return admit({
588
+ resolver,
589
+ pinAgentId: FIXTURE_AGENT,
590
+ posture: resolver.posture,
591
+ durableAdmit: v.nofence ? NOFENCE_ADMIT_VALUE : undefined,
592
+ });
593
+ }
399
594
  // ---- admit sweep digest (rulings 24.11, 24.11.1; C06-SWEEP-001/002) ----------------------------
400
595
  /** Golden vectors: a 3-dim toy sweep (every line) and C06 SWEEP_A (count, first 3 lines, digest). */
401
596
  export const ADMIT_SWEEP_VECTORS_PATH = "src/vectors/admit-sweep-vectors.json";
@@ -531,3 +726,125 @@ export async function admitSweepDigest(sweep) {
531
726
  const { tuples, text } = admitSweepText(sweep);
532
727
  return { tuples, verdicts_sha256: await sha256Hex(text) };
533
728
  }
729
+ // ---- Amendment 60 vectors: the homed inbox branch, one condition flipped per row ----------------
730
+ /** The inbox message the amendment 60 vectors answer: sha256 hex, open on the base row. */
731
+ export const INBOX_SHA_FIXTURE = "ab".repeat(32);
732
+ /**
733
+ * The base row admits an unattended inbox turn on a homed session; each other row flips exactly one
734
+ * condition. Every missing condition keeps the pre-60 refusal; (f) answers durable_guard_unavailable.
735
+ */
736
+ export const HOMED_INBOX_VECTORS = Object.freeze([
737
+ { name: "all hold: admitted unattended", over: {}, nofence: false, outcome: "admit" },
738
+ {
739
+ name: "all hold, resuming: admitted, no hello",
740
+ over: { effective_state: "resuming", state: "resuming" },
741
+ nofence: false,
742
+ outcome: "admit",
743
+ },
744
+ {
745
+ name: "(a) a pool session takes 58, not 60: still admitted",
746
+ over: { pool: true },
747
+ nofence: false,
748
+ outcome: "admit",
749
+ },
750
+ {
751
+ name: "(b) fenced key under nofence",
752
+ over: { fenced: true },
753
+ nofence: true,
754
+ outcome: "durable_unattended_unavailable",
755
+ },
756
+ {
757
+ name: "(b) no lease executor",
758
+ over: { lease_executor_id: null },
759
+ nofence: false,
760
+ outcome: "durable_unattended_unavailable",
761
+ },
762
+ {
763
+ name: "(b) lease lapsed (detached)",
764
+ over: { effective_state: "detached" },
765
+ nofence: false,
766
+ outcome: "durable_unattended_unavailable",
767
+ },
768
+ {
769
+ name: "(c) not sealed",
770
+ over: { sealed: false },
771
+ nofence: false,
772
+ outcome: "durable_unattended_unavailable",
773
+ },
774
+ {
775
+ name: "(c) no charter version",
776
+ over: { charter_version: null },
777
+ nofence: false,
778
+ outcome: "durable_unattended_unavailable",
779
+ },
780
+ {
781
+ name: "(d) host policy or the owner's opt-out says no",
782
+ over: { host_unattended: false },
783
+ nofence: false,
784
+ outcome: "durable_unattended_unavailable",
785
+ },
786
+ {
787
+ name: "(e) no inbox key on the newest entry",
788
+ over: {},
789
+ inboxSha: null,
790
+ nofence: false,
791
+ outcome: "durable_unattended_unavailable",
792
+ },
793
+ {
794
+ name: "(e) inbox sha not open (acked, dead or never delivered)",
795
+ over: { inbox_open: ["cd".repeat(32)] },
796
+ nofence: false,
797
+ outcome: "durable_unattended_unavailable",
798
+ },
799
+ {
800
+ name: "(e) inbox_open absent",
801
+ over: { inbox_open: undefined },
802
+ nofence: false,
803
+ outcome: "durable_unattended_unavailable",
804
+ },
805
+ {
806
+ name: "(e) inbox sha malformed",
807
+ over: { inbox_open: ["AB".repeat(32)] },
808
+ inboxSha: "AB".repeat(32),
809
+ nofence: false,
810
+ outcome: "durable_unattended_unavailable",
811
+ },
812
+ {
813
+ name: "(f) guard null",
814
+ over: { guard_state: null },
815
+ nofence: false,
816
+ outcome: "durable_guard_unavailable",
817
+ },
818
+ {
819
+ name: "(f) guard without schema_version",
820
+ over: { guard_state: { turns: 0, spend_usd: 0 } },
821
+ nofence: false,
822
+ outcome: "durable_guard_unavailable",
823
+ },
824
+ {
825
+ name: "attended on a homed session: unchanged",
826
+ over: { posture: "attended" },
827
+ inboxSha: null,
828
+ nofence: false,
829
+ outcome: "admit",
830
+ },
831
+ ]);
832
+ /** Decide one amendment 60 vector (the posture is the resolver's, as the gateway passes it). */
833
+ export function decideHomedInboxVector(v) {
834
+ const base = {
835
+ posture: "unattended",
836
+ charter_version: 1,
837
+ inbox_open: [INBOX_SHA_FIXTURE],
838
+ guard_state: { ...GUARD_STATE_V1_OK },
839
+ };
840
+ const resolver = { ...fixtureResolver(base), ...v.over };
841
+ if ("inbox_open" in v.over && v.over.inbox_open === undefined)
842
+ delete resolver.inbox_open;
843
+ return admit({
844
+ resolver,
845
+ pinAgentId: FIXTURE_AGENT,
846
+ posture: resolver.posture,
847
+ durableAdmit: v.nofence ? NOFENCE_ADMIT_VALUE : undefined,
848
+ inboxSha: "inboxSha" in v ? v.inboxSha : INBOX_SHA_FIXTURE,
849
+ });
850
+ }
@@ -64,6 +64,20 @@ export const M1_CLI_SURFACE = Object.freeze([
64
64
  // BACKBONE C4 (line 147: buildDurableLaunchSpec serves 'sessions adopt'); options: C14 spec
65
65
  // (`sessions adopt --dry-run --json`, `sessions adopt --own-agent`); ruling 32.33.
66
66
  entry(["agent", "sessions", "adopt"], ["--dry-run", "--json", "--own-agent"]),
67
+ // S1 amendment 61 (signed off by Wassim 2026-11-02): the owner's answer or dismissal of a locked
68
+ // session's question (own_answer, via coding_agent).
69
+ entry(["agent", "sessions", "answer"], ["--dismiss", "--json"]),
70
+ // S1 amendment 61: the session's questions to its owner (own_questions).
71
+ entry(["agent", "sessions", "questions"], ["--all", "--json"]),
72
+ // S1 amendment 60 (signed off by Wassim 2026-11-02): the owner door into a locked session's inbox. `send`
73
+ // posts own_inbox_send (owner credential, or an allowlisted agent's key named by --sender-key-env);
74
+ // --agent-id/--conversation address a session the caller cannot list (an allowlisted agent).
75
+ entry(["agent", "sessions", "send"], ["--agent-id", "--conversation", "--idempotency-key", "--json", "--sender-key-env"]),
76
+ // S1 amendment 60: the owner-managed inbox sender allowlist (own_inbox_senders, _sender_add, _sender_remove).
77
+ entry(["agent", "sessions", "senders"]),
78
+ entry(["agent", "sessions", "senders", "add"], ["--json", "--label"]),
79
+ entry(["agent", "sessions", "senders", "list"], ["--json"]),
80
+ entry(["agent", "sessions", "senders", "remove"], ["--json"]),
67
81
  // fixlines.ts launch_spec_change_sole_unlock (`mnemom agent sessions unlock <name>`); C11, C16 and
68
82
  // C17 specs; no source names an option; ruling 32.33.
69
83
  entry(["agent", "sessions", "unlock"]),
@@ -89,6 +103,13 @@ export const M1_CLI_SURFACE_BUILDERS = Object.freeze({
89
103
  "agent lock",
90
104
  "agent pause",
91
105
  "agent resume",
106
+ "agent sessions answer",
107
+ "agent sessions questions",
108
+ "agent sessions send",
109
+ "agent sessions senders",
110
+ "agent sessions senders add",
111
+ "agent sessions senders list",
112
+ "agent sessions senders remove",
92
113
  "agent sessions unlock",
93
114
  ]),
94
115
  C2: Object.freeze([
@@ -366,6 +366,66 @@ export declare const DURABLE_CODES: {
366
366
  readonly surfaces: readonly ["api"];
367
367
  readonly fields: readonly [];
368
368
  };
369
+ /** An agent sender with no live allowlist row for the recipient agent, set by the session's owner. */
370
+ readonly durable_inbox_not_allowlisted: {
371
+ readonly status: 403;
372
+ readonly surfaces: readonly ["api", "cli"];
373
+ readonly fields: readonly [];
374
+ };
375
+ /** The session cannot take inbox work: reason not_locked, ended, unsealed or unattended_off (host_unattended is not true, so §60 (e) could never admit the turn). */
376
+ readonly durable_inbox_closed: {
377
+ readonly status: 409;
378
+ readonly surfaces: readonly ["api", "cli"];
379
+ readonly fields: readonly ["reason"];
380
+ };
381
+ /** INBOX_OPEN_CAP messages are already open (admitted or delivered). */
382
+ readonly durable_inbox_full: {
383
+ readonly status: 429;
384
+ readonly surfaces: readonly ["api", "cli"];
385
+ readonly fields: readonly ["open", "cap"];
386
+ };
387
+ /** A send, allowlist, take or ack body outside its closed shape or limits; field names the first bad key (null: not an object). */
388
+ readonly durable_inbox_body_invalid: {
389
+ readonly status: 422;
390
+ readonly surfaces: readonly ["api", "cli"];
391
+ readonly fields: readonly ["field"];
392
+ };
393
+ /** An ack of a message not delivered to this session at this epoch with this sha. */
394
+ readonly durable_inbox_not_open: {
395
+ readonly status: 409;
396
+ readonly surfaces: readonly ["api"];
397
+ readonly fields: readonly [];
398
+ };
399
+ /** A sender identity or allowlist change the api refuses; reason is one of inbox.ts INBOX_SENDER_INVALID_REASONS. */
400
+ readonly durable_inbox_sender_invalid: {
401
+ readonly status: 422;
402
+ readonly surfaces: readonly ["api", "cli"];
403
+ readonly fields: readonly ["reason"];
404
+ };
405
+ /** An ask, poll, release or answer body outside its closed shape or limits; field names the first bad key. */
406
+ readonly durable_question_body_invalid: {
407
+ readonly status: 422;
408
+ readonly surfaces: readonly ["api", "cli"];
409
+ readonly fields: readonly ["field"];
410
+ };
411
+ /** No question with that approval_id on this session. */
412
+ readonly durable_question_not_found: {
413
+ readonly status: 404;
414
+ readonly surfaces: readonly ["api", "cli"];
415
+ readonly fields: readonly [];
416
+ };
417
+ /** The question is no longer open (answered, dismissed, expired); state names which. */
418
+ readonly durable_question_closed: {
419
+ readonly status: 409;
420
+ readonly surfaces: readonly ["api", "cli"];
421
+ readonly fields: readonly ["state"];
422
+ };
423
+ /** An ask while the session's open question is a different one (another question_sha); approval_id and state name it. Nothing is stored. */
424
+ readonly durable_question_busy: {
425
+ readonly status: 409;
426
+ readonly surfaces: readonly ["api", "cli"];
427
+ readonly fields: readonly ["approval_id", "state"];
428
+ };
369
429
  };
370
430
  export type DurableCode = keyof typeof DURABLE_CODES;
371
431
  export declare function isDurableCode(v: unknown): v is DurableCode;
@@ -176,6 +176,28 @@ export const DURABLE_CODES = {
176
176
  * versions, or no charter at all (a malformed body). The gateway refuses admission on it.
177
177
  */
178
178
  durable_charter_not_found: { status: 404, surfaces: ["api"], fields: [] },
179
+ // ---- api inbox, S1 amendment 60 (signed off by Wassim 2026-11-02; inbox.ts INBOX_REJECT_CODES) ----
180
+ /** An agent sender with no live allowlist row for the recipient agent, set by the session's owner. */
181
+ durable_inbox_not_allowlisted: { status: 403, surfaces: ["api", "cli"], fields: [] },
182
+ /** The session cannot take inbox work: reason not_locked, ended, unsealed or unattended_off (host_unattended is not true, so §60 (e) could never admit the turn). */
183
+ durable_inbox_closed: { status: 409, surfaces: ["api", "cli"], fields: ["reason"] },
184
+ /** INBOX_OPEN_CAP messages are already open (admitted or delivered). */
185
+ durable_inbox_full: { status: 429, surfaces: ["api", "cli"], fields: ["open", "cap"] },
186
+ /** A send, allowlist, take or ack body outside its closed shape or limits; field names the first bad key (null: not an object). */
187
+ durable_inbox_body_invalid: { status: 422, surfaces: ["api", "cli"], fields: ["field"] },
188
+ /** An ack of a message not delivered to this session at this epoch with this sha. */
189
+ durable_inbox_not_open: { status: 409, surfaces: ["api"], fields: [] },
190
+ /** A sender identity or allowlist change the api refuses; reason is one of inbox.ts INBOX_SENDER_INVALID_REASONS. */
191
+ durable_inbox_sender_invalid: { status: 422, surfaces: ["api", "cli"], fields: ["reason"] },
192
+ // ---- api questions, S1 amendment 61 (signed off by Wassim 2026-11-02; question.ts) ----
193
+ /** An ask, poll, release or answer body outside its closed shape or limits; field names the first bad key. */
194
+ durable_question_body_invalid: { status: 422, surfaces: ["api", "cli"], fields: ["field"] },
195
+ /** No question with that approval_id on this session. */
196
+ durable_question_not_found: { status: 404, surfaces: ["api", "cli"], fields: [] },
197
+ /** The question is no longer open (answered, dismissed, expired); state names which. */
198
+ durable_question_closed: { status: 409, surfaces: ["api", "cli"], fields: ["state"] },
199
+ /** An ask while the session's open question is a different one (another question_sha); approval_id and state name it. Nothing is stored. */
200
+ durable_question_busy: { status: 409, surfaces: ["api", "cli"], fields: ["approval_id", "state"] },
179
201
  };
180
202
  export function isDurableCode(v) {
181
203
  return typeof v === "string" && Object.prototype.hasOwnProperty.call(DURABLE_CODES, v);
@@ -30,9 +30,11 @@ export declare const DESIGN_EVENT_KINDS: {
30
30
  export declare const M1_EXCLUDED_KINDS: readonly ["intent.issued", "intent.committed", "intent.unknown", "intent.resolved", "intent.readmission_flagged", "context.note", "context.compacted", "inbox.acked"];
31
31
  /**
32
32
  * Every M1 kind (80) with its group, in §3.7 order, then the Doors amendment's three (rulings
33
- * 34.02, 34.06), appended so no existing index moves. Mirrors durable_event_kinds (parity test).
33
+ * 34.02, 34.06), executor.turn_continued, and inbox.acked (S1 amendment 60: M1 left it out, the
34
+ * inbox ack writes it; M1_EXCLUDED_KINDS stays the frozen M1 record), appended so no existing index
35
+ * moves. Mirrors durable_event_kinds (parity test).
34
36
  */
35
- export declare const DURABLE_EVENT_KINDS: readonly ["session.registered", "session.locked", "session.unlocked", "session.resumed", "session.detached", "session.parked", "session.suspended", "session.paused", "session.unpaused", "session.moved", "session.completed", "session.failed", "session.killed", "session.expired", "session.adopted", "seat.hello", "charter.sealed", "charter.amended", "charter.goal_sealed", "charter.card_drift", "profile.amended", "executor.upgraded", "attestation.passed", "attestation.failed", "lease.acquired", "lease.reclaimed", "lease.released", "lease.expired", "lease.fenced", "lease.zombie_call", "lease.stale_admit", "executor.enrolled", "executor.revoked", "executor.spawned", "executor.exited", "executor.contract_violation", "inbox.admitted", "inbox.rejected", "inbox.coalesced", "inbox.held_unsealed", "inbox.queued_for_home", "inbox.reverted", "inbox.delivered", "inbox.unmatched", "inbox.dead", "timer.set", "timer.fired", "timer.cancelled", "trigger.added", "trigger.removed", "trigger.fired", "trigger.suppressed", "trigger.over_cap", "wake.undelivered", "question.asked", "question.answered", "approval.requested", "approval.resolved", "approval.consumed", "approval.expired", "approval.superseded", "approval.single_person_override", "never.held", "chain.posture", "guard.refused", "guard.unavailable", "budget.reached", "grant.renewed", "grant.revoked", "verdict.violation", "identity.mismatch", "containment.pause", "containment.kill", "containment.auto_pause", "governance.degraded_admit", "governance.outage_mode_set", "policy.host_unattended_changed", "workspace.checkpointed", "rearm.recorded", "tip.signed", "session.ready", "session.waiting", "session.wait_cleared", "executor.turn_continued"];
37
+ export declare const DURABLE_EVENT_KINDS: readonly ["session.registered", "session.locked", "session.unlocked", "session.resumed", "session.detached", "session.parked", "session.suspended", "session.paused", "session.unpaused", "session.moved", "session.completed", "session.failed", "session.killed", "session.expired", "session.adopted", "seat.hello", "charter.sealed", "charter.amended", "charter.goal_sealed", "charter.card_drift", "profile.amended", "executor.upgraded", "attestation.passed", "attestation.failed", "lease.acquired", "lease.reclaimed", "lease.released", "lease.expired", "lease.fenced", "lease.zombie_call", "lease.stale_admit", "executor.enrolled", "executor.revoked", "executor.spawned", "executor.exited", "executor.contract_violation", "inbox.admitted", "inbox.rejected", "inbox.coalesced", "inbox.held_unsealed", "inbox.queued_for_home", "inbox.reverted", "inbox.delivered", "inbox.unmatched", "inbox.dead", "timer.set", "timer.fired", "timer.cancelled", "trigger.added", "trigger.removed", "trigger.fired", "trigger.suppressed", "trigger.over_cap", "wake.undelivered", "question.asked", "question.answered", "approval.requested", "approval.resolved", "approval.consumed", "approval.expired", "approval.superseded", "approval.single_person_override", "never.held", "chain.posture", "guard.refused", "guard.unavailable", "budget.reached", "grant.renewed", "grant.revoked", "verdict.violation", "identity.mismatch", "containment.pause", "containment.kill", "containment.auto_pause", "governance.degraded_admit", "governance.outage_mode_set", "policy.host_unattended_changed", "workspace.checkpointed", "rearm.recorded", "tip.signed", "session.ready", "session.waiting", "session.wait_cleared", "executor.turn_continued", "inbox.acked"];
36
38
  export type DurableEventKind = (typeof DURABLE_EVENT_KINDS)[number];
37
39
  export declare function isDurableEventKind(v: unknown): v is DurableEventKind;
38
40
  /**