@mnemom/mnemom 0.17.34-next.1 → 0.17.34-next.2

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 (195) hide show
  1. package/dist/base-url-proxy.mjs +18 -4
  2. package/dist/commands/agent-config.js +5 -1
  3. package/dist/commands/agent-doctor.d.ts +9 -0
  4. package/dist/commands/agent-doctor.js +4 -0
  5. package/dist/commands/agent-session.d.ts +1 -2
  6. package/dist/commands/agent-session.js +1 -2
  7. package/dist/commands/agent-setup.d.ts +6 -0
  8. package/dist/commands/agent-setup.js +12 -1
  9. package/dist/commands/agent.d.ts +11 -0
  10. package/dist/commands/agent.js +145 -46
  11. package/dist/commands/durable-doctor.d.ts +50 -0
  12. package/dist/commands/durable-doctor.js +186 -0
  13. package/dist/commands/durable-lock.d.ts +254 -0
  14. package/dist/commands/durable-lock.js +595 -0
  15. package/dist/commands/durable-sessions.d.ts +87 -0
  16. package/dist/commands/durable-sessions.js +303 -0
  17. package/dist/commands/durable-verbs.d.ts +116 -0
  18. package/dist/commands/durable-verbs.js +393 -0
  19. package/dist/durable/flock.d.ts +26 -0
  20. package/dist/durable/flock.js +80 -0
  21. package/dist/durable/launch-spec.d.ts +7 -1
  22. package/dist/durable/launch-spec.js +10 -3
  23. package/dist/durable/seat-proxy-entry.d.ts +11 -0
  24. package/dist/durable/seat-proxy-entry.js +25 -0
  25. package/dist/durable/seat-proxy.d.ts +107 -0
  26. package/dist/durable/seat-proxy.js +599 -0
  27. package/dist/durable/seat-socket.d.ts +46 -0
  28. package/dist/durable/seat-socket.js +179 -0
  29. package/dist/durable/seat-spec-validator.d.ts +28 -0
  30. package/dist/durable/seat-spec-validator.js +59 -0
  31. package/dist/durable/test-mode.mjs +81 -0
  32. package/dist/durable/turn-chain.d.ts +55 -0
  33. package/dist/durable/turn-chain.js +178 -0
  34. package/dist/host/auto-continue.d.ts +67 -0
  35. package/dist/host/auto-continue.js +118 -0
  36. package/dist/host/bootid.d.ts +13 -0
  37. package/dist/host/bootid.js +41 -0
  38. package/dist/host/client.d.ts +123 -0
  39. package/dist/host/client.js +171 -0
  40. package/dist/host/commands.d.ts +2 -0
  41. package/dist/host/commands.js +122 -0
  42. package/dist/host/control.d.ts +33 -0
  43. package/dist/host/control.js +144 -0
  44. package/dist/host/daemon.d.ts +217 -0
  45. package/dist/host/daemon.js +606 -0
  46. package/dist/host/gate.d.ts +46 -0
  47. package/dist/host/gate.js +82 -0
  48. package/dist/host/grant.d.ts +24 -0
  49. package/dist/host/grant.js +24 -0
  50. package/dist/host/instance.d.ts +35 -0
  51. package/dist/host/instance.js +62 -0
  52. package/dist/host/integrity.d.ts +35 -0
  53. package/dist/host/integrity.js +115 -0
  54. package/dist/host/launchd.d.ts +16 -0
  55. package/dist/host/launchd.js +45 -0
  56. package/dist/host/lock.d.ts +20 -0
  57. package/dist/host/lock.js +63 -0
  58. package/dist/host/owner.d.ts +55 -0
  59. package/dist/host/owner.js +121 -0
  60. package/dist/host/plist.d.ts +16 -0
  61. package/dist/host/plist.js +85 -0
  62. package/dist/host/procs.d.ts +27 -0
  63. package/dist/host/procs.js +105 -0
  64. package/dist/host/run.d.ts +66 -0
  65. package/dist/host/run.js +314 -0
  66. package/dist/host/runtime.d.ts +8 -0
  67. package/dist/host/runtime.js +22 -0
  68. package/dist/host/s1-names.d.ts +22 -0
  69. package/dist/host/s1-names.js +21 -0
  70. package/dist/host/seat-credential.d.ts +27 -0
  71. package/dist/host/seat-credential.js +41 -0
  72. package/dist/host/seat-launch-main.d.ts +1 -0
  73. package/dist/host/seat-launch-main.js +59 -0
  74. package/dist/host/seat-launch.d.ts +116 -0
  75. package/dist/host/seat-launch.js +302 -0
  76. package/dist/host/seat.d.ts +48 -0
  77. package/dist/host/seat.js +149 -0
  78. package/dist/host/state.d.ts +33 -0
  79. package/dist/host/state.js +117 -0
  80. package/dist/host/status.d.ts +101 -0
  81. package/dist/host/status.js +307 -0
  82. package/dist/host/tmux.d.ts +56 -0
  83. package/dist/host/tmux.js +182 -0
  84. package/dist/host/transcript.d.ts +30 -0
  85. package/dist/host/transcript.js +130 -0
  86. package/dist/host/verbs.d.ts +50 -0
  87. package/dist/host/verbs.js +271 -0
  88. package/dist/index.d.ts +8 -6
  89. package/dist/index.js +197 -35
  90. package/dist/lib/agent.d.ts +8 -26
  91. package/dist/lib/agent.js +11 -26
  92. package/dist/lib/claude-plugin.d.ts +11 -2
  93. package/dist/lib/claude-plugin.js +10 -1
  94. package/dist/lib/durable/api.d.ts +136 -0
  95. package/dist/lib/durable/api.js +220 -0
  96. package/dist/lib/durable/codes.d.ts +8 -0
  97. package/dist/lib/durable/codes.js +2 -0
  98. package/dist/lib/durable/first-turn.d.ts +50 -0
  99. package/dist/lib/durable/first-turn.js +102 -0
  100. package/dist/lib/durable/gate.d.ts +48 -0
  101. package/dist/lib/durable/gate.js +122 -0
  102. package/dist/lib/durable/handover.d.ts +101 -0
  103. package/dist/lib/durable/handover.js +175 -0
  104. package/dist/lib/durable/launch.d.ts +182 -0
  105. package/dist/lib/durable/launch.js +443 -0
  106. package/dist/lib/durable/launching.d.ts +15 -0
  107. package/dist/lib/durable/launching.js +70 -0
  108. package/dist/lib/durable/live.d.ts +194 -0
  109. package/dist/lib/durable/live.js +635 -0
  110. package/dist/lib/durable/refusal.d.ts +57 -0
  111. package/dist/lib/durable/refusal.js +78 -0
  112. package/dist/lib/durable/view.d.ts +83 -0
  113. package/dist/lib/durable/view.js +244 -0
  114. package/dist/lib/experimental.d.ts +0 -9
  115. package/dist/lib/experimental.js +18 -17
  116. package/dist/lib/launcher-config.d.ts +7 -0
  117. package/dist/lib/launcher-config.js +21 -0
  118. package/dist/lib/scan/report-email.d.ts +1 -1
  119. package/dist/lib/scan/report-email.js +9 -1
  120. package/dist/lib/subscription-login.d.ts +15 -0
  121. package/dist/lib/subscription-login.js +28 -1
  122. package/dist/vendor/durable-contract/index.js +240 -18
  123. package/dist/vendor/shared/durable-contract/admission.d.ts +240 -0
  124. package/dist/vendor/shared/durable-contract/admission.js +533 -0
  125. package/dist/vendor/shared/durable-contract/arm.d.ts +51 -0
  126. package/dist/vendor/shared/durable-contract/arm.js +133 -0
  127. package/dist/vendor/shared/durable-contract/canonical.d.ts +29 -0
  128. package/dist/vendor/shared/durable-contract/canonical.js +98 -0
  129. package/dist/vendor/shared/durable-contract/cell-id.d.ts +22 -0
  130. package/dist/vendor/shared/durable-contract/cell-id.js +38 -0
  131. package/dist/vendor/shared/durable-contract/cli-output.d.ts +342 -0
  132. package/dist/vendor/shared/durable-contract/cli-output.js +201 -0
  133. package/dist/vendor/shared/durable-contract/cli-surface.d.ts +119 -0
  134. package/dist/vendor/shared/durable-contract/cli-surface.js +270 -0
  135. package/dist/vendor/shared/durable-contract/codes.d.ts +537 -0
  136. package/dist/vendor/shared/durable-contract/codes.js +475 -0
  137. package/dist/vendor/shared/durable-contract/constants.d.ts +153 -0
  138. package/dist/vendor/shared/durable-contract/constants.js +179 -0
  139. package/dist/vendor/shared/durable-contract/doors.d.ts +119 -0
  140. package/dist/vendor/shared/durable-contract/doors.js +249 -0
  141. package/dist/vendor/shared/durable-contract/envelope.d.ts +103 -0
  142. package/dist/vendor/shared/durable-contract/envelope.js +317 -0
  143. package/dist/vendor/shared/durable-contract/events.d.ts +147 -0
  144. package/dist/vendor/shared/durable-contract/events.js +630 -0
  145. package/dist/vendor/shared/durable-contract/executor-state.d.ts +41 -0
  146. package/dist/vendor/shared/durable-contract/executor-state.js +32 -0
  147. package/dist/vendor/shared/durable-contract/fixlines.d.ts +318 -0
  148. package/dist/vendor/shared/durable-contract/fixlines.js +483 -0
  149. package/dist/vendor/shared/durable-contract/freeze-record.d.ts +787 -0
  150. package/dist/vendor/shared/durable-contract/freeze-record.js +361 -0
  151. package/dist/vendor/shared/durable-contract/index.d.ts +36 -0
  152. package/dist/vendor/shared/durable-contract/index.js +37 -0
  153. package/dist/vendor/shared/durable-contract/journal-approvals.d.ts +29 -0
  154. package/dist/vendor/shared/durable-contract/journal-approvals.js +60 -0
  155. package/dist/vendor/shared/durable-contract/keys.d.ts +24 -0
  156. package/dist/vendor/shared/durable-contract/keys.js +66 -0
  157. package/dist/vendor/shared/durable-contract/lock.d.ts +128 -0
  158. package/dist/vendor/shared/durable-contract/lock.js +151 -0
  159. package/dist/vendor/shared/durable-contract/names.d.ts +25 -0
  160. package/dist/vendor/shared/durable-contract/names.js +78 -0
  161. package/dist/vendor/shared/durable-contract/owner-verbs.d.ts +175 -0
  162. package/dist/vendor/shared/durable-contract/owner-verbs.js +403 -0
  163. package/dist/vendor/shared/durable-contract/paths.d.ts +23 -0
  164. package/dist/vendor/shared/durable-contract/paths.js +35 -0
  165. package/dist/vendor/shared/durable-contract/pure-fn.d.ts +48 -0
  166. package/dist/vendor/shared/durable-contract/pure-fn.js +89 -0
  167. package/dist/vendor/shared/durable-contract/routes.d.ts +205 -0
  168. package/dist/vendor/shared/durable-contract/routes.js +315 -0
  169. package/dist/vendor/shared/durable-contract/schema.d.ts +126 -0
  170. package/dist/vendor/shared/durable-contract/schema.js +441 -0
  171. package/dist/vendor/shared/durable-contract/seal.d.ts +54 -0
  172. package/dist/vendor/shared/durable-contract/seal.js +99 -0
  173. package/dist/vendor/shared/durable-contract/secret-scope.d.ts +28 -0
  174. package/dist/vendor/shared/durable-contract/secret-scope.js +76 -0
  175. package/dist/vendor/shared/durable-contract/session-id.d.ts +21 -0
  176. package/dist/vendor/shared/durable-contract/session-id.js +58 -0
  177. package/dist/vendor/shared/durable-contract/spec.d.ts +162 -0
  178. package/dist/vendor/shared/durable-contract/spec.js +286 -0
  179. package/dist/vendor/shared/durable-contract/states.d.ts +96 -0
  180. package/dist/vendor/shared/durable-contract/states.js +218 -0
  181. package/dist/vendor/shared/durable-contract/telemetry.d.ts +94 -0
  182. package/dist/vendor/shared/durable-contract/telemetry.js +180 -0
  183. package/dist/vendor/shared/durable-contract/test-mode.d.ts +62 -0
  184. package/dist/vendor/shared/durable-contract/test-mode.js +140 -0
  185. package/dist/vendor/shared/durable-contract/turn.d.ts +57 -0
  186. package/dist/vendor/shared/durable-contract/turn.js +81 -0
  187. package/dist/vendor/shared/durable-contract/vectors.d.ts +191 -0
  188. package/dist/vendor/shared/durable-contract/vectors.js +208 -0
  189. package/package.json +3 -2
  190. package/plugins/integrity-manifest.json +35 -0
  191. package/plugins/mnemom/hooks/hooks.json +15 -1
  192. package/plugins/mnemom/hooks/register.tsx +60 -2
  193. package/plugins/mnemom/hooks/seat-hello.mjs +116 -0
  194. package/dist/commands/agent-implicit-notice.d.ts +0 -31
  195. package/dist/commands/agent-implicit-notice.js +0 -73
@@ -16,7 +16,7 @@
16
16
  *
17
17
  * Pure apart from the injected deps, so every arm is unit-tested.
18
18
  */
19
- import { stripOwnerCredentialEnv } from "./agent.js";
19
+ import { applyGatewayHintHeaders, stripOwnerCredentialEnv } from "./agent.js";
20
20
  export const AGENT_AUTHS = ["api-key", "subscription"];
21
21
  /**
22
22
  * The retired `console` value (it read the key Claude Code's Anthropic Console /login
@@ -132,6 +132,32 @@ export function subscriptionShape(shape, shapeExplicit, rcAllowed, say) {
132
132
  say("mnemom agent: subscription login runs terminal-only for now — launching in this terminal.");
133
133
  return "terminal";
134
134
  }
135
+ /**
136
+ * The coding agent's env for either auth arm: what `mnemom agent` launches claude with, and what a
137
+ * durable seat launches its claude with (host/seat-launch.ts, dogfood B6). With an Anthropic key:
138
+ * Claude Code logged in via claude.ai (OAuth) PREEMPTS ANTHROPIC_API_KEY, so it is force-unset;
139
+ * the real key rides in ANTHROPIC_CUSTOM_HEADERS (`headers`) and ANTHROPIC_AUTH_TOKEN is a fixed
140
+ * non-secret placeholder. Without one (a subscription launch) NO auth token is set: Claude Code
141
+ * then sends its own claude.ai login. Either way the owner's own Mnemom credential env is
142
+ * stripped (MNE-8245), as is MNEMOM_AGENT_ANTHROPIC_KEY (the key reaches the child only in the
143
+ * headers: C14, B6), and Claude Code's gateway hint headers are on (a value the owner set wins):
144
+ * the seat proxy chains each turn by x-claude-code-prompt-id, and without it a seat's first typed
145
+ * turn chained to the launch prompt (dogfood B8). Set here so the two callers cannot drift apart.
146
+ */
147
+ export function launchChildEnv(base, door, headers, anthropicKey) {
148
+ if (!anthropicKey)
149
+ return applyGatewayHintHeaders(subscriptionChildEnv(base, door, headers));
150
+ const env = { ...base };
151
+ delete env.ANTHROPIC_API_KEY;
152
+ delete env.MNEMOM_AGENT_ANTHROPIC_KEY;
153
+ env.ANTHROPIC_BASE_URL = door;
154
+ env.ANTHROPIC_AUTH_TOKEN = GATEWAY_AUTH_PLACEHOLDER;
155
+ env.ANTHROPIC_CUSTOM_HEADERS = headers;
156
+ stripOwnerCredentialEnv(env);
157
+ return applyGatewayHintHeaders(env);
158
+ }
159
+ /** The fixed, non-secret ANTHROPIC_AUTH_TOKEN of an api-key launch (the key rides in a header). */
160
+ export const GATEWAY_AUTH_PLACEHOLDER = "mnemom-gateway";
135
161
  /**
136
162
  * The child env for a subscription launch: the gateway door, the Mnemom headers, and
137
163
  * NOTHING that would make Claude Code send a key instead of its claude.ai login.
@@ -139,6 +165,7 @@ export function subscriptionShape(shape, shapeExplicit, rcAllowed, say) {
139
165
  export function subscriptionChildEnv(base, door, headers) {
140
166
  const env = { ...base };
141
167
  delete env.ANTHROPIC_API_KEY;
168
+ delete env.MNEMOM_AGENT_ANTHROPIC_KEY;
142
169
  delete env.ANTHROPIC_AUTH_TOKEN;
143
170
  // The key already rides in the headers; the child process has no other use for it.
144
171
  // MNE-8245 defense-in-depth: also strips MNEMOM_API_KEY/MNEMOM_TOKEN, in case the
@@ -193,7 +193,10 @@ var SUSPENDED_REASONS = [
193
193
  "card_drift",
194
194
  "attestation_failed",
195
195
  "owner_departed",
196
- "respawn_failed"
196
+ "respawn_failed",
197
+ /** ruling 34.22: a question wait's, or any non-budget approval wait's, approval expired or was denied; the owner resumes by hand. Budget waits keep budget_reached. */
198
+ "approval_expired",
199
+ "approval_denied"
197
200
  ];
198
201
  var PAUSED_REASONS = ["owner", "agent_contained", "breakglass"];
199
202
  var FAILED_REASONS = ["transcript_lost"];
@@ -224,7 +227,10 @@ var M1_WRITTEN_SUSPENDED_REASONS = [
224
227
  "identity_mismatch",
225
228
  "attestation_failed",
226
229
  "respawn_failed",
227
- "grant_expired"
230
+ "grant_expired",
231
+ /** ruling 34.22: written by the approval-wait expiry/denial path. */
232
+ "approval_expired",
233
+ "approval_denied"
228
234
  ];
229
235
  var WAIT_REASONS = [
230
236
  "approval",
@@ -902,6 +908,9 @@ var DURABLE_CODES = {
902
908
  surfaces: ["api"],
903
909
  fields: ["reason", "state_reason", "check", "state", "wait_reason"]
904
910
  },
911
+ // The per-org claim rate limit (ruling 34.24): nothing written, no key minted. retry_after_s is
912
+ // the number of seconds to wait (claimRateLimitedDetailsOk).
913
+ durable_claim_rate_limited: { status: 429, surfaces: ["api"], fields: ["retry_after_s"] },
905
914
  // ---- api journal (C10-R0 (i), (j), (k)) ----
906
915
  /** Lost CAS race on (session_id, seq). */
907
916
  durable_append_conflict: { status: 409, surfaces: ["api"], fields: ["tip_seq"] },
@@ -995,7 +1004,8 @@ var CLAIM_OUTCOMES = [
995
1004
  "needs_key",
996
1005
  "lost_race",
997
1006
  "ineligible",
998
- "unavailable"
1007
+ "unavailable",
1008
+ "rate_limited"
999
1009
  ];
1000
1010
  var CLAIM_OUTCOME_STATUS = {
1001
1011
  acquired: 200,
@@ -1004,7 +1014,8 @@ var CLAIM_OUTCOME_STATUS = {
1004
1014
  needs_key: 409,
1005
1015
  lost_race: 409,
1006
1016
  ineligible: 403,
1007
- unavailable: 503
1017
+ unavailable: 503,
1018
+ rate_limited: 429
1008
1019
  };
1009
1020
  var CLAIM_LOST_RACE_REASONS = ["stale_tokens", "lease_live", "org_lease_cap"];
1010
1021
  var CLAIM_INELIGIBLE_REASONS = [
@@ -1069,6 +1080,14 @@ function claimLostRaceDetailsOk(details) {
1069
1080
  if (details.reason !== "org_lease_cap") return !("live" in details) && !("cap" in details);
1070
1081
  return Number.isInteger(details.live) && details.live >= 0 && Number.isInteger(details.cap) && details.cap >= 1;
1071
1082
  }
1083
+ function claimRateLimitedDetailsOk(details) {
1084
+ if (Object.keys(details).some(
1085
+ (k) => !["fix", ...DURABLE_CODES.durable_claim_rate_limited.fields].includes(k)
1086
+ ))
1087
+ return false;
1088
+ const t = details.retry_after_s;
1089
+ return typeof t === "number" && Number.isFinite(t) && t >= 0;
1090
+ }
1072
1091
  function claimIneligibleDetailsOk(details) {
1073
1092
  if (Object.keys(details).some(
1074
1093
  (k) => !["fix", ...DURABLE_CODES.durable_claim_ineligible.fields].includes(k)
@@ -1603,6 +1622,17 @@ var FIX_LINES = {
1603
1622
  ),
1604
1623
  respawn_failed: e("command", "`mnemom agent resume <name>`"),
1605
1624
  attestation_failed: e("command", "`mnemom agent resume <name>`"),
1625
+ /** suspended(approval_expired|approval_denied) (ruling 34.22): the wait was left; the owner resumes by hand. */
1626
+ approval_expired: e(
1627
+ "command",
1628
+ "`mnemom agent resume <name>`",
1629
+ "the approval expired and this session needs you to resume it: "
1630
+ ),
1631
+ approval_denied: e(
1632
+ "command",
1633
+ "`mnemom agent resume <name>`",
1634
+ "the approval was denied and this session needs you to resume it: "
1635
+ ),
1606
1636
  attestation_cwd_missing: e(
1607
1637
  "command",
1608
1638
  "`cd <toplevel> && mnemom agent <name> --new`",
@@ -1693,6 +1723,13 @@ var FIX_LINES = {
1693
1723
  "command",
1694
1724
  "`mnemom agent <name> --agent <another-agent>`, or <precondition>"
1695
1725
  ),
1726
+ // The api's create refusal while another session is locked on the agent (dogfood walk5): the
1727
+ // reader finishes or reuses the holder, or starts <name> on another agent. <holder> is the
1728
+ // locked session's name; `<another-agent>` stays literal (ruling 21).
1729
+ durable_only_held: e(
1730
+ "command",
1731
+ "<holder> is locked on this agent: finish it with `mnemom agent done <holder>`, carry on in it with `mnemom agent <holder>`, or start <name> on another agent with `mnemom agent <name> --agent <another-agent>`"
1732
+ ),
1696
1733
  // ---- owner verbs (owner-verb table step 3; final F04, F06) ----
1697
1734
  not_owner_admin: e(
1698
1735
  "command",
@@ -1793,6 +1830,9 @@ function renderDurableOnlyWith(clauses, launcherKey, params) {
1793
1830
  });
1794
1831
  return launcherKey === "always" ? base : base + DURABLE_ONLY_CONFIG_CLAUSE;
1795
1832
  }
1833
+ function renderDurableOnlyHeld(params) {
1834
+ return substitute(FIX_LINES.durable_only_held.body, { name: params.name, holder: params.holder });
1835
+ }
1796
1836
  var STOPPED_EFFECTIVE_STATES = ["paused", "suspended", "suspended_grant_expired"];
1797
1837
  var STOPPED_FIX_NULL_REASON = "null";
1798
1838
  var STOPPED_FIX_ANY_REASON = "*";
@@ -1813,7 +1853,9 @@ var STOPPED_FIX = Object.freeze({
1813
1853
  card_drift: "stopped_no_m1_remedy",
1814
1854
  attestation_failed: "attestation_failed",
1815
1855
  owner_departed: "stopped_no_m1_remedy",
1816
- respawn_failed: "respawn_failed"
1856
+ respawn_failed: "respawn_failed",
1857
+ approval_expired: "approval_expired",
1858
+ approval_denied: "approval_denied"
1817
1859
  }),
1818
1860
  suspended_grant_expired: Object.freeze({ [STOPPED_FIX_ANY_REASON]: "grant_expired" })
1819
1861
  });
@@ -2202,7 +2244,8 @@ var DURABLE_EVENT_KINDS = [
2202
2244
  "tip.signed",
2203
2245
  "session.ready",
2204
2246
  "session.waiting",
2205
- "session.wait_cleared"
2247
+ "session.wait_cleared",
2248
+ "executor.turn_continued"
2206
2249
  ];
2207
2250
  function isDurableEventKind(v) {
2208
2251
  return typeof v === "string" && DURABLE_EVENT_KINDS.includes(v);
@@ -2210,7 +2253,8 @@ function isDurableEventKind(v) {
2210
2253
  var AMENDMENT_EVENT_GROUPS = Object.freeze({
2211
2254
  "session.ready": "lifecycle",
2212
2255
  "session.waiting": "lifecycle",
2213
- "session.wait_cleared": "lifecycle"
2256
+ "session.wait_cleared": "lifecycle",
2257
+ "executor.turn_continued": "lease"
2214
2258
  });
2215
2259
  function eventGroupOf(kind) {
2216
2260
  if (Object.prototype.hasOwnProperty.call(AMENDMENT_EVENT_GROUPS, kind))
@@ -2221,7 +2265,8 @@ function eventGroupOf(kind) {
2221
2265
  var EVENT_WRITERS = ["executor", "gateway", "api"];
2222
2266
  var EXECUTOR_WRITABLE_KINDS = [
2223
2267
  "executor.spawned",
2224
- "session.waiting"
2268
+ "session.waiting",
2269
+ "executor.turn_continued"
2225
2270
  ];
2226
2271
  var GATEWAY_WRITABLE_KINDS = [
2227
2272
  "lease.zombie_call",
@@ -2329,7 +2374,14 @@ var KIND_REFS = {
2329
2374
  "session.unpaused": obj(
2330
2375
  {
2331
2376
  from_state: ENUM(["paused", "suspended"]),
2332
- from_reason: ENUM(["owner", "agent_contained", "respawn_failed", "attestation_failed"])
2377
+ from_reason: ENUM([
2378
+ "owner",
2379
+ "agent_contained",
2380
+ "respawn_failed",
2381
+ "attestation_failed",
2382
+ "approval_expired",
2383
+ "approval_denied"
2384
+ ])
2333
2385
  },
2334
2386
  ["from_state", "from_reason"],
2335
2387
  [
@@ -2341,7 +2393,14 @@ var KIND_REFS = {
2341
2393
  {
2342
2394
  field: "from_state",
2343
2395
  equals: "suspended",
2344
- enums: { from_reason: ["respawn_failed", "attestation_failed"] }
2396
+ enums: {
2397
+ from_reason: [
2398
+ "respawn_failed",
2399
+ "attestation_failed",
2400
+ "approval_expired",
2401
+ "approval_denied"
2402
+ ]
2403
+ }
2345
2404
  }
2346
2405
  ]
2347
2406
  ),
@@ -2432,7 +2491,10 @@ var KIND_REFS = {
2432
2491
  { field: "wait_reason", equals: "budget", require: ["approval_id"], forbid: ["head_sha"] }
2433
2492
  ]
2434
2493
  ),
2435
- "session.wait_cleared": obj({ wait_reason: ENUM(PARKED_ONLY_WAIT_REASONS) })
2494
+ "session.wait_cleared": obj({ wait_reason: ENUM(PARKED_ONLY_WAIT_REASONS) }),
2495
+ // ---- lead ruling 2026-10-28: the spawn that sent the continue; a separate fact, so
2496
+ // executor.spawned's refs stay exactly {spawn_id} ----
2497
+ "executor.turn_continued": obj({ spawn_id: UUID })
2436
2498
  };
2437
2499
  function refsSchemaOf(kind) {
2438
2500
  return KIND_REFS[kind] ?? EMPTY;
@@ -2652,7 +2714,7 @@ function ownerVerbDecision(i) {
2652
2714
  case "resume":
2653
2715
  if (!locked) return row8();
2654
2716
  if (contained) return deviceStepOr(i, "unpause_contained");
2655
- if (i.state === "paused" && i.state_reason === "owner" || i.state === "suspended" && (i.state_reason === "respawn_failed" || i.state_reason === "attestation_failed")) {
2717
+ if (i.state === "paused" && i.state_reason === "owner" || i.state === "suspended" && (i.state_reason === "respawn_failed" || i.state_reason === "attestation_failed" || i.state_reason === "approval_expired" || i.state_reason === "approval_denied")) {
2656
2718
  return {
2657
2719
  kind: "apply",
2658
2720
  status: 200,
@@ -3048,11 +3110,16 @@ var CHAIN_KEY = "chain";
3048
3110
  var INBOX_KEY = "inbox";
3049
3111
  var TURN_HASH_RE = /^[0-9a-f]{64}$/;
3050
3112
  var ATTENDED_SOURCES = [void 0, "typed", "queued"];
3113
+ var TURN_PRODUCER_RE = /^[a-z][a-z0-9-]{0,31}$/;
3114
+ var ATTENDED_TASK_PRODUCER = "session-task";
3115
+ var attendedHuman = (e2) => e2.origin === "human" && ATTENDED_SOURCES.includes(e2.source) && !e2.inbox;
3051
3116
  function candidatePosture(entries, schemaKnown = true) {
3052
3117
  if (!schemaKnown) return "unattended";
3053
3118
  const newest = entries[entries.length - 1];
3054
3119
  if (newest === void 0) return "unattended";
3055
- return newest.origin === "human" && ATTENDED_SOURCES.includes(newest.source) && !newest.inbox ? "attended" : "unattended";
3120
+ if (attendedHuman(newest)) return "attended";
3121
+ const continuation = newest.origin === "task" && newest.source === "system" && newest.producer === ATTENDED_TASK_PRODUCER && !newest.inbox && entries.slice(0, -1).some(attendedHuman);
3122
+ return continuation ? "attended" : "unattended";
3056
3123
  }
3057
3124
  async function chainIdOf(rootPromptId) {
3058
3125
  if (typeof rootPromptId !== "string" || rootPromptId.length === 0)
@@ -3389,7 +3456,8 @@ var M1_COLUMNS = {
3389
3456
  "expires_at",
3390
3457
  "created_at",
3391
3458
  "updated_at",
3392
- "wait_ref"
3459
+ "wait_ref",
3460
+ "new_session"
3393
3461
  ],
3394
3462
  durable_lease_keys: [
3395
3463
  "key_hash",
@@ -3891,6 +3959,7 @@ var CIPHER_KEY_REFS = ["mnemom"];
3891
3959
  var DEK_BYTES = 32;
3892
3960
  var IV_BYTES = 12;
3893
3961
  var TAG_BYTES = 16;
3962
+ var CONTRACT_OPTIONAL_KEYS = ["goal_id", "work_card", "shape"];
3894
3963
  function contractAad(sessionId, charterVersion) {
3895
3964
  return `durable-contract:v1:${sessionId}:${charterVersion}`;
3896
3965
  }
@@ -3898,26 +3967,39 @@ function parseContract(raw) {
3898
3967
  if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return null;
3899
3968
  const r = raw;
3900
3969
  const keys = ["statement", "requirements", "allowed_paths", "forbidden_paths"];
3901
- if (Object.keys(r).some((k) => !keys.includes(k))) return null;
3970
+ const known = [...keys, ...CONTRACT_OPTIONAL_KEYS];
3971
+ if (Object.keys(r).some((k) => !known.includes(k))) return null;
3902
3972
  if (typeof r.statement !== "string" || r.statement.length === 0 || r.statement.length > CONTRACT_STATEMENT_MAX_CHARS)
3903
3973
  return null;
3904
3974
  for (const k of keys.slice(1)) {
3905
3975
  const v = r[k] ?? [];
3906
3976
  if (!Array.isArray(v) || v.some((s) => typeof s !== "string")) return null;
3907
3977
  }
3908
- return {
3978
+ if ("goal_id" in r && (typeof r.goal_id !== "string" || r.goal_id.length === 0)) return null;
3979
+ if ("work_card" in r && r.work_card !== true) return null;
3980
+ if ("shape" in r && r.shape !== "duty") return null;
3981
+ const out = {
3909
3982
  statement: r.statement,
3910
3983
  requirements: r.requirements ?? [],
3911
3984
  allowed_paths: r.allowed_paths ?? [],
3912
3985
  forbidden_paths: r.forbidden_paths ?? []
3913
3986
  };
3987
+ return { ...out, ...optionalContractFields(r) };
3988
+ }
3989
+ function optionalContractFields(c) {
3990
+ const out = {};
3991
+ if (c.goal_id !== void 0) out.goal_id = c.goal_id;
3992
+ if (c.work_card !== void 0) out.work_card = c.work_card;
3993
+ if (c.shape !== void 0) out.shape = c.shape;
3994
+ return out;
3914
3995
  }
3915
3996
  function contractPlaintext(c) {
3916
3997
  return canonicalJson({
3917
3998
  statement: c.statement,
3918
3999
  requirements: c.requirements,
3919
4000
  allowed_paths: c.allowed_paths,
3920
- forbidden_paths: c.forbidden_paths
4001
+ forbidden_paths: c.forbidden_paths,
4002
+ ...optionalContractFields(c)
3921
4003
  });
3922
4004
  }
3923
4005
  async function statementHash(statement) {
@@ -3997,8 +4079,13 @@ var COMMITMENT_KEYS = [
3997
4079
  "active_time_limit_s",
3998
4080
  "pins",
3999
4081
  "tool_classes",
4000
- "launch_spec"
4082
+ "launch_spec",
4083
+ // amendment 55 (C07-R02): what the gateway sealed beyond the ceilings, so a reload keeps it
4084
+ "mode",
4085
+ "stall_turns",
4086
+ "contract_hash"
4001
4087
  ];
4088
+ var CONTRACT_MODE_VALUES = ["nudge", "enforce"];
4002
4089
  var TOOL_CLASS_VALUES = ["input_dependent", "safe", "idempotent"];
4003
4090
  var PIN_KEYS = ["card_content_hash", "policy_engine_major"];
4004
4091
  function isValidCommitment(raw) {
@@ -4008,6 +4095,7 @@ function isValidCommitment(raw) {
4008
4095
  switch (k) {
4009
4096
  case "statement_hash":
4010
4097
  case "requirements_hash":
4098
+ case "contract_hash":
4011
4099
  if (typeof v !== "string" || !HEX64_RE.test(v)) return false;
4012
4100
  break;
4013
4101
  case "budget_usd":
@@ -4017,6 +4105,7 @@ function isValidCommitment(raw) {
4017
4105
  case "max_wakes_per_day":
4018
4106
  case "max_turns":
4019
4107
  case "active_time_limit_s":
4108
+ case "stall_turns":
4020
4109
  if (!Number.isSafeInteger(v) || v < 0) return false;
4021
4110
  break;
4022
4111
  case "pins": {
@@ -4036,6 +4125,9 @@ function isValidCommitment(raw) {
4036
4125
  }
4037
4126
  break;
4038
4127
  }
4128
+ case "mode":
4129
+ if (!CONTRACT_MODE_VALUES.includes(v)) return false;
4130
+ break;
4039
4131
  case "launch_spec":
4040
4132
  if (typeof v !== "object" || v === null || Array.isArray(v)) return false;
4041
4133
  break;
@@ -4081,10 +4173,74 @@ function charterPreimage(row) {
4081
4173
  created_at: canonicalEventTs(row.created_at)
4082
4174
  };
4083
4175
  }
4176
+ function charterV1CreatedAt(sealedAt) {
4177
+ try {
4178
+ return canonicalEventTs(sealedAt);
4179
+ } catch {
4180
+ }
4181
+ const ms = Date.parse(sealedAt);
4182
+ if (!Number.isFinite(ms)) throw new RangeError(`not a seal instant: ${sealedAt}`);
4183
+ return canonicalEventTs(new Date(ms).toISOString());
4184
+ }
4084
4185
  async function charterHash(row) {
4085
4186
  return sha256Hex(canonicalJson(charterPreimage(row)));
4086
4187
  }
4087
4188
 
4189
+ // ../shared/durable-contract/src/seal.ts
4190
+ var SEALED_CONTRACT_FIELDS = [
4191
+ "goal_id",
4192
+ "statement",
4193
+ "requirements",
4194
+ "allowed_paths",
4195
+ "forbidden_paths",
4196
+ "max_turns",
4197
+ "budget_usd",
4198
+ "stall_turns",
4199
+ "time_limit_s",
4200
+ "mode",
4201
+ "work_card",
4202
+ "shape"
4203
+ ];
4204
+ async function sealedContractHash(c) {
4205
+ const normalised = { ...c };
4206
+ if ((c.mode ?? "nudge") === "nudge") delete normalised.mode;
4207
+ return sha256Hex(canonicalJson(normalised));
4208
+ }
4209
+ var CEILINGS = [
4210
+ ["budget_usd", "budget_usd"],
4211
+ ["max_turns", "max_turns"],
4212
+ ["stall_turns", "stall_turns"],
4213
+ ["time_limit_s", "active_time_limit_s"]
4214
+ ];
4215
+ async function splitSealedContract(seal) {
4216
+ const known = SEALED_CONTRACT_FIELDS;
4217
+ if (Object.keys(seal).some((k) => !known.includes(k))) return null;
4218
+ const text = {};
4219
+ for (const k of ["statement", "requirements", "allowed_paths", "forbidden_paths", "goal_id", "work_card", "shape"])
4220
+ if (seal[k] !== void 0) text[k] = seal[k];
4221
+ const contract = parseContract(text);
4222
+ if (contract === null) return null;
4223
+ const commitments = {
4224
+ statement_hash: await statementHash(contract.statement),
4225
+ requirements_hash: await requirementsHash(contract.requirements),
4226
+ contract_hash: await sealedContractHash(seal)
4227
+ };
4228
+ if (seal.mode !== void 0) commitments.mode = seal.mode;
4229
+ for (const [from, to] of CEILINGS) if (seal[from] !== void 0) commitments[to] = seal[from];
4230
+ return isValidCommitment(commitments) ? { contract, commitments } : null;
4231
+ }
4232
+ async function sealedContractFromCharter(contract, charter) {
4233
+ if (typeof charter.contract_hash !== "string") return null;
4234
+ const seal = { ...contract };
4235
+ if (typeof charter.mode === "string") seal.mode = charter.mode;
4236
+ for (const [to, from] of CEILINGS) {
4237
+ const v = charter[from];
4238
+ if (typeof v === "number") seal[to] = v;
4239
+ }
4240
+ const hash = await sealedContractHash(seal);
4241
+ return hash === charter.contract_hash ? { contract: seal, contract_hash: hash } : null;
4242
+ }
4243
+
4088
4244
  // ../shared/durable-contract/src/executor-state.ts
4089
4245
  var EXECUTOR_STATE_VERSION = 1;
4090
4246
  var EXECUTOR_STATE_SCHEMA = Object.freeze({
@@ -4203,6 +4359,12 @@ function execSessionsResponseOk(v) {
4203
4359
  return keysExactly(v, Object.keys(EXEC_SESSIONS_RESPONSE.grant_expired)) && v.grant_expired === true && v.sessions.length === 0 && fieldOk({ type: "timestamp", nullable: false }, v.grant_expires_at);
4204
4360
  return keysExactly(v, ["sessions"]) && v.sessions.every(execSessionsItemOk);
4205
4361
  }
4362
+ var OWNER_SESSION_VIEW_FIELDS = Object.freeze({
4363
+ cc_session_id: "string|null"
4364
+ });
4365
+ function ownerSessionViewOk(v) {
4366
+ return isObj(v) && "cc_session_id" in v && fieldOk({ type: "string", nullable: true }, v.cc_session_id);
4367
+ }
4206
4368
  var EXECUTOR_KEY_HEADER = "X-Mnemom-Api-Key";
4207
4369
  var HEARTBEAT_REQUEST_KEYS = ["nonce", "entries"];
4208
4370
  function heartbeatRequestOk(v) {
@@ -4880,6 +5042,8 @@ var FREEZE_STRUCTURED = Object.freeze({
4880
5042
  HEARTBEAT_RESULT_FIELDS,
4881
5043
  /** GET exec_sessions body: only sessions[] and each item's uuid id are frozen (24.16). */
4882
5044
  EXEC_SESSIONS_RESPONSE,
5045
+ /** Owner session view: cc_session_id present, string or null; the view is otherwise open (#1085). */
5046
+ OWNER_SESSION_VIEW_FIELDS,
4883
5047
  /** Claim refusal details (24.22.1): lost_race reasons, ineligible reasons and their presence rules. */
4884
5048
  CLAIM_LOST_RACE_REASONS,
4885
5049
  CLAIM_INELIGIBLE_REASONS,
@@ -5122,6 +5286,50 @@ var CHARTER_HASH_VECTORS = {
5122
5286
  }
5123
5287
  ]
5124
5288
  };
5289
+ var SEAL_VECTORS = {
5290
+ "seal": {
5291
+ "statement": "Ship the release. canary zq-k1-102d461d964a345ca757",
5292
+ "requirements": [
5293
+ "Tests stay green. canary zq-k2-54e87989d0dd1c2f7a00"
5294
+ ],
5295
+ "budget_usd": 5,
5296
+ "max_turns": 40,
5297
+ "time_limit_s": 3600,
5298
+ "mode": "enforce",
5299
+ "allowed_paths": [
5300
+ "src/**"
5301
+ ],
5302
+ "forbidden_paths": [
5303
+ "secrets/**"
5304
+ ]
5305
+ },
5306
+ "enforce_hash": "85fc982c26cf4a28ac1e7e3ba0f746a83bd96bc3ce7a3ed84401f79aa684d13a",
5307
+ "gateway_enforce_h16": "85fc982c26cf4a28",
5308
+ "nudge_hash": "d0344555137faf1ce06f81bb905ec9dfb15dd385de57b6a959e381bf1f3fe654",
5309
+ "gateway_nudge_h16": "d0344555137faf1c",
5310
+ "sealed_at": "2026-10-29T12:45:33.355-07:00",
5311
+ "charter_v1": {
5312
+ "commitments": {
5313
+ "statement_hash": "04ed1e6039e500e2a1d09fd4238a77863cdfc699e504cea01a4c63263ffdf538",
5314
+ "requirements_hash": "d594733b87aa9594eb4d084a49e8450aa8ac9e32ffb9c985d7a2f24fa6513fcd",
5315
+ "contract_hash": "85fc982c26cf4a28ac1e7e3ba0f746a83bd96bc3ce7a3ed84401f79aa684d13a",
5316
+ "mode": "enforce",
5317
+ "budget_usd": 5,
5318
+ "max_turns": 40,
5319
+ "active_time_limit_s": 3600,
5320
+ "pins": {
5321
+ "card_content_hash": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
5322
+ "policy_engine_major": 3
5323
+ },
5324
+ "tool_classes": {
5325
+ "Bash": "input_dependent"
5326
+ }
5327
+ },
5328
+ "created_at": "2026-10-29T19:45:33.355000Z",
5329
+ "preimage": '{"charter":{"active_time_limit_s":3600,"budget_usd":5,"contract_hash":"85fc982c26cf4a28ac1e7e3ba0f746a83bd96bc3ce7a3ed84401f79aa684d13a","max_turns":40,"mode":"enforce","pins":{"card_content_hash":"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc","policy_engine_major":3},"requirements_hash":"d594733b87aa9594eb4d084a49e8450aa8ac9e32ffb9c985d7a2f24fa6513fcd","statement_hash":"04ed1e6039e500e2a1d09fd4238a77863cdfc699e504cea01a4c63263ffdf538","tool_classes":{"Bash":"input_dependent"}},"created_at":"2026-10-29T19:45:33.355000Z","prev_hash":"0000000000000000000000000000000000000000000000000000000000000000","session_id":"11111111-2222-4333-8444-555555555555","v":1,"version":1}',
5330
+ "hash": "5a3bb041c155d67e50d18ee9afb0e6903f7a64988c881ab6373d3447fd5906f5"
5331
+ }
5332
+ };
5125
5333
  export {
5126
5334
  ABSENT_FUNCTIONS_M1,
5127
5335
  ADMISSION_PRECEDENCE,
@@ -5152,6 +5360,7 @@ export {
5152
5360
  ARM_VERSION,
5153
5361
  ATTACH_WAIT_S,
5154
5362
  ATTENDED_SOURCES,
5363
+ ATTENDED_TASK_PRODUCER,
5155
5364
  ATTESTATION_CHECKS_M1,
5156
5365
  ATTRIBUTE_VALUES,
5157
5366
  BUILDER_INPUT_TABLE,
@@ -5187,6 +5396,8 @@ export {
5187
5396
  CLI_USAGE_EXIT,
5188
5397
  COMMITMENT_KEYS,
5189
5398
  CONTRACT_JSON_MAX_BYTES,
5399
+ CONTRACT_MODE_VALUES,
5400
+ CONTRACT_OPTIONAL_KEYS,
5190
5401
  CONTRACT_PURGE_AFTER_S,
5191
5402
  CONTRACT_STATEMENT_MAX_CHARS,
5192
5403
  CONTRACT_VECTOR,
@@ -5356,6 +5567,7 @@ export {
5356
5567
  OUTAGE_TEXT_M1,
5357
5568
  OWNER_MUTATION_APPROVAL_TTL_S,
5358
5569
  OWNER_MUTATION_CLIENT_ID,
5570
+ OWNER_SESSION_VIEW_FIELDS,
5359
5571
  OWNER_TABLE_VERBS,
5360
5572
  OWNER_VERBS,
5361
5573
  PARKED_ONLY_WAIT_REASONS,
@@ -5413,6 +5625,8 @@ export {
5413
5625
  RUNNER_OUTCOMES,
5414
5626
  RUNNER_OUTCOME_FIELDS,
5415
5627
  RUNNER_REFUSED_REASONS,
5628
+ SEALED_CONTRACT_FIELDS,
5629
+ SEAL_VECTORS,
5416
5630
  SEAT_DAEMON_FLAGS,
5417
5631
  SEAT_MAX_ATTEMPTS_NONRETRY,
5418
5632
  SEAT_TEXT_M1,
@@ -5476,6 +5690,7 @@ export {
5476
5690
  TURN_HASH_RE,
5477
5691
  TURN_HEADER_MAX_LEN,
5478
5692
  TURN_ORIGINS,
5693
+ TURN_PRODUCER_RE,
5479
5694
  TURN_SOURCES,
5480
5695
  TURN_WAIT_MS,
5481
5696
  T_HELLO_S,
@@ -5519,12 +5734,14 @@ export {
5519
5734
  charterByHashResponseOk,
5520
5735
  charterHash,
5521
5736
  charterPreimage,
5737
+ charterV1CreatedAt,
5522
5738
  checkDurableSpan,
5523
5739
  claimBackoffMs,
5524
5740
  claimBodyOk,
5525
5741
  claimIneligibleDetailsOk,
5526
5742
  claimLostRaceDetailsOk,
5527
5743
  claimNeedsKeyRetry,
5744
+ claimRateLimitedDetailsOk,
5528
5745
  classifyKey,
5529
5746
  cliRefusalJson,
5530
5747
  contractAad,
@@ -5596,6 +5813,7 @@ export {
5596
5813
  normalizeCellId,
5597
5814
  normalizeSessionName,
5598
5815
  openContract,
5816
+ ownerSessionViewOk,
5599
5817
  ownerVerbDecision,
5600
5818
  parseArm,
5601
5819
  parseContract,
@@ -5625,6 +5843,7 @@ export {
5625
5843
  refsSha256,
5626
5844
  renderAdoptNote,
5627
5845
  renderDurableOnly,
5846
+ renderDurableOnlyHeld,
5628
5847
  renderFixLine,
5629
5848
  renderNonTtyLocked,
5630
5849
  renderStoppedReasonText,
@@ -5638,6 +5857,8 @@ export {
5638
5857
  s1Resolve,
5639
5858
  s1Value,
5640
5859
  sealContract,
5860
+ sealedContractFromCharter,
5861
+ sealedContractHash,
5641
5862
  seamsOf,
5642
5863
  secretEncodings,
5643
5864
  sessionNameRefusal,
@@ -5645,6 +5866,7 @@ export {
5645
5866
  shouldRetryHeader,
5646
5867
  spanStatusOf,
5647
5868
  specHash,
5869
+ splitSealedContract,
5648
5870
  stampEventTs,
5649
5871
  stateRows,
5650
5872
  statementHash,