@intentic/sandbox-contract 1.343.0 → 1.345.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 (325) hide show
  1. package/README.md +10 -0
  2. package/dist/contracts/accounts.contract.d.ts +24 -0
  3. package/dist/contracts/accounts.contract.d.ts.map +1 -1
  4. package/dist/contracts/agent.contract.d.ts +214 -6
  5. package/dist/contracts/agent.contract.d.ts.map +1 -1
  6. package/dist/contracts/agent.contract.js +13 -2
  7. package/dist/contracts/agent.contract.js.map +1 -1
  8. package/dist/contracts/agents.contract.d.ts +656 -0
  9. package/dist/contracts/agents.contract.d.ts.map +1 -1
  10. package/dist/contracts/agents.contract.js +5 -3
  11. package/dist/contracts/agents.contract.js.map +1 -1
  12. package/dist/contracts/device.contract.d.ts +259 -0
  13. package/dist/contracts/device.contract.d.ts.map +1 -1
  14. package/dist/contracts/device.contract.js +5 -1
  15. package/dist/contracts/device.contract.js.map +1 -1
  16. package/dist/contracts/endpoints.contract.d.ts +2 -0
  17. package/dist/contracts/endpoints.contract.d.ts.map +1 -1
  18. package/dist/contracts/endpoints.contract.js +1 -0
  19. package/dist/contracts/endpoints.contract.js.map +1 -1
  20. package/dist/contracts/push.contract.d.ts +11 -0
  21. package/dist/contracts/push.contract.d.ts.map +1 -1
  22. package/dist/contracts/push.contract.js +10 -1
  23. package/dist/contracts/push.contract.js.map +1 -1
  24. package/dist/contracts/runner.contract.d.ts +18 -2
  25. package/dist/contracts/runner.contract.d.ts.map +1 -1
  26. package/dist/contracts/secrets.contract.d.ts +169 -0
  27. package/dist/contracts/secrets.contract.d.ts.map +1 -1
  28. package/dist/contracts/secrets.contract.js +35 -0
  29. package/dist/contracts/secrets.contract.js.map +1 -1
  30. package/dist/contracts/sessions.contract.d.ts +2 -0
  31. package/dist/contracts/sessions.contract.d.ts.map +1 -1
  32. package/dist/contracts/settings.contract.d.ts +37 -2
  33. package/dist/contracts/settings.contract.d.ts.map +1 -1
  34. package/dist/contracts/system.contract.d.ts +185 -35
  35. package/dist/contracts/system.contract.d.ts.map +1 -1
  36. package/dist/contracts/translator.contract.d.ts +24 -0
  37. package/dist/contracts/translator.contract.d.ts.map +1 -1
  38. package/dist/contracts/workspace.contract.d.ts +11 -0
  39. package/dist/contracts/workspace.contract.d.ts.map +1 -1
  40. package/dist/contracts/workspace.contract.js +11 -1
  41. package/dist/contracts/workspace.contract.js.map +1 -1
  42. package/dist/events/agent-events.d.ts +18 -0
  43. package/dist/events/agent-events.d.ts.map +1 -1
  44. package/dist/events/agent-events.js +3 -1
  45. package/dist/events/agent-events.js.map +1 -1
  46. package/dist/events/agent-transcript.d.ts +727 -0
  47. package/dist/events/agent-transcript.d.ts.map +1 -0
  48. package/dist/events/agent-transcript.js +34 -0
  49. package/dist/events/agent-transcript.js.map +1 -0
  50. package/dist/events/agent-words.d.ts +5 -0
  51. package/dist/events/agent-words.d.ts.map +1 -1
  52. package/dist/events/agent-words.js +9 -0
  53. package/dist/events/agent-words.js.map +1 -1
  54. package/dist/events/requests.d.ts +143 -0
  55. package/dist/events/requests.d.ts.map +1 -1
  56. package/dist/events/requests.js +35 -1
  57. package/dist/events/requests.js.map +1 -1
  58. package/dist/events/sandbox-notice.d.ts +7 -0
  59. package/dist/events/sandbox-notice.d.ts.map +1 -1
  60. package/dist/events/sandbox-notice.js +1 -0
  61. package/dist/events/sandbox-notice.js.map +1 -1
  62. package/dist/events/system-events.d.ts +88 -0
  63. package/dist/events/system-events.d.ts.map +1 -1
  64. package/dist/events/transcript.d.ts +20 -720
  65. package/dist/events/transcript.d.ts.map +1 -1
  66. package/dist/events/transcript.js +17 -19
  67. package/dist/events/transcript.js.map +1 -1
  68. package/dist/events/undelivered.d.ts +4 -0
  69. package/dist/events/undelivered.d.ts.map +1 -1
  70. package/dist/events/undelivered.js +13 -0
  71. package/dist/events/undelivered.js.map +1 -1
  72. package/dist/ids/conversation-ids.d.ts +2 -0
  73. package/dist/ids/conversation-ids.d.ts.map +1 -1
  74. package/dist/ids/conversation-ids.js +2 -0
  75. package/dist/ids/conversation-ids.js.map +1 -1
  76. package/dist/ids/row-ids.d.ts +3 -0
  77. package/dist/ids/row-ids.d.ts.map +1 -0
  78. package/dist/ids/row-ids.js +11 -0
  79. package/dist/ids/row-ids.js.map +1 -0
  80. package/dist/index.d.ts +1339 -48
  81. package/dist/index.d.ts.map +1 -1
  82. package/dist/models/agent-lanes.d.ts.map +1 -1
  83. package/dist/models/agent-lanes.js +3 -2
  84. package/dist/models/agent-lanes.js.map +1 -1
  85. package/dist/models/agent-standing.d.ts +4 -0
  86. package/dist/models/agent-standing.d.ts.map +1 -1
  87. package/dist/models/agent-standing.js +2 -1
  88. package/dist/models/agent-standing.js.map +1 -1
  89. package/dist/models/plan-pools.d.ts +5 -1
  90. package/dist/models/plan-pools.d.ts.map +1 -1
  91. package/dist/models/plan-pools.js +57 -21
  92. package/dist/models/plan-pools.js.map +1 -1
  93. package/dist/netd/generated/wire.d.ts +5 -0
  94. package/dist/netd/generated/wire.d.ts.map +1 -1
  95. package/dist/policy/command-classes.d.ts +1 -1
  96. package/dist/policy/command-classes.d.ts.map +1 -1
  97. package/dist/policy/command-classes.js +2 -2
  98. package/dist/policy/command-classes.js.map +1 -1
  99. package/dist/policy/keyring-origins.d.ts +27 -0
  100. package/dist/policy/keyring-origins.d.ts.map +1 -0
  101. package/dist/policy/keyring-origins.js +213 -0
  102. package/dist/policy/keyring-origins.js.map +1 -0
  103. package/dist/policy/keyring-seal.d.ts +9 -0
  104. package/dist/policy/keyring-seal.d.ts.map +1 -1
  105. package/dist/policy/keyring-seal.js +18 -6
  106. package/dist/policy/keyring-seal.js.map +1 -1
  107. package/dist/policy/safety-policy.d.ts +1 -1
  108. package/dist/policy/safety-policy.d.ts.map +1 -1
  109. package/dist/policy/safety-policy.js +1 -1
  110. package/dist/policy/safety-policy.js.map +1 -1
  111. package/dist/policy/turned-away.d.ts +1 -0
  112. package/dist/policy/turned-away.d.ts.map +1 -1
  113. package/dist/policy/turned-away.js +11 -0
  114. package/dist/policy/turned-away.js.map +1 -1
  115. package/dist/protocol/doors/host-protocol.d.ts +1 -0
  116. package/dist/protocol/doors/host-protocol.d.ts.map +1 -1
  117. package/dist/protocol/doors/host-protocol.js +1 -0
  118. package/dist/protocol/doors/host-protocol.js.map +1 -1
  119. package/dist/protocol/doors/webext-links.d.ts +1 -0
  120. package/dist/protocol/doors/webext-links.d.ts.map +1 -1
  121. package/dist/protocol/doors/webext-links.js +1 -0
  122. package/dist/protocol/doors/webext-links.js.map +1 -1
  123. package/dist/protocol/peer-dial.d.ts +2 -0
  124. package/dist/protocol/peer-dial.d.ts.map +1 -1
  125. package/dist/protocol/peer-dial.js +62 -29
  126. package/dist/protocol/peer-dial.js.map +1 -1
  127. package/dist/protocol/raw/raw-json-routes.d.ts +193 -0
  128. package/dist/protocol/raw/raw-json-routes.d.ts.map +1 -1
  129. package/dist/protocol/raw/raw-json-routes.js +5 -0
  130. package/dist/protocol/raw/raw-json-routes.js.map +1 -1
  131. package/dist/protocol/raw/raw-routes.d.ts +31 -0
  132. package/dist/protocol/raw/raw-routes.d.ts.map +1 -1
  133. package/dist/protocol/raw/raw-routes.js +8 -0
  134. package/dist/protocol/raw/raw-routes.js.map +1 -1
  135. package/dist/schemas/agent-place.d.ts +10 -0
  136. package/dist/schemas/agent-place.d.ts.map +1 -0
  137. package/dist/schemas/agent-place.js +15 -0
  138. package/dist/schemas/agent-place.js.map +1 -0
  139. package/dist/schemas/agent.d.ts +116 -83
  140. package/dist/schemas/agent.d.ts.map +1 -1
  141. package/dist/schemas/agent.js +26 -39
  142. package/dist/schemas/agent.js.map +1 -1
  143. package/dist/schemas/agents-list.d.ts +38 -0
  144. package/dist/schemas/agents-list.d.ts.map +1 -1
  145. package/dist/schemas/agents.d.ts +117 -16
  146. package/dist/schemas/agents.d.ts.map +1 -1
  147. package/dist/schemas/agents.js +19 -21
  148. package/dist/schemas/agents.js.map +1 -1
  149. package/dist/schemas/attach.d.ts +8 -0
  150. package/dist/schemas/attach.d.ts.map +1 -0
  151. package/dist/schemas/attach.js +14 -0
  152. package/dist/schemas/attach.js.map +1 -0
  153. package/dist/schemas/command-admission.d.ts +71 -0
  154. package/dist/schemas/command-admission.d.ts.map +1 -0
  155. package/dist/schemas/command-admission.js +27 -0
  156. package/dist/schemas/command-admission.js.map +1 -0
  157. package/dist/schemas/conversation-links.d.ts +44 -0
  158. package/dist/schemas/conversation-links.d.ts.map +1 -0
  159. package/dist/schemas/conversation-links.js +35 -0
  160. package/dist/schemas/conversation-links.js.map +1 -0
  161. package/dist/schemas/data-protection.d.ts +5 -2
  162. package/dist/schemas/data-protection.d.ts.map +1 -1
  163. package/dist/schemas/data-protection.js +17 -1
  164. package/dist/schemas/data-protection.js.map +1 -1
  165. package/dist/schemas/device-folder.d.ts +61 -0
  166. package/dist/schemas/device-folder.d.ts.map +1 -0
  167. package/dist/schemas/device-folder.js +24 -0
  168. package/dist/schemas/device-folder.js.map +1 -0
  169. package/dist/schemas/devices.d.ts +112 -39
  170. package/dist/schemas/devices.d.ts.map +1 -1
  171. package/dist/schemas/devices.js +8 -10
  172. package/dist/schemas/devices.js.map +1 -1
  173. package/dist/schemas/hosts.d.ts +2 -0
  174. package/dist/schemas/hosts.d.ts.map +1 -1
  175. package/dist/schemas/hosts.js +2 -0
  176. package/dist/schemas/hosts.js.map +1 -1
  177. package/dist/schemas/keyring-native.d.ts +137 -0
  178. package/dist/schemas/keyring-native.d.ts.map +1 -0
  179. package/dist/schemas/keyring-native.js +69 -0
  180. package/dist/schemas/keyring-native.js.map +1 -0
  181. package/dist/schemas/keyring.d.ts +413 -0
  182. package/dist/schemas/keyring.d.ts.map +1 -1
  183. package/dist/schemas/keyring.js +139 -4
  184. package/dist/schemas/keyring.js.map +1 -1
  185. package/dist/schemas/metrics.d.ts +11 -0
  186. package/dist/schemas/metrics.d.ts.map +1 -1
  187. package/dist/schemas/metrics.js +17 -0
  188. package/dist/schemas/metrics.js.map +1 -1
  189. package/dist/schemas/phone-passwords.d.ts +186 -0
  190. package/dist/schemas/phone-passwords.d.ts.map +1 -0
  191. package/dist/schemas/phone-passwords.js +25 -0
  192. package/dist/schemas/phone-passwords.js.map +1 -0
  193. package/dist/schemas/providers/plan-limits.d.ts +74 -0
  194. package/dist/schemas/providers/plan-limits.d.ts.map +1 -1
  195. package/dist/schemas/providers/plan-limits.js +31 -0
  196. package/dist/schemas/providers/plan-limits.js.map +1 -1
  197. package/dist/schemas/providers/provider-oauth.d.ts +24 -0
  198. package/dist/schemas/providers/provider-oauth.d.ts.map +1 -1
  199. package/dist/schemas/providers/usage.d.ts +1 -0
  200. package/dist/schemas/providers/usage.d.ts.map +1 -1
  201. package/dist/schemas/providers/usage.js +1 -0
  202. package/dist/schemas/providers/usage.js.map +1 -1
  203. package/dist/schemas/push.d.ts +13 -0
  204. package/dist/schemas/push.d.ts.map +1 -1
  205. package/dist/schemas/push.js +11 -1
  206. package/dist/schemas/push.js.map +1 -1
  207. package/dist/schemas/sandbox-passwords.d.ts +288 -0
  208. package/dist/schemas/sandbox-passwords.d.ts.map +1 -0
  209. package/dist/schemas/sandbox-passwords.js +66 -0
  210. package/dist/schemas/sandbox-passwords.js.map +1 -0
  211. package/dist/schemas/secrets.d.ts +2 -0
  212. package/dist/schemas/secrets.d.ts.map +1 -1
  213. package/dist/schemas/secrets.js +4 -0
  214. package/dist/schemas/secrets.js.map +1 -1
  215. package/dist/schemas/settings-history.d.ts +1 -1
  216. package/dist/schemas/settings-history.d.ts.map +1 -1
  217. package/dist/schemas/settings-history.js +15 -0
  218. package/dist/schemas/settings-history.js.map +1 -1
  219. package/dist/schemas/settings-savings.d.ts +709 -0
  220. package/dist/schemas/settings-savings.d.ts.map +1 -0
  221. package/dist/schemas/settings-savings.js +53 -0
  222. package/dist/schemas/settings-savings.js.map +1 -0
  223. package/dist/schemas/settings.d.ts +7 -673
  224. package/dist/schemas/settings.d.ts.map +1 -1
  225. package/dist/schemas/settings.js +7 -58
  226. package/dist/schemas/settings.js.map +1 -1
  227. package/dist/schemas/terminal.d.ts +5 -0
  228. package/dist/schemas/terminal.d.ts.map +1 -1
  229. package/dist/schemas/terminal.js +4 -0
  230. package/dist/schemas/terminal.js.map +1 -1
  231. package/dist/schemas/work-assurance.d.ts +24 -0
  232. package/dist/schemas/work-assurance.d.ts.map +1 -0
  233. package/dist/schemas/work-assurance.js +23 -0
  234. package/dist/schemas/work-assurance.js.map +1 -0
  235. package/dist/schemas/workspace/workspace-tree.d.ts +23 -0
  236. package/dist/schemas/workspace/workspace-tree.d.ts.map +1 -1
  237. package/dist/schemas/workspace/workspace-tree.js +20 -0
  238. package/dist/schemas/workspace/workspace-tree.js.map +1 -1
  239. package/dist/state/auth-state.d.ts +4 -0
  240. package/dist/state/auth-state.d.ts.map +1 -0
  241. package/dist/state/auth-state.js +37 -0
  242. package/dist/state/auth-state.js.map +1 -0
  243. package/dist/state/definition.d.ts +12 -4
  244. package/dist/state/definition.d.ts.map +1 -1
  245. package/dist/state/history-state.d.ts.map +1 -1
  246. package/dist/state/history-state.js +17 -1
  247. package/dist/state/history-state.js.map +1 -1
  248. package/dist/state/runtime-state.d.ts.map +1 -1
  249. package/dist/state/runtime-state.js.map +1 -1
  250. package/dist/text/transcript-fold.js +5 -5
  251. package/dist/text/transcript-fold.js.map +1 -1
  252. package/dist/webext/index.d.ts +1 -0
  253. package/dist/webext/index.d.ts.map +1 -1
  254. package/dist/webext/index.js +1 -0
  255. package/dist/webext/index.js.map +1 -1
  256. package/package.json +6 -5
  257. package/src/contracts/agent.contract.ts +13 -1
  258. package/src/contracts/agents.contract.ts +4 -3
  259. package/src/contracts/device.contract.ts +16 -0
  260. package/src/contracts/endpoints.contract.ts +3 -0
  261. package/src/contracts/push.contract.ts +23 -1
  262. package/src/contracts/secrets.contract.ts +39 -0
  263. package/src/contracts/workspace.contract.ts +16 -0
  264. package/src/events/agent-events.ts +6 -1
  265. package/src/events/agent-transcript.ts +48 -0
  266. package/src/events/agent-words.ts +13 -0
  267. package/src/events/requests.ts +41 -3
  268. package/src/events/sandbox-notice.ts +3 -0
  269. package/src/events/transcript.ts +30 -28
  270. package/src/events/undelivered.ts +18 -0
  271. package/src/ids/conversation-ids.ts +7 -0
  272. package/src/ids/row-ids.ts +20 -0
  273. package/src/models/agent-lanes.ts +9 -3
  274. package/src/models/agent-standing.ts +9 -1
  275. package/src/models/plan-pools.test.ts +128 -20
  276. package/src/models/plan-pools.ts +114 -31
  277. package/src/netd/generated/netd-wire.json +25 -0
  278. package/src/netd/generated/wire.ts +1 -1
  279. package/src/policy/command-classes.ts +2 -2
  280. package/src/policy/keyring-origins.test.ts +132 -0
  281. package/src/policy/keyring-origins.ts +287 -0
  282. package/src/policy/keyring-seal.test.ts +37 -2
  283. package/src/policy/keyring-seal.ts +33 -7
  284. package/src/policy/safety-policy.ts +1 -1
  285. package/src/policy/tests/safety-policy.test.ts +1 -1
  286. package/src/policy/turned-away.ts +16 -0
  287. package/src/protocol/doors/host-protocol.ts +3 -0
  288. package/src/protocol/doors/webext-links.ts +3 -0
  289. package/src/protocol/peer-dial.test.ts +90 -4
  290. package/src/protocol/peer-dial.ts +83 -39
  291. package/src/protocol/raw/raw-json-routes.ts +13 -0
  292. package/src/protocol/raw/raw-routes.ts +12 -1
  293. package/src/schemas/agent-place.ts +22 -0
  294. package/src/schemas/agent.ts +42 -78
  295. package/src/schemas/agents.ts +41 -46
  296. package/src/schemas/attach.ts +23 -0
  297. package/src/schemas/command-admission.ts +57 -0
  298. package/src/schemas/conversation-links.ts +62 -0
  299. package/src/schemas/data-protection.ts +36 -10
  300. package/src/schemas/device-folder.ts +59 -0
  301. package/src/schemas/devices.ts +17 -42
  302. package/src/schemas/hosts.ts +4 -0
  303. package/src/schemas/keyring-native.test.ts +13 -0
  304. package/src/schemas/keyring-native.ts +101 -0
  305. package/src/schemas/keyring.ts +202 -4
  306. package/src/schemas/metrics.ts +28 -3
  307. package/src/schemas/phone-passwords.ts +51 -0
  308. package/src/schemas/providers/plan-limits.ts +49 -2
  309. package/src/schemas/providers/usage.ts +2 -0
  310. package/src/schemas/push.ts +19 -3
  311. package/src/schemas/sandbox-passwords.ts +88 -0
  312. package/src/schemas/secrets.ts +4 -0
  313. package/src/schemas/settings-history.ts +20 -0
  314. package/src/schemas/settings-savings.ts +125 -0
  315. package/src/schemas/settings.test.ts +38 -0
  316. package/src/schemas/settings.ts +20 -128
  317. package/src/schemas/terminal.ts +8 -0
  318. package/src/schemas/work-assurance.ts +36 -0
  319. package/src/schemas/workspace/workspace-tree.ts +32 -0
  320. package/src/state/auth-state.ts +89 -0
  321. package/src/state/history-state.ts +44 -1
  322. package/src/state/runtime-state.ts +5 -4
  323. package/src/text/transcript-fold.test.ts +67 -0
  324. package/src/text/transcript-fold.ts +6 -6
  325. package/src/webext/index.ts +2 -0
@@ -0,0 +1,89 @@
1
+ import { STATE_DIR } from "@intentic/constants";
2
+ import type { StateFile } from "./state-portability.js";
3
+ import type { WorkspaceStatePath } from "./workspace-state.js";
4
+
5
+ // The auth root holds AI-provider logins, the sandbox's secret vaults and the trust files a turn must not edit (mode
6
+ // 0600, off the file routes, tree walk and search index). It lives at `.intentic/secrets/auth/` unless AGENT_AUTH_DIR
7
+ // moved it, and the workspace table names it once, as a `secret` directory. This table classifies what is inside, so
8
+ // an export does not carry this sandbox's own keys and pairings with the credentials, and does not drop the owner's
9
+ // restrictions with them either. auth-state-coverage.test.ts in the daemon keeps it complete.
10
+ //
11
+ // The default for a path no entry claims is `secret`, the class of the directory itself: a provider home (`claude/`,
12
+ // `codex/`, `cliproxy/`, `opencode/`…) is a login, and a new provider lands secret by construction.
13
+ //
14
+ // The classes follow the history table's precedent. A restriction the owner set is `carry`: a secret that travels must
15
+ // not arrive ungated. A yes the owner gave (a grant, a release, a widened rule) is `identity`, like the hook and extension
16
+ // approvals there: a trust decision the target's owner makes again.
17
+
18
+ // Where the auth root sits inside the workspace when AGENT_AUTH_DIR does not move it; a declared workspace path.
19
+ export const AUTH_ROOT_IN_WORKSPACE = `${STATE_DIR}/secrets/auth/` as const satisfies WorkspaceStatePath;
20
+
21
+ // Auth-root-relative paths, forward-slash, matched by prefix; a directory keeps its trailing slash.
22
+ export const AUTH_STATE_FILES: readonly StateFile[] = [
23
+ /* ---- the owner's restrictions: no credential in them, and loosened if left behind ---- */
24
+
25
+ // Which credentials need a named person's click (secrets/credential-gates.ts).
26
+ { path: "credential-gates.json", portability: "carry" },
27
+ // Where each secret may be sent (secrets/guards/host-guards.ts).
28
+ { path: "secret-hosts.json", portability: "carry" },
29
+ // The privacy shield's policy: whether it masks, what it looks for, which providers it trusts.
30
+ { path: "privacy-shield.json", portability: "carry" },
31
+ // The execution boundary agents run in (workload/domain/agent-domain-policy.ts).
32
+ { path: "agent-domain.json", portability: "carry" },
33
+
34
+ /* ---- credentials and what holds their values ---- */
35
+
36
+ { path: "sandbox-secrets.json", portability: "secret" },
37
+ { path: "capability-secrets.json", portability: "secret" },
38
+ { path: "extension-secrets.json", portability: "secret" },
39
+ // The personal data the shield masked, by token, and the pictures it painted over.
40
+ { path: "privacy-vault.json", portability: "secret" },
41
+ { path: "privacy-images/", portability: "secret" },
42
+ { path: "ssh-keys/", portability: "secret" },
43
+ // An update's pre-images of the files above; a vault's copy is a vault.
44
+ { path: "converting/", portability: "secret" },
45
+
46
+ /* ---- yeses the owner gave here: decided again on the target ---- */
47
+
48
+ // Sandbox-wide permissions ("Always: <line>") and each conversation's own (personas/owner-grants.ts,
49
+ // conversation-grants.ts); a conversation's card simply asks again, so only the sandbox-wide ones carry a note.
50
+ { path: "owner-grants.json", portability: "identity", note: "Give sandbox-wide permissions again from the Access tab." },
51
+ { path: "conversation-grants.json", portability: "identity" },
52
+ // An approver's release of a gated credential for one conversation.
53
+ { path: "credential-releases.json", portability: "identity" },
54
+ // Programs a secret may be typed into unasked; unset, every typing asks.
55
+ { path: "secret-programs.json", portability: "identity", note: "Allow programs to receive secrets again from Secrets." },
56
+ // Per-card credential rules and raw delivery, the owner's widening of a connector's own rules.
57
+ { path: "credential-policy.json", portability: "identity", note: "Set a connection's credential rules and delivery again from Capabilities." },
58
+
59
+ /* ---- this sandbox's own keys, and what it is paired with ---- */
60
+
61
+ // The keyring keypair the owner's computers pinned their shares to; only the public halves ever leave.
62
+ { path: "keyring-keys.json", portability: "identity", note: "Passwords shared from your computers are shared again with the new sandbox." },
63
+ // What each connected computer's keyring said, the entries copied to this sandbox's key, deliveries waiting for a
64
+ // computer, and the needs raised to them.
65
+ { path: "keyring-devices.json", portability: "identity" },
66
+ { path: "keyring-copies.json", portability: "identity" },
67
+ { path: "keyring-sync-mailbox.json", portability: "identity" },
68
+ { path: "keyring-needs.json", portability: "identity" },
69
+ // The credential broker's signing key and the privacy gateway's token key, each minted on first use.
70
+ { path: "broker-session.key", portability: "identity" },
71
+ { path: "privacy-gateway.key", portability: "identity" },
72
+ // The organisation policy the platform hands this sandbox; the target's platform hands its own.
73
+ { path: "org-policy.json", portability: "identity" },
74
+
75
+ /* ---- regenerated by the target ---- */
76
+
77
+ // Seat refusals the provider answered, and the model catalogs fetched for each runtime.
78
+ { path: "claude/seats.json", portability: "derived" },
79
+ { path: "claude/models.json", portability: "derived" },
80
+ { path: "cursor/models.json", portability: "derived" },
81
+ { path: "devin/models.json", portability: "derived" },
82
+ { path: "gemini/models.json", portability: "derived" },
83
+ // Each custom endpoint's last discovered model list, fetched again from the endpoint.
84
+ { path: "endpoints/", portability: "derived" },
85
+ // Values a computer released for one use each, for masking only; never outlive the process handed them.
86
+ { path: "keyring-released.json", portability: "derived" },
87
+ // The shell script and socket OpenCode runs commands through, written at boot.
88
+ { path: "opencode-shell/", portability: "derived" },
89
+ ];
@@ -25,6 +25,14 @@ export const HISTORY_STATE_FILES: readonly StateFile[] = [
25
25
  // The tasks this sandbox's conversations handed to linked sandboxes (links/linked-children.ts), followed until they
26
26
  // settle: part of the conversations' own record, so it goes where they go.
27
27
  { path: "links/linked-children.json", portability: "carry" },
28
+ // One file per agent a conversation spawned (agent/subagents/spawned-children.ts): what its parent supervises it by
29
+ // (its run, session, last report and result), read back at boot so a restart does not orphan it. Part of the
30
+ // conversations' own record, so it goes where they go.
31
+ { path: "spawned-children/", portability: "carry" },
32
+ // One file per workflow run a conversation started (agent/subagents/workflows/script-runs.ts): its script, its calls and what
33
+ // each handed back, so a restart picks it up where it was and a later run can resume from its finished calls. Part of
34
+ // the conversations' own record, so it goes where they go.
35
+ { path: "script-runs/", portability: "carry" },
28
36
  // The long tool outputs those transcripts name rather than hold, stored once by content for every record naming
29
37
  // them; a transcript without them keeps only each output's start.
30
38
  { path: "blobs/", portability: "carry" },
@@ -48,6 +56,10 @@ export const HISTORY_STATE_FILES: readonly StateFile[] = [
48
56
  { path: "audit/", portability: "carry" },
49
57
  { path: "usage.jsonl", portability: "carry" },
50
58
  { path: "account-usage.json", portability: "carry" },
59
+ // What each provider's usage answers have been made of (their paths, and one redacted sample), so an answer that
60
+ // changes is noticed. Carried: the provider answers the same wherever the sandbox runs, and a fresh record would
61
+ // take the next changed answer as the first one.
62
+ { path: "provider-answers.json", portability: "carry" },
51
63
  // Per-account stay-away for a provider's usage endpoint. Carried, not re-earned: earning one costs the very read it
52
64
  // holds off, and is answered with a deadline measured from that moment. Entries past their instant are inert.
53
65
  { path: "usage-parks.json", portability: "carry" },
@@ -71,6 +83,14 @@ export const HISTORY_STATE_FILES: readonly StateFile[] = [
71
83
  { path: "apply-events.ndjson", portability: "carry" },
72
84
  { path: "check-events/", portability: "carry" },
73
85
 
86
+ // User-started operator panels resume on this sandbox after a restart; a moved sandbox starts inert.
87
+ { path: "panels.json", portability: "derived" },
88
+ // Receipts name kept commands lost with container-local capture storage; never replay arbitrary commands.
89
+ { path: "kept-jobs/", portability: "derived" },
90
+ // The last hour's turns `agents message` and each link started (the daemon's store/start-window.ts), so a restart does
91
+ // not reopen their hourly ceilings; a moved sandbox starts its hour afresh.
92
+ { path: "turn-starts.json", portability: "derived" },
93
+
74
94
  /* ---- regenerated by the target ---- */
75
95
 
76
96
  // Deliberately omitted: the branch lives in gits/, the registry in conversations.db; regenerated on the next turn.
@@ -185,7 +205,11 @@ export const HISTORY_STATE_FILES: readonly StateFile[] = [
185
205
  portability: "identity",
186
206
  note: "Re-invite collaborators from the Access tab, a grant is the platform's record, and the target enforces its own copy.",
187
207
  },
188
- { path: "identity/control-tokens.json", portability: "identity", note: "Mint fresh control tokens, the old ones authenticate against the source sandbox." },
208
+ {
209
+ path: "identity/control-tokens.json",
210
+ portability: "identity",
211
+ note: "Mint fresh control tokens, the old ones authenticate against the source sandbox.",
212
+ },
189
213
  // The links other sandboxes hand this one tasks through (links/inbound-links.ts): hashed tokens like the control
190
214
  // tokens, each minted here, and the tasks filed under them; elsewhere they would let the paired sandboxes reach the
191
215
  // target in this one's name.
@@ -223,6 +247,9 @@ export const HISTORY_STATE_FILES: readonly StateFile[] = [
223
247
  { path: "phone-enrollments.json", portability: "identity", note: "Pair your phone again from its card: the app is still installed." },
224
248
  { path: "phone-pair-consumed.json", portability: "identity" },
225
249
  { path: "phone-wake.json", portability: "identity" },
250
+ // Which computers' keyrings each phone paired with for Passwords (phones/phone-pairings.ts): a shortcut over the
251
+ // keyrings' own pinned keys, keyed by phones paired to this sandbox, so it stays with the pairings above.
252
+ { path: "phone-pairings.json", portability: "identity" },
226
253
  // Setup-device pairing burn list; carrying it would mark another sandbox's fresh pairing as spent.
227
254
  { path: "host-pair-consumed.json", portability: "identity" },
228
255
  // Lands waiting for the computer whose folder they go to, and which computer last held each attached folder
@@ -256,6 +283,11 @@ export const HISTORY_STATE_FILES: readonly StateFile[] = [
256
283
  // person, since the key that signed it stays behind.
257
284
  { path: "automation-holds/", portability: "carry" },
258
285
  { path: "automation-holds.key", portability: "identity", note: "A held wake that was counting down arrives waiting for your yes instead." },
286
+ // What waits for an automation fire not journalled yet (the daemon's automations/durable/inbox-store.ts): a channel
287
+ // message in its debounce or behind a running fire, a workspace event behind its chore. Travels with the turn journal
288
+ // in conversations.db, which names the rows a fire already took.
289
+ { path: "automation-listener-inbox.json", portability: "carry" },
290
+ { path: "automation-workspace-inbox.json", portability: "carry" },
259
291
  { path: "local-cert/", portability: "identity" },
260
292
 
261
293
  /* ---- the state engine's own bookkeeping (the daemon's store/evolution/state-journal.ts) ---- */
@@ -267,4 +299,15 @@ export const HISTORY_STATE_FILES: readonly StateFile[] = [
267
299
  // Every conversation the import of the pre-1.308 layout settled (the daemon's conversations/registry/pre-1308-import.ts),
268
300
  // so one deleted after its import is not brought back from the old files still on disk. About this volume only.
269
301
  { path: "pre-1308-import.json", portability: "derived" },
302
+
303
+ /* ---- written beside the daemon, by the image, the host's ic and the package manager ---- */
304
+
305
+ // The terminal's typed history (the image's HISTFILE, made by docker-entrypoint.sh): the owner's own, kept so its
306
+ // suggestions survive a rebuild. `secret`, since a typed line can hold a pasted token.
307
+ { path: "shell/", portability: "secret" },
308
+ // ic's copy of its records for this sandbox (ic's sandbox/mirror.rs): its channel and rollback target, the machine
309
+ // that keeps it, its backups and repairs. About the machine it runs on, so the target's ic writes its own.
310
+ { path: ".ic/", portability: "identity" },
311
+ // pnpm's package store for installs in a checkout under /history, kept at the top of the mount pnpm finds it on.
312
+ { path: ".pnpm-store/", portability: "derived" },
270
313
  ];
@@ -53,10 +53,11 @@ const RUNTIME_DOMAINS = [
53
53
  // Commit subject drafted after landing; arrives too late for the turn-end refresh, needs its own push.
54
54
  { domain: "landings", invalidates: [["git", "changes"]] },
55
55
 
56
- // A pipeline run reached its end (webhook delivery, or the REST poll for a repo with no hook). The board's own
57
- // poll is the freshness floor, not the answer: somebody watching a run finish must not wait out a poll interval.
58
- // Runs only: the frame doesn't name which run moved, and re-reading every open row's job graph would cost a
59
- // vendor call per row. The row re-reads its own graph off the status this invalidation lands (useRunJobs.ts).
56
+ // A pipeline run or one of its jobs moved: every webhook delivery, in flight or ended (2026-10-20), or the REST poll
57
+ // for a repo with no hook. The board's own poll is the freshness floor, not the answer: somebody watching a run
58
+ // must not wait out a poll interval. Runs only: the frame doesn't name which run moved, and re-reading every open
59
+ // row's job graph would cost a vendor call per row. An open in-flight row re-reads its own graph when the board's
60
+ // runs land (useRunJobs.ts); the daemon's CI-shaped watches recheck on it too (watchers.ts).
60
61
  { domain: "ci", invalidates: [["ci-runs"]] },
61
62
 
62
63
  // An engine install starting or ending, whoever started it; the card's only feed, since a read costs registry calls.
@@ -113,6 +113,22 @@ describe("foldTurn", () => {
113
113
  ]);
114
114
  });
115
115
 
116
+ // What a reader needs once nothing in memory remembers the subagent: the card the turn settles into keeps it.
117
+ it("keeps where the runtime holds an in-process subagent's own record on its card", () => {
118
+ const events: AgentEvent[] = [
119
+ { kind: "tool_call", id: "task-1", name: "Agent", category: "other", status: "in_progress" },
120
+ { kind: "subagent", id: "task-1", subagentKind: "subagent", agentType: "Explore" },
121
+ { kind: "subagent_update", id: "task-1", sdk: { sessionId: "ses-1", agentId: "a1b2" } },
122
+ { kind: "subagent_update", id: "task-1", status: "completed" },
123
+ ];
124
+ expect(foldOf("delegate", events).at(-1)?.tools?.[0]?.subagent).toEqual({
125
+ kind: "subagent",
126
+ agentType: "Explore",
127
+ status: "completed",
128
+ sdk: { sessionId: "ses-1", agentId: "a1b2" },
129
+ });
130
+ });
131
+
116
132
  // A spawned subagent is named by its own conversation, not the call that started it; the spawn answers with that
117
133
  // name, which is how its card is found, so it reads on its card exactly as an in-process one does.
118
134
  it("puts a spawned subagent on the card of the call whose result names it", () => {
@@ -931,6 +947,57 @@ describe(`a refusal that ran nothing`, () => {
931
947
  expect(fold.ranNothing).toBe(false);
932
948
  });
933
949
 
950
+ // The reported row (onboarding review 2026-10-18, F07): the trial ran out on a later step of a turn that had already
951
+ // edited a file, and the row said the message was not delivered and held to send again. Neither was true: the turn
952
+ // ran, nothing holds its words (turn-runs keeps only a turn turned away at the door), and a resend repeats its edits.
953
+ describe(`arriving after the turn already ran`, () => {
954
+ const SPENT = {
955
+ kind: `error`,
956
+ code: `trial-exhausted`,
957
+ message: `Free trial used up for today: every free agent step is spent. Connect a model to keep going.`,
958
+ } as const satisfies AgentEvent;
959
+ const EDITED: readonly AgentEvent[] = [
960
+ { kind: `tool_call`, id: `t1`, name: `Edit`, category: `edit`, status: `completed`, target: `src/page.tsx` },
961
+ ];
962
+
963
+ it(`says the run stopped partway with its changes kept, and offers another model rather than a resend`, () => {
964
+ const fold = new TranscriptFold(openingOf(`change the heading`));
965
+ for (const event of EDITED) {
966
+ fold.apply(event);
967
+ }
968
+ fold.apply(SPENT);
969
+
970
+ expect(fold.rows.map((row) => row.role)).toEqual([`user`, `assistant`, `notice`]);
971
+ expect(fold.rows.at(-1)).toEqual({
972
+ role: `notice`,
973
+ text: `${SPENT.message} The run stopped partway. The changes it made so far are kept: continue with another model to pick up from here.`,
974
+ noticeAction: `switchModel`,
975
+ noticeCode: { code: `stoppedPartway`, params: { message: SPENT.message, error: `trial-exhausted`, switchModel: true } },
976
+ });
977
+ expect(fold.ranNothing).toBe(false);
978
+ });
979
+
980
+ // Another model does not clear a full disk; the row still never claims the words are held.
981
+ it(`offers no model switch for a refusal another model would not get past`, () => {
982
+ const disk = { kind: `error`, code: `sandbox-disk-low`, message: `The sandbox's disk is full.` } as const satisfies AgentEvent;
983
+ expect(foldOf(`change the heading`, [...EDITED, disk]).at(-1)).toEqual({
984
+ role: `notice`,
985
+ text: `${disk.message} The run stopped partway. The changes it made so far are kept: send a message to pick up from here.`,
986
+ noticeCode: { code: `stoppedPartway`, params: { message: disk.message, error: `sandbox-disk-low` } },
987
+ });
988
+ });
989
+
990
+ it(`keeps the not-delivered row for the same refusal when nothing had run`, () => {
991
+ expect(foldOf(`change the heading`, [SPENT])).toEqual([
992
+ {
993
+ role: `notice`,
994
+ text: `${SPENT.message} Your message was not delivered: it is held for you to send again.`,
995
+ noticeCode: { code: `undelivered`, params: { message: SPENT.message, error: `trial-exhausted` } },
996
+ },
997
+ ]);
998
+ });
999
+ });
1000
+
934
1001
  // The sandbox, not a composer, keeps a turn it started itself (a fix press, a peer's message): the frame says so
935
1002
  // with `held`. The bug this exists for: such a refusal took the fix prompt out, and no queue anywhere held a copy.
936
1003
  describe(`of a turn the sandbox keeps`, () => {
@@ -15,8 +15,8 @@ import { contextTrimLine, contextTrimNotice } from "../schemas/context-trim.js";
15
15
  import { keptWarmLine, keptWarmNotice } from "../schemas/keep-warm.js";
16
16
  import { handedOffLine, handedOffNotice } from "../schemas/providers/handoff.js";
17
17
  import { isLandConflict } from "../events/land-conflict.js";
18
- import { turnedAwayCode } from "../policy/turned-away.js";
19
- import { undeliveredRow } from "../events/undelivered.js";
18
+ import { anotherModelClears, turnedAwayCode } from "../policy/turned-away.js";
19
+ import { stoppedPartwayRow, undeliveredRow } from "../events/undelivered.js";
20
20
  import { mentionedPathTokens } from "./mentions.js";
21
21
  import { unspokenPromptRow } from "../events/agent-words.js";
22
22
  import { needRowText } from "../events/need-wake.js";
@@ -239,8 +239,8 @@ const RENEWAL_WITHDRAWN =
239
239
  "The credential was being renewed, but the turn stopped before it could continue: it will not carry on by itself, so press Continue to pick it back up.";
240
240
 
241
241
  // Row for a turn-ending error: the provider's own message plus one clause on what happens next. The live wait itself is
242
- // drawn by the chat, not stored here.
243
- const errorRow = (event: Extract<AgentEvent, { kind: "error" }>): TranscriptRow => {
242
+ // drawn by the chat, not stored here. `ran`: an assistant row stands, so a door refusal stopped the turn partway.
243
+ const errorRow = (event: Extract<AgentEvent, { kind: "error" }>, ran: boolean): TranscriptRow => {
244
244
  const { message, code } = event;
245
245
  const said = failureOf(event);
246
246
  switch (code) {
@@ -281,7 +281,7 @@ const errorRow = (event: Extract<AgentEvent, { kind: "error" }>): TranscriptRow
281
281
  // provider's own uncoded words are only ever themselves.
282
282
  return code === undefined ? { role: "notice", text: message } : { role: "notice", text: message, noticeCode: noticeCode({ code: "failed", params: said }) };
283
283
  }
284
- return heldRow(event);
284
+ return ran && event.held === undefined ? stoppedPartwayRow(said, anotherModelClears(code)) : heldRow(event);
285
285
  };
286
286
 
287
287
  // What a laddered wall's automatic re-runs are doing, said on the failure's own row so the count stays in the record.
@@ -488,7 +488,7 @@ export class TranscriptFold {
488
488
  case "error":
489
489
  // Keeps a refusal (no prose from the provider) from reading as a session that ended mid-question.
490
490
  // A refusal that ran nothing takes its message back out ahead of the notice standing in for it.
491
- return [...this.retract(event), ...this.withdrawRenewal(event), ...this.pushRow(errorRow(event))];
491
+ return [...this.retract(event), ...this.withdrawRenewal(event), ...this.pushRow(errorRow(event, this.rows.some((row) => row.role === "assistant")))];
492
492
  case "plan": {
493
493
  // Folds a plan into an identical retired prose bubble instead of drawing the same markdown twice.
494
494
  const adjacent = this.rows.at(-1);
@@ -9,3 +9,5 @@ export * from "../protocol/doors/webext-protocol.js";
9
9
  export * from "../schemas/webext.js";
10
10
  export * from "../schemas/loopback-catch.js";
11
11
  export * from "../schemas/peer-enrollment.js";
12
+ // What the extension says to `intentic-keyring native-host` (the Passwords app's browser capture and fill).
13
+ export * from "../schemas/keyring-native.js";