@intentic/sandbox-contract 1.344.0 → 1.346.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 (418) hide show
  1. package/README.md +27 -9
  2. package/dist/contracts/accounts.contract.d.ts +24 -80
  3. package/dist/contracts/accounts.contract.d.ts.map +1 -1
  4. package/dist/contracts/agent.contract.d.ts +247 -8
  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 +1570 -33
  9. package/dist/contracts/agents.contract.d.ts.map +1 -1
  10. package/dist/contracts/agents.contract.js +47 -4
  11. package/dist/contracts/agents.contract.js.map +1 -1
  12. package/dist/contracts/device.contract.d.ts +244 -1
  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 -1
  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/providers.contract.d.ts +0 -1
  21. package/dist/contracts/providers.contract.d.ts.map +1 -1
  22. package/dist/contracts/push.contract.d.ts +11 -0
  23. package/dist/contracts/push.contract.d.ts.map +1 -1
  24. package/dist/contracts/push.contract.js +10 -1
  25. package/dist/contracts/push.contract.js.map +1 -1
  26. package/dist/contracts/runner.contract.d.ts +149 -123
  27. package/dist/contracts/runner.contract.d.ts.map +1 -1
  28. package/dist/contracts/secrets.contract.d.ts +169 -0
  29. package/dist/contracts/secrets.contract.d.ts.map +1 -1
  30. package/dist/contracts/secrets.contract.js +35 -0
  31. package/dist/contracts/secrets.contract.js.map +1 -1
  32. package/dist/contracts/sessions.contract.d.ts +2 -0
  33. package/dist/contracts/sessions.contract.d.ts.map +1 -1
  34. package/dist/contracts/settings.contract.d.ts +37 -0
  35. package/dist/contracts/settings.contract.d.ts.map +1 -1
  36. package/dist/contracts/system.contract.d.ts +235 -31
  37. package/dist/contracts/system.contract.d.ts.map +1 -1
  38. package/dist/contracts/translator.contract.d.ts +24 -80
  39. package/dist/contracts/translator.contract.d.ts.map +1 -1
  40. package/dist/contracts/workspace.contract.d.ts +11 -0
  41. package/dist/contracts/workspace.contract.d.ts.map +1 -1
  42. package/dist/contracts/workspace.contract.js +11 -1
  43. package/dist/contracts/workspace.contract.js.map +1 -1
  44. package/dist/events/agent-events.d.ts +60 -0
  45. package/dist/events/agent-events.d.ts.map +1 -1
  46. package/dist/events/agent-events.js +44 -38
  47. package/dist/events/agent-events.js.map +1 -1
  48. package/dist/events/agent-transcript.d.ts +727 -0
  49. package/dist/events/agent-transcript.d.ts.map +1 -0
  50. package/dist/events/agent-transcript.js +34 -0
  51. package/dist/events/agent-transcript.js.map +1 -0
  52. package/dist/events/agent-words.d.ts +5 -0
  53. package/dist/events/agent-words.d.ts.map +1 -1
  54. package/dist/events/agent-words.js +9 -0
  55. package/dist/events/agent-words.js.map +1 -1
  56. package/dist/events/failure-rows.d.ts +14 -0
  57. package/dist/events/failure-rows.d.ts.map +1 -0
  58. package/dist/events/failure-rows.js +109 -0
  59. package/dist/events/failure-rows.js.map +1 -0
  60. package/dist/events/requests.d.ts +143 -0
  61. package/dist/events/requests.d.ts.map +1 -1
  62. package/dist/events/requests.js +35 -1
  63. package/dist/events/requests.js.map +1 -1
  64. package/dist/events/sandbox-notice.d.ts +23 -0
  65. package/dist/events/sandbox-notice.d.ts.map +1 -1
  66. package/dist/events/sandbox-notice.js +2 -0
  67. package/dist/events/sandbox-notice.js.map +1 -1
  68. package/dist/events/system-events.d.ts +156 -0
  69. package/dist/events/system-events.d.ts.map +1 -1
  70. package/dist/events/system-events.js +7 -1
  71. package/dist/events/system-events.js.map +1 -1
  72. package/dist/events/transcript.d.ts +20 -720
  73. package/dist/events/transcript.d.ts.map +1 -1
  74. package/dist/events/transcript.js +17 -19
  75. package/dist/events/transcript.js.map +1 -1
  76. package/dist/ids/conversation-ids.d.ts +2 -0
  77. package/dist/ids/conversation-ids.d.ts.map +1 -1
  78. package/dist/ids/conversation-ids.js +2 -0
  79. package/dist/ids/conversation-ids.js.map +1 -1
  80. package/dist/ids/row-ids.d.ts +3 -0
  81. package/dist/ids/row-ids.d.ts.map +1 -0
  82. package/dist/ids/row-ids.js +11 -0
  83. package/dist/ids/row-ids.js.map +1 -0
  84. package/dist/index.d.ts +2296 -199
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/models/agent-lanes.d.ts.map +1 -1
  87. package/dist/models/agent-lanes.js +6 -7
  88. package/dist/models/agent-lanes.js.map +1 -1
  89. package/dist/models/agent-standing.d.ts +6 -19
  90. package/dist/models/agent-standing.d.ts.map +1 -1
  91. package/dist/models/agent-standing.js +14 -38
  92. package/dist/models/agent-standing.js.map +1 -1
  93. package/dist/models/model-pins.d.ts +3 -0
  94. package/dist/models/model-pins.d.ts.map +1 -1
  95. package/dist/models/model-pins.js +2 -0
  96. package/dist/models/model-pins.js.map +1 -1
  97. package/dist/models/plan-pools.d.ts +26 -4
  98. package/dist/models/plan-pools.d.ts.map +1 -1
  99. package/dist/models/plan-pools.js +159 -40
  100. package/dist/models/plan-pools.js.map +1 -1
  101. package/dist/netd/generated/wire.d.ts +5 -0
  102. package/dist/netd/generated/wire.d.ts.map +1 -1
  103. package/dist/policy/command-classes.d.ts +1 -1
  104. package/dist/policy/command-classes.d.ts.map +1 -1
  105. package/dist/policy/command-classes.js +2 -2
  106. package/dist/policy/command-classes.js.map +1 -1
  107. package/dist/policy/keyring-origins.d.ts +27 -0
  108. package/dist/policy/keyring-origins.d.ts.map +1 -0
  109. package/dist/policy/keyring-origins.js +213 -0
  110. package/dist/policy/keyring-origins.js.map +1 -0
  111. package/dist/policy/keyring-seal.d.ts +9 -0
  112. package/dist/policy/keyring-seal.d.ts.map +1 -1
  113. package/dist/policy/keyring-seal.js +18 -6
  114. package/dist/policy/keyring-seal.js.map +1 -1
  115. package/dist/policy/safety-policy.d.ts +1 -1
  116. package/dist/policy/safety-policy.d.ts.map +1 -1
  117. package/dist/policy/safety-policy.js +1 -1
  118. package/dist/policy/safety-policy.js.map +1 -1
  119. package/dist/policy/turned-away.d.ts +1 -0
  120. package/dist/policy/turned-away.d.ts.map +1 -1
  121. package/dist/policy/turned-away.js +10 -0
  122. package/dist/policy/turned-away.js.map +1 -1
  123. package/dist/protocol/doors/host-protocol.d.ts +1 -0
  124. package/dist/protocol/doors/host-protocol.d.ts.map +1 -1
  125. package/dist/protocol/doors/host-protocol.js +1 -0
  126. package/dist/protocol/doors/host-protocol.js.map +1 -1
  127. package/dist/protocol/doors/runner-protocol.d.ts +1 -0
  128. package/dist/protocol/doors/runner-protocol.d.ts.map +1 -1
  129. package/dist/protocol/doors/runner-protocol.js +1 -0
  130. package/dist/protocol/doors/runner-protocol.js.map +1 -1
  131. package/dist/protocol/doors/webext-links.d.ts +1 -0
  132. package/dist/protocol/doors/webext-links.d.ts.map +1 -1
  133. package/dist/protocol/doors/webext-links.js +1 -0
  134. package/dist/protocol/doors/webext-links.js.map +1 -1
  135. package/dist/protocol/peer-dial.d.ts +2 -0
  136. package/dist/protocol/peer-dial.d.ts.map +1 -1
  137. package/dist/protocol/peer-dial.js +62 -29
  138. package/dist/protocol/peer-dial.js.map +1 -1
  139. package/dist/protocol/raw/raw-json-routes.d.ts +179 -1
  140. package/dist/protocol/raw/raw-json-routes.d.ts.map +1 -1
  141. package/dist/protocol/raw/raw-json-routes.js +5 -0
  142. package/dist/protocol/raw/raw-json-routes.js.map +1 -1
  143. package/dist/protocol/raw/raw-routes.d.ts +35 -0
  144. package/dist/protocol/raw/raw-routes.d.ts.map +1 -1
  145. package/dist/protocol/raw/raw-routes.js +9 -0
  146. package/dist/protocol/raw/raw-routes.js.map +1 -1
  147. package/dist/schemas/agent-next.d.ts +21 -0
  148. package/dist/schemas/agent-next.d.ts.map +1 -0
  149. package/dist/schemas/agent-next.js +21 -0
  150. package/dist/schemas/agent-next.js.map +1 -0
  151. package/dist/schemas/agent-place.d.ts +10 -0
  152. package/dist/schemas/agent-place.d.ts.map +1 -0
  153. package/dist/schemas/agent-place.js +15 -0
  154. package/dist/schemas/agent-place.js.map +1 -0
  155. package/dist/schemas/agent-search.d.ts +45 -0
  156. package/dist/schemas/agent-search.d.ts.map +1 -0
  157. package/dist/schemas/agent-search.js +28 -0
  158. package/dist/schemas/agent-search.js.map +1 -0
  159. package/dist/schemas/agent.d.ts +120 -78
  160. package/dist/schemas/agent.d.ts.map +1 -1
  161. package/dist/schemas/agent.js +40 -49
  162. package/dist/schemas/agent.js.map +1 -1
  163. package/dist/schemas/agents-list.d.ts +54 -0
  164. package/dist/schemas/agents-list.d.ts.map +1 -1
  165. package/dist/schemas/agents.d.ts +165 -59
  166. package/dist/schemas/agents.d.ts.map +1 -1
  167. package/dist/schemas/agents.js +25 -50
  168. package/dist/schemas/agents.js.map +1 -1
  169. package/dist/schemas/attach.d.ts +8 -0
  170. package/dist/schemas/attach.d.ts.map +1 -0
  171. package/dist/schemas/attach.js +14 -0
  172. package/dist/schemas/attach.js.map +1 -0
  173. package/dist/schemas/command-admission.d.ts +71 -0
  174. package/dist/schemas/command-admission.d.ts.map +1 -0
  175. package/dist/schemas/command-admission.js +27 -0
  176. package/dist/schemas/command-admission.js.map +1 -0
  177. package/dist/schemas/compose-overlay.d.ts +9 -0
  178. package/dist/schemas/compose-overlay.d.ts.map +1 -0
  179. package/dist/schemas/compose-overlay.js +11 -0
  180. package/dist/schemas/compose-overlay.js.map +1 -0
  181. package/dist/schemas/composer-drafts.d.ts +169 -0
  182. package/dist/schemas/composer-drafts.d.ts.map +1 -0
  183. package/dist/schemas/composer-drafts.js +60 -0
  184. package/dist/schemas/composer-drafts.js.map +1 -0
  185. package/dist/schemas/conversation-links.d.ts +44 -0
  186. package/dist/schemas/conversation-links.d.ts.map +1 -0
  187. package/dist/schemas/conversation-links.js +35 -0
  188. package/dist/schemas/conversation-links.js.map +1 -0
  189. package/dist/schemas/data-protection.d.ts +1 -1
  190. package/dist/schemas/data-protection.d.ts.map +1 -1
  191. package/dist/schemas/device-commands.d.ts +63 -0
  192. package/dist/schemas/device-commands.d.ts.map +1 -0
  193. package/dist/schemas/device-commands.js +42 -0
  194. package/dist/schemas/device-commands.js.map +1 -0
  195. package/dist/schemas/device-folder.d.ts +11 -0
  196. package/dist/schemas/device-folder.d.ts.map +1 -1
  197. package/dist/schemas/device-folder.js +1 -0
  198. package/dist/schemas/device-folder.js.map +1 -1
  199. package/dist/schemas/devices.d.ts +18 -68
  200. package/dist/schemas/devices.d.ts.map +1 -1
  201. package/dist/schemas/devices.js +8 -45
  202. package/dist/schemas/devices.js.map +1 -1
  203. package/dist/schemas/environment.d.ts.map +1 -1
  204. package/dist/schemas/environment.js.map +1 -1
  205. package/dist/schemas/hosts.d.ts +29 -0
  206. package/dist/schemas/hosts.d.ts.map +1 -1
  207. package/dist/schemas/hosts.js +23 -0
  208. package/dist/schemas/hosts.js.map +1 -1
  209. package/dist/schemas/keyring-native.d.ts +137 -0
  210. package/dist/schemas/keyring-native.d.ts.map +1 -0
  211. package/dist/schemas/keyring-native.js +69 -0
  212. package/dist/schemas/keyring-native.js.map +1 -0
  213. package/dist/schemas/keyring.d.ts +413 -0
  214. package/dist/schemas/keyring.d.ts.map +1 -1
  215. package/dist/schemas/keyring.js +139 -4
  216. package/dist/schemas/keyring.js.map +1 -1
  217. package/dist/schemas/phone-passwords.d.ts +186 -0
  218. package/dist/schemas/phone-passwords.d.ts.map +1 -0
  219. package/dist/schemas/phone-passwords.js +25 -0
  220. package/dist/schemas/phone-passwords.js.map +1 -0
  221. package/dist/schemas/privacy-egress.d.ts +41 -0
  222. package/dist/schemas/privacy-egress.d.ts.map +1 -0
  223. package/dist/schemas/privacy-egress.js +30 -0
  224. package/dist/schemas/privacy-egress.js.map +1 -0
  225. package/dist/schemas/privacy.d.ts +1 -0
  226. package/dist/schemas/privacy.d.ts.map +1 -1
  227. package/dist/schemas/privacy.js +1 -0
  228. package/dist/schemas/privacy.js.map +1 -1
  229. package/dist/schemas/providers/plan-limits.d.ts +76 -130
  230. package/dist/schemas/providers/plan-limits.d.ts.map +1 -1
  231. package/dist/schemas/providers/plan-limits.js +36 -23
  232. package/dist/schemas/providers/plan-limits.js.map +1 -1
  233. package/dist/schemas/providers/provider-oauth.d.ts +24 -82
  234. package/dist/schemas/providers/provider-oauth.d.ts.map +1 -1
  235. package/dist/schemas/providers/provider-oauth.js +1 -6
  236. package/dist/schemas/providers/provider-oauth.js.map +1 -1
  237. package/dist/schemas/providers/refusals.d.ts +64 -0
  238. package/dist/schemas/providers/refusals.d.ts.map +1 -0
  239. package/dist/schemas/providers/refusals.js +33 -0
  240. package/dist/schemas/providers/refusals.js.map +1 -0
  241. package/dist/schemas/providers/usage.d.ts +1 -0
  242. package/dist/schemas/providers/usage.d.ts.map +1 -1
  243. package/dist/schemas/providers/usage.js +1 -0
  244. package/dist/schemas/providers/usage.js.map +1 -1
  245. package/dist/schemas/push.d.ts +13 -0
  246. package/dist/schemas/push.d.ts.map +1 -1
  247. package/dist/schemas/push.js +11 -1
  248. package/dist/schemas/push.js.map +1 -1
  249. package/dist/schemas/sandbox-passwords.d.ts +288 -0
  250. package/dist/schemas/sandbox-passwords.d.ts.map +1 -0
  251. package/dist/schemas/sandbox-passwords.js +66 -0
  252. package/dist/schemas/sandbox-passwords.js.map +1 -0
  253. package/dist/schemas/secrets.d.ts +2 -0
  254. package/dist/schemas/secrets.d.ts.map +1 -1
  255. package/dist/schemas/secrets.js +4 -0
  256. package/dist/schemas/secrets.js.map +1 -1
  257. package/dist/schemas/sessions.js +1 -1
  258. package/dist/schemas/sessions.js.map +1 -1
  259. package/dist/schemas/settings-savings.d.ts +709 -0
  260. package/dist/schemas/settings-savings.d.ts.map +1 -0
  261. package/dist/schemas/settings-savings.js +53 -0
  262. package/dist/schemas/settings-savings.js.map +1 -0
  263. package/dist/schemas/settings.d.ts +7 -671
  264. package/dist/schemas/settings.d.ts.map +1 -1
  265. package/dist/schemas/settings.js +5 -50
  266. package/dist/schemas/settings.js.map +1 -1
  267. package/dist/schemas/system.d.ts +16 -0
  268. package/dist/schemas/system.d.ts.map +1 -1
  269. package/dist/schemas/system.js +11 -0
  270. package/dist/schemas/system.js.map +1 -1
  271. package/dist/schemas/terminal.d.ts +5 -0
  272. package/dist/schemas/terminal.d.ts.map +1 -1
  273. package/dist/schemas/terminal.js +4 -0
  274. package/dist/schemas/terminal.js.map +1 -1
  275. package/dist/schemas/work-assurance.d.ts +24 -0
  276. package/dist/schemas/work-assurance.d.ts.map +1 -0
  277. package/dist/schemas/work-assurance.js +23 -0
  278. package/dist/schemas/work-assurance.js.map +1 -0
  279. package/dist/schemas/workspace/workspace-tree.d.ts +23 -0
  280. package/dist/schemas/workspace/workspace-tree.d.ts.map +1 -1
  281. package/dist/schemas/workspace/workspace-tree.js +20 -0
  282. package/dist/schemas/workspace/workspace-tree.js.map +1 -1
  283. package/dist/state/auth-state.d.ts +4 -0
  284. package/dist/state/auth-state.d.ts.map +1 -0
  285. package/dist/state/auth-state.js +37 -0
  286. package/dist/state/auth-state.js.map +1 -0
  287. package/dist/state/definition.d.ts +12 -0
  288. package/dist/state/definition.d.ts.map +1 -1
  289. package/dist/state/runtime-state.d.ts +3 -0
  290. package/dist/state/runtime-state.d.ts.map +1 -1
  291. package/dist/state/runtime-state.js +1 -0
  292. package/dist/state/runtime-state.js.map +1 -1
  293. package/dist/state/sandbox-build.d.ts +20 -0
  294. package/dist/state/sandbox-build.d.ts.map +1 -0
  295. package/dist/state/sandbox-build.js +43 -0
  296. package/dist/state/sandbox-build.js.map +1 -0
  297. package/dist/state/ways-back.d.ts +4 -0
  298. package/dist/state/ways-back.d.ts.map +1 -0
  299. package/dist/state/ways-back.js +8 -0
  300. package/dist/state/ways-back.js.map +1 -0
  301. package/dist/text/land-rows.d.ts +14 -0
  302. package/dist/text/land-rows.d.ts.map +1 -0
  303. package/dist/text/land-rows.js +86 -0
  304. package/dist/text/land-rows.js.map +1 -0
  305. package/dist/text/transcript-fold.d.ts +4 -2
  306. package/dist/text/transcript-fold.d.ts.map +1 -1
  307. package/dist/text/transcript-fold.js +21 -187
  308. package/dist/text/transcript-fold.js.map +1 -1
  309. package/dist/webext/index.d.ts +1 -0
  310. package/dist/webext/index.d.ts.map +1 -1
  311. package/dist/webext/index.js +1 -0
  312. package/dist/webext/index.js.map +1 -1
  313. package/package.json +7 -6
  314. package/src/contracts/agent.contract.ts +13 -1
  315. package/src/contracts/agents.contract.ts +53 -28
  316. package/src/contracts/device.contract.ts +16 -0
  317. package/src/contracts/endpoints.contract.ts +3 -0
  318. package/src/contracts/push.contract.ts +23 -1
  319. package/src/contracts/secrets.contract.ts +39 -0
  320. package/src/contracts/workspace.contract.ts +16 -0
  321. package/src/events/agent-events.ts +99 -79
  322. package/src/events/agent-transcript.ts +48 -0
  323. package/src/events/agent-words.ts +13 -0
  324. package/src/events/failure-rows.ts +148 -0
  325. package/src/events/requests.ts +41 -3
  326. package/src/events/sandbox-notice.ts +14 -2
  327. package/src/events/system-events.ts +14 -4
  328. package/src/events/transcript.ts +30 -28
  329. package/src/ids/conversation-ids.ts +7 -0
  330. package/src/ids/project-dir.test.ts +2 -2
  331. package/src/ids/project-dir.ts +4 -4
  332. package/src/ids/row-ids.ts +20 -0
  333. package/src/models/agent-lanes.ts +16 -24
  334. package/src/models/agent-runtimes.ts +2 -2
  335. package/src/models/agent-standing.ts +38 -95
  336. package/src/models/model-pins.test.ts +31 -1
  337. package/src/models/model-pins.ts +17 -0
  338. package/src/models/plan-pools.test.ts +274 -31
  339. package/src/models/plan-pools.ts +294 -79
  340. package/src/netd/generated/netd-wire.json +25 -0
  341. package/src/netd/generated/wire.ts +1 -1
  342. package/src/policy/command-classes.ts +2 -2
  343. package/src/policy/keyring-origins.test.ts +132 -0
  344. package/src/policy/keyring-origins.ts +287 -0
  345. package/src/policy/keyring-seal.test.ts +37 -2
  346. package/src/policy/keyring-seal.ts +33 -7
  347. package/src/policy/safety-policy.ts +1 -1
  348. package/src/policy/tests/safety-policy.test.ts +1 -1
  349. package/src/policy/turned-away.ts +15 -0
  350. package/src/protocol/doors/host-protocol.ts +3 -0
  351. package/src/protocol/doors/runner-protocol.ts +4 -1
  352. package/src/protocol/doors/webext-links.ts +3 -0
  353. package/src/protocol/peer-dial.test.ts +90 -4
  354. package/src/protocol/peer-dial.ts +83 -39
  355. package/src/protocol/raw/raw-json-routes.ts +13 -0
  356. package/src/protocol/raw/raw-routes.ts +13 -1
  357. package/src/schemas/agent-next.ts +34 -0
  358. package/src/schemas/agent-place.ts +22 -0
  359. package/src/schemas/agent-search.ts +51 -0
  360. package/src/schemas/agent.ts +63 -90
  361. package/src/schemas/agents.ts +55 -99
  362. package/src/schemas/attach.ts +23 -0
  363. package/src/schemas/command-admission.ts +57 -0
  364. package/src/schemas/compose-overlay.test.ts +35 -0
  365. package/src/schemas/compose-overlay.ts +19 -0
  366. package/src/schemas/composer-drafts.ts +86 -0
  367. package/src/schemas/conversation-links.ts +62 -0
  368. package/src/schemas/data-protection.ts +1 -1
  369. package/src/schemas/device-commands.ts +89 -0
  370. package/src/schemas/device-folder.ts +9 -0
  371. package/src/schemas/devices.ts +28 -110
  372. package/src/schemas/environment.ts +8 -9
  373. package/src/schemas/hosts.ts +60 -0
  374. package/src/schemas/keyring-native.test.ts +13 -0
  375. package/src/schemas/keyring-native.ts +101 -0
  376. package/src/schemas/keyring.ts +202 -4
  377. package/src/schemas/machine-presence.test.ts +33 -0
  378. package/src/schemas/phone-passwords.ts +51 -0
  379. package/src/schemas/privacy-egress.test.ts +83 -0
  380. package/src/schemas/privacy-egress.ts +86 -0
  381. package/src/schemas/privacy.ts +4 -0
  382. package/src/schemas/project-delivery.ts +1 -1
  383. package/src/schemas/providers/plan-limits.test.ts +16 -0
  384. package/src/schemas/providers/plan-limits.ts +55 -49
  385. package/src/schemas/providers/provider-oauth.ts +1 -13
  386. package/src/schemas/providers/refusals.ts +62 -0
  387. package/src/schemas/providers/usage.ts +2 -0
  388. package/src/schemas/push.ts +19 -3
  389. package/src/schemas/sandbox-passwords.ts +88 -0
  390. package/src/schemas/secrets.ts +4 -0
  391. package/src/schemas/sessions.ts +1 -1
  392. package/src/schemas/settings-savings.ts +125 -0
  393. package/src/schemas/settings.ts +10 -116
  394. package/src/schemas/system.ts +15 -0
  395. package/src/schemas/terminal.ts +8 -0
  396. package/src/schemas/work-assurance.ts +36 -0
  397. package/src/schemas/workspace/workspace-tree.ts +32 -0
  398. package/src/state/auth-state.ts +89 -0
  399. package/src/state/runtime-state.ts +10 -4
  400. package/src/state/sandbox-build.test.ts +95 -0
  401. package/src/state/sandbox-build.ts +96 -0
  402. package/src/state/ways-back.test.ts +36 -0
  403. package/src/state/ways-back.ts +19 -0
  404. package/src/state/workspace-state.ts +1 -1
  405. package/src/text/land-rows.ts +111 -0
  406. package/src/text/transcript-fold.test.ts +105 -9
  407. package/src/text/transcript-fold.ts +30 -232
  408. package/src/webext/index.ts +2 -0
  409. package/dist/events/undelivered.d.ts +0 -6
  410. package/dist/events/undelivered.d.ts.map +0 -1
  411. package/dist/events/undelivered.js +0 -9
  412. package/dist/events/undelivered.js.map +0 -1
  413. package/dist/state/history-state.d.ts +0 -3
  414. package/dist/state/history-state.d.ts.map +0 -1
  415. package/dist/state/history-state.js +0 -137
  416. package/dist/state/history-state.js.map +0 -1
  417. package/src/events/undelivered.ts +0 -15
  418. package/src/state/history-state.ts +0 -270
@@ -0,0 +1,125 @@
1
+ // settings-savings: what each token-reduction mechanism saved and how the turn-level ones are measured, as the
2
+ // settings routes report them. Re-exported by settings.ts, whose routes carry them.
3
+ import { z } from "zod";
4
+
5
+ // What each token-reduction mechanism actually saved. Input-side: both sides of the comparison come off the same
6
+ // command (raw in, emitted out), so the counterfactual is observed, not estimated — exact, per command.
7
+
8
+ // Sequential attribution (sums exactly to raw − emitted, drawable as a stacked bar); not what disabling this stage
9
+ // would save, since downstream would eat some of the same lines. Negative for `footer`, which adds cost back.
10
+ export const SavingsStageSchema = z.object({ id: z.string(), commands: z.number(), savedTokens: z.number() });
11
+ // Aggregated from historyRoot/logs/filter-stats.jsonl (one row per Bash command). Windowed on the ledger's own UTC-day
12
+ // calendar, so the reader's date range and these figures agree.
13
+ export const InputSavingsSchema = z.object({
14
+ // Epoch ms of the ledger's last command, so the card can show its age rather than implying freshness.
15
+ updatedAt: z.number().optional(),
16
+ commands: z.number(),
17
+ rawTokens: z.number(),
18
+ emittedTokens: z.number(),
19
+ savedPct: z.number(),
20
+ // Per-stage attribution, biggest first.
21
+ perCleaner: z.array(SavingsStageSchema),
22
+ // The measured control (raw vs. cleaned); the only real whole-pipeline counterfactual, not an estimate.
23
+ holdout: z.object({ cleaned: z.number(), heldOut: z.number(), measuredSavedPct: z.number().optional() }),
24
+ // Grouped by command text: worth a handler is judged by total tokens across runs, not one outlier's size.
25
+ gaps: z.array(z.object({ command: z.string(), commands: z.number(), tokens: z.number() })),
26
+ });
27
+ export type InputSavings = z.infer<typeof InputSavingsSchema>;
28
+ // One arm of a turn-level experiment; mean is per turn, since the two arms never hold the same count.
29
+ // `mean` is over samples capped at both arms' pooled 95th percentile, so one runaway conversation cannot carry an arm.
30
+ // For a yes/no reading (`openedWithListing`) it is the share of yeses, 0 to 1, and uncapped.
31
+ export const SavingsArmSchema = z.object({ turns: z.number(), mean: z.number() });
32
+ // One metric's reading of a turn-level experiment (the two arms, plus the arithmetic over them). `metric` says what
33
+ // `mean`/`deltaPct` count:
34
+ // searchCalls: searches a turn ran (the search teaching).
35
+ // openingSearches: same, narrowed to before the turn first touched a file.
36
+ // openedWithListing: whether a turn listed directories to orient itself, as a share of turns (the project map).
37
+ // callsBeforeTarget: how far a turn walked before touching a file it went on to edit.
38
+ // failedCalls: tool calls that ended in error (the field notes, whose largest section is a failure taxonomy).
39
+ // openingPrompt: tokens a turn's first request sent (cache reads plus cache writes), which is what every later call of
40
+ // the turn reads again (tool search, which moves the tool schemas out of it).
41
+ // openingWrite: tokens a follow-up turn's first request wrote to the cache instead of reading them (the stable prompt).
42
+ // Every reading is the main agent's own: a subagent's calls are counted toward the turn and read for nothing.
43
+ // Never cost: each mechanism moves one small part of a turn's work, inside the noise of the rest. The prompt's size is
44
+ // the exception that proves it: it is the part every call pays again, so it is read directly rather than through cost.
45
+ export const TurnMetricReadingSchema = z.object({
46
+ metric: z.enum(["searchCalls", "openingSearches", "openedWithListing", "callsBeforeTarget", "failedCalls", "openingPrompt", "openingWrite"]),
47
+ on: SavingsArmSchema,
48
+ off: SavingsArmSchema,
49
+ // Additional control turns to reach a fixed target resolution, not today's delta (which inherits noise and always
50
+ // promises "next week"). Absent means nothing to wait for: under `minTurns`, already published, or already resolved
51
+ // enough.
52
+ controlTurnsNeeded: z.number().optional(),
53
+ // ± percentage points at 95% (Welch); present once both arms clear `minTurns`, even when `deltaPct` is withheld —
54
+ // "smaller than ±35 points" is still a useful, true answer.
55
+ marginPct: z.number().optional(),
56
+ // Present only once the margin excludes zero — clearing `minTurns` alone isn't enough, or a wide, unresolved swing
57
+ // reads as a real number.
58
+ // deltaPct: change in the metric's mean per turn; negative is a saving.
59
+ // saved: what that delta was worth over the turns that ran with it, in the metric's own unit.
60
+ deltaPct: z.number().optional(),
61
+ saved: z.number().optional(),
62
+ });
63
+ export type TurnMetricReading = z.infer<typeof TurnMetricReadingSchema>;
64
+ // One coin flip, several readings: `metrics` is a list since splitting readings into separate entries would duplicate
65
+ // the arm assignment. Screens read `metrics[0]` as the headline, the rest as supporting lines.
66
+ export const TurnExperimentSchema = z.object({
67
+ // A head and a tail, not a plain array, so "always a headline" is a type fact, not a check every screen repeats.
68
+ // `.nonempty()` doesn't do this in zod 4 (a runtime check, still typed as a plain array).
69
+ metrics: z.tuple([TurnMetricReadingSchema], TurnMetricReadingSchema),
70
+ // Carried on the wire so "measuring…" reflects the daemon's real threshold, not a guess; shared across every
71
+ // reading, since they're the same turns.
72
+ minTurns: z.number(),
73
+ // Turn mechanisms randomize by turn; session-loaded teaching randomizes whole conversations; a once-sent treatment
74
+ // (the map) samples one turn per conversation, not an average, or its effect divides by the conversation's length.
75
+ sampleUnit: z.enum(["turns", "conversations", "opening turns"]).optional(),
76
+ // Content-addressed treatment version; the reader filters to the latest so two instruction revisions don't blur
77
+ // into one experiment.
78
+ cohort: z.string().optional(),
79
+ // The latest earlier cohort that reached an answer, with only its answered readings (a margin, with or without a
80
+ // delta), so restarting a comparison does not wipe a finding off the screen while the new one is early. `from` and
81
+ // `to` are its first and last measured turn inside the window read, epoch ms. Absent when no earlier one answered.
82
+ previous: z
83
+ .object({ from: z.number(), to: z.number(), cohort: z.string().optional(), metrics: z.array(TurnMetricReadingSchema) })
84
+ .optional(),
85
+ // Whether the treatment was taken up at all, which no reading above can tell: the share, 0 to 1, of each group's
86
+ // searches that ran iq, pooled over the turns of this cohort that recorded it. `turns` is the treated group's count;
87
+ // absent until it reaches `minTurns`. The search teaching only.
88
+ uptake: z.object({ on: z.number(), off: z.number(), turns: z.number() }).optional(),
89
+ });
90
+ export type TurnExperiment = z.infer<typeof TurnExperimentSchema>;
91
+ // What the settings row can say about the brief without opening it: whether there is one, how much of it this budget
92
+ // reaches, and whether anything is scheduled to rewrite it. Read off the file and the automation store, never stored.
93
+ export const FieldNotesStatusSchema = z.object({
94
+ // False means the automation has never run (or was never set up) — the ordinary state before the first month.
95
+ present: z.boolean(),
96
+ // Epoch ms the file was last written. Absent when there is no file.
97
+ writtenAt: z.number().optional(),
98
+ // How many ranked sections the current budget reaches, out of how many the file holds. The pair is the point: "5"
99
+ // alone cannot tell a generous budget from a short file.
100
+ ranksSent: z.number().optional(),
101
+ ranksTotal: z.number().optional(),
102
+ // What the brief costs the prompt, in characters, at the current budget.
103
+ chars: z.number().optional(),
104
+ // The monthly rewrite: absent until the owner creates it from the offered template, since an automation names the
105
+ // models it spends and nothing chooses those for them.
106
+ automation: z.enum(["missing", "enabled", "disabled"]),
107
+ // When it next runs, epoch ms; absent when there is nothing scheduled.
108
+ nextRunAt: z.number().optional(),
109
+ // Said out loud rather than shown as "no file": a brief that exists and cannot be read is a broken automation.
110
+ unreadable: z.string().optional(),
111
+ // Blocks of the file its priority table does not rank, so no limit ever sends them. Absent when there are none.
112
+ unlisted: z.array(z.string()).optional(),
113
+ });
114
+ export type FieldNotesStatus = z.infer<typeof FieldNotesStatusSchema>;
115
+ export const SavingsReportSchema = z.object({
116
+ input: InputSavingsSchema,
117
+ search: TurnExperimentSchema.optional(),
118
+ // Same absence rule as `search`: not measured, never zero.
119
+ map: TurnExperimentSchema.optional(),
120
+ notes: TurnExperimentSchema.optional(),
121
+ toolSearch: TurnExperimentSchema.optional(),
122
+ stablePrompt: TurnExperimentSchema.optional(),
123
+ coldTrim: TurnExperimentSchema.optional(),
124
+ });
125
+ export type SavingsReport = z.infer<typeof SavingsReportSchema>;
@@ -6,7 +6,7 @@ import { claudeExperimentSettings, iqSearchSettings } from "./settings-experimen
6
6
  import { CommandJudgeModeSchema, ProjectInstallModeSchema } from "../policy/safety-policy.js";
7
7
  import { ModelRoleSchema } from "../models/model-roles.js";
8
8
  import { MODEL_SETUP_ID, ModelSetupSchema } from "../models/model-setups.js";
9
- import { AdmissionPolicySchema, AdmissionRuleSchema } from "./agent.js";
9
+ import { AdmissionPolicySchema, AdmissionRuleSchema } from "./command-admission.js";
10
10
  import { KeepWarmSettingsSchema } from "./keep-warm.js";
11
11
  import { LimitHandoffSchema } from "./providers/handoff.js";
12
12
  import { SessionsPlacementSchema } from "./offload.js";
@@ -597,6 +597,13 @@ export const SandboxSettingsSchema = z.object({
597
597
  .max(10)
598
598
  .default(3)
599
599
  .describe("How many levels deep the delegation may go, since a subagent can start subagents of its own."),
600
+ // How far off a reset a spawned child's spent turn is booked to re-run by itself (classify-failure.ts); one with fallbacks
601
+ // keeps 90 minutes. 2026-10-18: was a fixed 90 minutes, which ended every child behind a five-hour window.
602
+ childRerunHorizonHours: z.number().int().min(0).max(24).default(6).describe(
603
+ "How long a subagent refused for a spent allowance waits for the provider's reset before it goes again by itself. Past it, or at 0, it stops and its parent hears where else the work can go. One spawned with fallbacks waits at most 90 minutes and then moves to them.",
604
+ ),
605
+ subagentBudget: z.boolean().default(true).describe("Start a subagent only where an account's allowance can carry it through its windows, on the account left with the most room after it. The rest wait as pending and start by themselves as running ones end or a window reopens. Off, every subagent starts at once, wherever the most room reads now."),
606
+ subagentReservePercent: z.number().int().min(0).max(50).default(10).describe("How much of each allowance window, in points of 100, subagents leave for your own conversations: a fan-out is planned against what is left past it."),
600
607
  // Width again, for a team-chat automation rather than a turn: each thread a message lands in is a conversation of
601
608
  // its own, and threads of one automation are worked on side by side up to this many (automations/scheduler.ts in
602
609
  // the daemon); one more waits, told it is queued, until a slot frees. Read per fire, so a change holds from the next
@@ -668,121 +675,8 @@ export type TimezoneState = z.infer<typeof TimezoneStateSchema>;
668
675
  // from, so a fork from an older build reads as a snapshot.
669
676
  export const BuiltinPromptTextSchema = z.object({ text: z.string(), version: z.string() });
670
677
  export type BuiltinPromptText = z.infer<typeof BuiltinPromptTextSchema>;
671
- // What each token-reduction mechanism actually saved. Input-side: both sides of the comparison come off the same
672
- // command (raw in, emitted out), so the counterfactual is observed, not estimated — exact, per command.
673
-
674
- // Sequential attribution (sums exactly to raw − emitted, drawable as a stacked bar); not what disabling this stage
675
- // would save, since downstream would eat some of the same lines. Negative for `footer`, which adds cost back.
676
- export const SavingsStageSchema = z.object({ id: z.string(), commands: z.number(), savedTokens: z.number() });
677
- // Aggregated from historyRoot/logs/filter-stats.jsonl (one row per Bash command). Windowed on the ledger's own UTC-day
678
- // calendar, so the reader's date range and these figures agree.
679
- export const InputSavingsSchema = z.object({
680
- // Epoch ms of the ledger's last command, so the card can show its age rather than implying freshness.
681
- updatedAt: z.number().optional(),
682
- commands: z.number(),
683
- rawTokens: z.number(),
684
- emittedTokens: z.number(),
685
- savedPct: z.number(),
686
- // Per-stage attribution, biggest first.
687
- perCleaner: z.array(SavingsStageSchema),
688
- // The measured control (raw vs. cleaned); the only real whole-pipeline counterfactual, not an estimate.
689
- holdout: z.object({ cleaned: z.number(), heldOut: z.number(), measuredSavedPct: z.number().optional() }),
690
- // Grouped by command text: worth a handler is judged by total tokens across runs, not one outlier's size.
691
- gaps: z.array(z.object({ command: z.string(), commands: z.number(), tokens: z.number() })),
692
- });
693
- export type InputSavings = z.infer<typeof InputSavingsSchema>;
694
- // One arm of a turn-level experiment; mean is per turn, since the two arms never hold the same count.
695
- // `mean` is over samples capped at both arms' pooled 95th percentile, so one runaway conversation cannot carry an arm.
696
- // For a yes/no reading (`openedWithListing`) it is the share of yeses, 0 to 1, and uncapped.
697
- export const SavingsArmSchema = z.object({ turns: z.number(), mean: z.number() });
698
- // One metric's reading of a turn-level experiment (the two arms, plus the arithmetic over them). `metric` says what
699
- // `mean`/`deltaPct` count:
700
- // searchCalls: searches a turn ran (the search teaching).
701
- // openingSearches: same, narrowed to before the turn first touched a file.
702
- // openedWithListing: whether a turn listed directories to orient itself, as a share of turns (the project map).
703
- // callsBeforeTarget: how far a turn walked before touching a file it went on to edit.
704
- // failedCalls: tool calls that ended in error (the field notes, whose largest section is a failure taxonomy).
705
- // openingPrompt: tokens a turn's first request sent (cache reads plus cache writes), which is what every later call of
706
- // the turn reads again (tool search, which moves the tool schemas out of it).
707
- // openingWrite: tokens a follow-up turn's first request wrote to the cache instead of reading them (the stable prompt).
708
- // Every reading is the main agent's own: a subagent's calls are counted toward the turn and read for nothing.
709
- // Never cost: each mechanism moves one small part of a turn's work, inside the noise of the rest. The prompt's size is
710
- // the exception that proves it: it is the part every call pays again, so it is read directly rather than through cost.
711
- export const TurnMetricReadingSchema = z.object({
712
- metric: z.enum(["searchCalls", "openingSearches", "openedWithListing", "callsBeforeTarget", "failedCalls", "openingPrompt", "openingWrite"]),
713
- on: SavingsArmSchema,
714
- off: SavingsArmSchema,
715
- // Additional control turns to reach a fixed target resolution, not today's delta (which inherits noise and always
716
- // promises "next week"). Absent means nothing to wait for: under `minTurns`, already published, or already resolved
717
- // enough.
718
- controlTurnsNeeded: z.number().optional(),
719
- // ± percentage points at 95% (Welch); present once both arms clear `minTurns`, even when `deltaPct` is withheld —
720
- // "smaller than ±35 points" is still a useful, true answer.
721
- marginPct: z.number().optional(),
722
- // Present only once the margin excludes zero — clearing `minTurns` alone isn't enough, or a wide, unresolved swing
723
- // reads as a real number.
724
- // deltaPct: change in the metric's mean per turn; negative is a saving.
725
- // saved: what that delta was worth over the turns that ran with it, in the metric's own unit.
726
- deltaPct: z.number().optional(),
727
- saved: z.number().optional(),
728
- });
729
- export type TurnMetricReading = z.infer<typeof TurnMetricReadingSchema>;
730
- // One coin flip, several readings: `metrics` is a list since splitting readings into separate entries would duplicate
731
- // the arm assignment. Screens read `metrics[0]` as the headline, the rest as supporting lines.
732
- export const TurnExperimentSchema = z.object({
733
- // A head and a tail, not a plain array, so "always a headline" is a type fact, not a check every screen repeats.
734
- // `.nonempty()` doesn't do this in zod 4 (a runtime check, still typed as a plain array).
735
- metrics: z.tuple([TurnMetricReadingSchema], TurnMetricReadingSchema),
736
- // Carried on the wire so "measuring…" reflects the daemon's real threshold, not a guess; shared across every
737
- // reading, since they're the same turns.
738
- minTurns: z.number(),
739
- // Turn mechanisms randomize by turn; session-loaded teaching randomizes whole conversations; a once-sent treatment
740
- // (the map) samples one turn per conversation, not an average, or its effect divides by the conversation's length.
741
- sampleUnit: z.enum(["turns", "conversations", "opening turns"]).optional(),
742
- // Content-addressed treatment version; the reader filters to the latest so two instruction revisions don't blur
743
- // into one experiment.
744
- cohort: z.string().optional(),
745
- // The latest earlier cohort that reached an answer, with only its answered readings (a margin, with or without a
746
- // delta), so restarting a comparison does not wipe a finding off the screen while the new one is early. `from` and
747
- // `to` are its first and last measured turn inside the window read, epoch ms. Absent when no earlier one answered.
748
- previous: z
749
- .object({ from: z.number(), to: z.number(), cohort: z.string().optional(), metrics: z.array(TurnMetricReadingSchema) })
750
- .optional(),
751
- });
752
- export type TurnExperiment = z.infer<typeof TurnExperimentSchema>;
753
- // What the settings row can say about the brief without opening it: whether there is one, how much of it this budget
754
- // reaches, and whether anything is scheduled to rewrite it. Read off the file and the automation store, never stored.
755
- export const FieldNotesStatusSchema = z.object({
756
- // False means the automation has never run (or was never set up) — the ordinary state before the first month.
757
- present: z.boolean(),
758
- // Epoch ms the file was last written. Absent when there is no file.
759
- writtenAt: z.number().optional(),
760
- // How many ranked sections the current budget reaches, out of how many the file holds. The pair is the point: "5"
761
- // alone cannot tell a generous budget from a short file.
762
- ranksSent: z.number().optional(),
763
- ranksTotal: z.number().optional(),
764
- // What the brief costs the prompt, in characters, at the current budget.
765
- chars: z.number().optional(),
766
- // The monthly rewrite: absent until the owner creates it from the offered template, since an automation names the
767
- // models it spends and nothing chooses those for them.
768
- automation: z.enum(["missing", "enabled", "disabled"]),
769
- // When it next runs, epoch ms; absent when there is nothing scheduled.
770
- nextRunAt: z.number().optional(),
771
- // Said out loud rather than shown as "no file": a brief that exists and cannot be read is a broken automation.
772
- unreadable: z.string().optional(),
773
- });
774
- export type FieldNotesStatus = z.infer<typeof FieldNotesStatusSchema>;
775
- export const SavingsReportSchema = z.object({
776
- input: InputSavingsSchema,
777
- search: TurnExperimentSchema.optional(),
778
- // Same absence rule as `search`: not measured, never zero.
779
- map: TurnExperimentSchema.optional(),
780
- notes: TurnExperimentSchema.optional(),
781
- toolSearch: TurnExperimentSchema.optional(),
782
- stablePrompt: TurnExperimentSchema.optional(),
783
- coldTrim: TurnExperimentSchema.optional(),
784
- });
785
- export type SavingsReport = z.infer<typeof SavingsReportSchema>;
678
+ // What each token-reduction mechanism saved, and the comparisons that measure the turn-level ones, in a file of their own.
679
+ export * from "./settings-savings.js";
786
680
 
787
681
  // ---- what a REPOSITORY declares for itself, at `<repo>/.intentic/checks.json` ----
788
682
  // Here rather than in a file of its own because the line between these shapes and the settings above is authority, not
@@ -61,6 +61,17 @@ export const PreparingUpdateSchema = z.object({
61
61
  percent: z.number().min(0).max(100).optional().describe("How far through the download it is, from 0 to 100. Absent for a step with no measure of its own."),
62
62
  });
63
63
  export type PreparingUpdate = z.infer<typeof PreparingUpdateSchema>;
64
+ // What answers (state/sandbox-build.ts RunningSandbox): the build this container runs and when its daemon started.
65
+ export const RunningSandboxSchema = z.object({
66
+ build: z
67
+ .object({
68
+ base: z.string().describe("The base image as the machine that runs it named it; empty when it said nothing."),
69
+ baseDigest: z.string().optional().describe("That base's registry digest, when the machine read one."),
70
+ overlay: z.string().optional().describe("The hash of the environment recipe built on the base. Absent on a stock image."),
71
+ })
72
+ .describe("Which build this container is: its base image and the environment built on it."),
73
+ bootedAt: z.number().describe("When the daemon answering started, in milliseconds. A container swapped in is a new boot."),
74
+ });
64
75
  export const InfoSchema = z.object({
65
76
  name: z.string().optional().describe("What this sandbox is called."),
66
77
  image: z.string().optional().describe("The image it is running."),
@@ -129,6 +140,10 @@ export const InfoSchema = z.object({
129
140
  autoUpdate: AutoUpdateSchema.optional().describe(
130
141
  "Whether and when this sandbox takes a downloaded update by itself, and what it is waiting on. Absent where it cannot: a hosted sandbox, one built from a checkout, or one older than automatic updates.",
131
142
  ),
143
+ // What answers now, for a page telling a swap it pressed from one still running; absent from a daemon older than it.
144
+ running: RunningSandboxSchema.optional().describe(
145
+ "Which build answers and when its daemon started, so a page that asked for a rebuild, an update or a rollback can tell when the new container is the one answering. Absent from a sandbox older than this field.",
146
+ ),
132
147
  });
133
148
  export type Info = z.infer<typeof InfoSchema>;
134
149
  // What the daemon could not read in its own `.intentic/` state files, and in the files on its volume that
@@ -219,6 +219,14 @@ export const SubagentVerificationSchema = z.object({
219
219
  ),
220
220
  });
221
221
  export type SubagentVerification = z.infer<typeof SubagentVerificationSchema>;
222
+ // Where the Claude runtime keeps an in-process subagent's own record: beside the session it ran in, under the runtime's
223
+ // own id for it. The daemon pairs the two while the subagent runs and writes them onto its delegation's card, so the
224
+ // subagent's whole run reads back from that record after a restart, when nothing in memory still knows where it is.
225
+ export const SubagentSdkRecordSchema = z.object({
226
+ sessionId: z.string().describe("The provider session the subagent ran in."),
227
+ agentId: z.string().describe("The runtime's own id for the subagent, which names its record beside that session."),
228
+ });
229
+ export type SubagentSdkRecord = z.infer<typeof SubagentSdkRecordSchema>;
222
230
  export const SubagentSessionSchema = z.object({
223
231
  id: z
224
232
  .string()
@@ -0,0 +1,36 @@
1
+ import { z } from "zod";
2
+
3
+ // WHAT HAS LOOKED AT A CONVERSATION'S WORK, as its card says it: what its last turn checked of its own work, and the
4
+ // latest code review it reported. Both written by a turn's settle from what the turn did, never asked of the model.
5
+ // Re-exported by agents.ts, whose summary carries them.
6
+
7
+ // What the last turn showed of its own work, read off its tool calls and never asked of the model: the record a card
8
+ // badges instead of sending the turn back to prove anything. CI checks what the owner pushes (schemas/ci.ts).
9
+ export const TurnProofSchema = z.object({
10
+ at: z.number().describe("When the turn that left this ended, in milliseconds."),
11
+ verification: z
12
+ .enum(["verified", "unproven", "failing", "no-code"])
13
+ .describe(
14
+ "Verified: a check it ran passed after its last edit to code. Failing: the last one it ran failed. Unproven: it changed code and ran nothing that checked it. No-code: it changed nothing a check could speak to.",
15
+ ),
16
+ check: z.string().optional().describe("The command that spoke, when one did, so a targeted test is never read as the whole suite."),
17
+ unviewed: z
18
+ .number()
19
+ .optional()
20
+ .describe("How many rendered files it changed (pages, components, styles) without looking at the result afterwards. Absent when none."),
21
+ });
22
+ export type TurnProof = z.infer<typeof TurnProofSchema>;
23
+ // The latest code review a conversation reported (events/review.ts), counted rather than carried: the findings stay in
24
+ // its chat, where the card that sends them to be fixed draws them. Kept until a later review replaces it, since a turn
25
+ // that reviews nothing has not undone the one before.
26
+ export const ReviewTallySchema = z.object({
27
+ at: z.number().describe("When the turn that reported it ended, in milliseconds."),
28
+ source: z.enum(["claude", "codex"]).describe("Which harness's reviewer reported it."),
29
+ findings: z.number().int().nonnegative().describe("How many findings it reported."),
30
+ open: z
31
+ .number()
32
+ .int()
33
+ .nonnegative()
34
+ .describe("How many of those no re-report has marked fixed or set aside yet. Equal to `findings` until the review is reported again with its fixes applied."),
35
+ });
36
+ export type ReviewTally = z.infer<typeof ReviewTallySchema>;
@@ -143,6 +143,38 @@ export const WorkspaceMediaTicketSchema = z.object({
143
143
  ticket: z.string().describe("Hand this to the streaming route in the query string. It buys exactly the one file it was minted for."),
144
144
  expiresAt: z.number().describe("When it stops working, in milliseconds, so a player can tell a dead ticket from a dead file."),
145
145
  });
146
+ // The long edges a picture is re-encoded at for drawing (GET /workspace/thumb's `size=e<edge>`), smallest first. A reader
147
+ // asks for the smallest one at least as long as the box the picture fills on its screen, device pixels counted, the
148
+ // way a browser picks from a srcset. Steps of about one and a half, so a pick is never much larger than it needs, and
149
+ // few enough that the pictures of a folder seen at several sizes share their renditions.
150
+ export const PICTURE_EDGES = [384, 512, 768, 1024, 1536, 2048] as const;
151
+ export type PictureEdge = (typeof PICTURE_EDGES)[number];
152
+
153
+ // The box each picture or video is drawn in, asked of a folder's worth at once: a gallery lays its rows out from every
154
+ // picture's shape before any of them has loaded, so a row never reflows under the reader as its pictures arrive.
155
+ export const WORKSPACE_DIMENSIONS_MAX = 500;
156
+ export const WorkspaceDimensionsQuerySchema = WorkspaceScopeSchema.extend({
157
+ paths: z
158
+ .array(z.string().min(1))
159
+ .min(1)
160
+ .max(WORKSPACE_DIMENSIONS_MAX)
161
+ .describe("The pictures and videos to measure, as workspace paths. Anything else, or anything unreadable, is left out of the answer."),
162
+ });
163
+ export const WorkspaceDimensionSchema = z.object({
164
+ path: z.string().describe("The path as it was asked for."),
165
+ width: z.number().describe("Width in pixels, as the picture is shown: a phone photo's or a phone video's rotation is already applied."),
166
+ height: z.number().describe("Height in pixels, as the picture is shown."),
167
+ duration: z.number().optional().describe("A video's running time in seconds, where its container says."),
168
+ });
169
+ export type WorkspaceDimension = z.infer<typeof WorkspaceDimensionSchema>;
170
+ export const WorkspaceDimensionsSchema = z.object({
171
+ items: z
172
+ .array(WorkspaceDimensionSchema)
173
+ .describe(
174
+ "One entry per path that could be measured. A path missing here is not a picture this could read, which is an answer, not an error.",
175
+ ),
176
+ });
177
+ export type WorkspaceDimensions = z.infer<typeof WorkspaceDimensionsSchema>;
146
178
  // Credential for GET /workspace/download, which the browser navigates to so its own download manager streams the archive
147
179
  // to disk. The ticket carries the whole selection, resolved when minted, so however many entries it names the URL stays
148
180
  // short.
@@ -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
+ ];
@@ -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.
@@ -72,6 +73,11 @@ const RUNTIME_DOMAINS = [
72
73
  // A standing yes written or taken back outside a need's answer: a permission card's pass, a release, a purge. They
73
74
  // live under the auth root, which no file push watches, and the Allowed list must move with the card that wrote one.
74
75
  { domain: "grants", invalidates: [["grants"]] },
76
+
77
+ // Somebody's composer draft was written, cleared or sent. The frame names no conversation and carries no words, since
78
+ // every member hears it: each window reads back its own caller's drafts (agents.drafts). The key is the editor's draft
79
+ // store's, which reads them back itself rather than through a cached query (models/conversations/drafts/).
80
+ { domain: "drafts", invalidates: [["drafts"]] },
75
81
  ] as const satisfies readonly RuntimeDomainBinding[];
76
82
 
77
83
  export const RUNTIME_DOMAIN_BINDINGS: readonly RuntimeDomainBinding[] = RUNTIME_DOMAINS;
@@ -0,0 +1,95 @@
1
+ import { DEV_SANDBOX_IMAGE } from "../policy/overlay-lint.js";
2
+ import { buildParity, builtFromCheckout, rebuildPending, type RunningSandbox, type SandboxBuild, sameBuild, swapVerdict } from "./sandbox-build.js";
3
+
4
+ // Every "which build" question is one of these, asked of two SandboxBuild records; a surface that compares fields of its
5
+ // own choosing is how "pending rebuild" outlived a rebuild and a runner read outdated for good (2026-10).
6
+
7
+ const stable = "ghcr.io/intentic/sandbox:stable";
8
+ const digest = (byte: string): string => `sha256:${byte.repeat(64)}`;
9
+
10
+ test("a rebuild is pending exactly when the overlay wanted is not the one running", () => {
11
+ expect(rebuildPending("h1", "h1")).toBe(false);
12
+ expect(rebuildPending("h2", "h1")).toBe(true);
13
+ // A stock container wanting an overlay waits for it; one wanting none waits for nothing, whatever it runs.
14
+ expect(rebuildPending("h1", undefined)).toBe(true);
15
+ expect(rebuildPending(undefined, undefined)).toBe(false);
16
+ expect(rebuildPending(undefined, "h1")).toBe(false);
17
+ });
18
+
19
+ test("a runner on the parent's base and overlay is current, and either moving is outdated", () => {
20
+ const parent: SandboxBuild = { base: stable, overlay: "abc123" };
21
+ expect(buildParity(parent, { ...parent })).toBe("current");
22
+ expect(buildParity(parent, { ...parent, overlay: "def456" })).toBe("outdated");
23
+ expect(buildParity(parent, { ...parent, base: "ghcr.io/intentic/sandbox:2.2.0" })).toBe("outdated");
24
+ });
25
+
26
+ test("an overlay on one side only is a difference; neither side having one is not", () => {
27
+ expect(buildParity({ base: stable }, { base: stable })).toBe("current");
28
+ expect(buildParity({ base: stable, overlay: "abc" }, { base: stable })).toBe("outdated");
29
+ expect(buildParity({ base: stable }, { base: stable, overlay: "abc" })).toBe("outdated");
30
+ });
31
+
32
+ // One tag is one name for whatever the registry held when each machine pulled it; the digest is the build.
33
+ test("the base is compared by digest when both sides read one, and by its reference otherwise", () => {
34
+ expect(buildParity({ base: stable, baseDigest: digest("a") }, { base: stable, baseDigest: digest("b") })).toBe("outdated");
35
+ expect(buildParity({ base: stable, baseDigest: digest("a") }, { base: "ghcr.io/intentic/sandbox:beta", baseDigest: digest("a") })).toBe("current");
36
+ expect(buildParity({ base: stable, baseDigest: digest("a") }, { base: stable })).toBe("current");
37
+ expect(buildParity({ base: stable, baseDigest: digest("a") }, { base: "ghcr.io/intentic/sandbox:beta" })).toBe("outdated");
38
+ });
39
+
40
+ // Each machine's `intentic-sandbox:dev` is whatever its checkout held, so the name agreeing proves nothing, and an update
41
+ // cannot bring it level: `ic` refuses to move a checkout build onto the published image (recreate.rs).
42
+ test("nothing to compare, or a build from a checkout on either side, reads as unknown rather than as a warning", () => {
43
+ const parent: SandboxBuild = { base: stable, overlay: "abc" };
44
+ expect(buildParity(parent, undefined)).toBe("unknown");
45
+ expect(buildParity(parent, { base: "" })).toBe("unknown");
46
+ expect(buildParity({ base: "" }, parent)).toBe("unknown");
47
+ expect(buildParity({ base: DEV_SANDBOX_IMAGE, overlay: "abc" }, { base: DEV_SANDBOX_IMAGE, overlay: "abc" })).toBe("unknown");
48
+ expect(buildParity(parent, { base: DEV_SANDBOX_IMAGE, overlay: "abc" })).toBe("unknown");
49
+ });
50
+
51
+ // A rollback pin is a local tag too, and a rolled-back sandbox rejoins its channel by updating, not by a checkout.
52
+ test("only the dogfood base is a build from a checkout", () => {
53
+ expect(builtFromCheckout({ base: DEV_SANDBOX_IMAGE })).toBe(true);
54
+ expect(builtFromCheckout({ base: stable })).toBe(false);
55
+ expect(builtFromCheckout({ base: "intentic-sandbox-rollback-demo:f6e917ce9b90" })).toBe(false);
56
+ expect(builtFromCheckout({ base: "" })).toBe(false);
57
+ });
58
+
59
+ // A swap is told landed by what answers, never by the version: a checkout build is 0.0.0 before and after, and an update
60
+ // of one followed by "the version moved" waited out its deadline and said the sandbox never came back (2026-10).
61
+ const running = (build: SandboxBuild, bootedAt: number): RunningSandbox => ({ build, bootedAt });
62
+
63
+ test("two builds are the same only when something can tell, and differ the moment the overlay or digest does", () => {
64
+ expect(sameBuild({ base: stable, baseDigest: digest("a") }, { base: stable, baseDigest: digest("a") })).toBe(true);
65
+ expect(sameBuild({ base: stable, baseDigest: digest("a") }, { base: stable, baseDigest: digest("b") })).toBe(false);
66
+ expect(sameBuild({ base: stable, overlay: "h1" }, { base: stable, overlay: "h2" })).toBe(false);
67
+ expect(sameBuild({ base: stable }, { base: "ghcr.io/intentic/sandbox:beta" })).toBe(false);
68
+ expect(sameBuild({ base: stable }, { base: stable })).toBeUndefined();
69
+ expect(sameBuild({ base: DEV_SANDBOX_IMAGE }, { base: DEV_SANDBOX_IMAGE })).toBeUndefined();
70
+ });
71
+
72
+ test("an update of a checkout build lands on the new boot, though every version reads 0.0.0", () => {
73
+ const from = running({ base: DEV_SANDBOX_IMAGE }, 1000);
74
+ expect(swapVerdict({ from }, from)).toBe("waiting");
75
+ expect(swapVerdict({ from }, running({ base: DEV_SANDBOX_IMAGE }, 2000))).toBe("landed");
76
+ });
77
+
78
+ test("an update of a release lands when the digest moves, and a new boot on the old digest came back unmoved", () => {
79
+ const from = running({ base: stable, baseDigest: digest("a") }, 1000);
80
+ expect(swapVerdict({ from }, running({ base: stable, baseDigest: digest("b") }, 2000))).toBe("landed");
81
+ expect(swapVerdict({ from }, running({ base: stable, baseDigest: digest("a") }, 2000))).toBe("unmoved");
82
+ expect(swapVerdict({ from }, from)).toBe("waiting");
83
+ // A rollback names another tag: moved, digest or not.
84
+ expect(swapVerdict({ from: running({ base: stable }, 1000) }, running({ base: "ghcr.io/intentic/sandbox:0.9.0" }, 1000))).toBe("landed");
85
+ });
86
+
87
+ test("a rebuild lands on its overlay, and a new boot on any other overlay came back without it", () => {
88
+ const from = running({ base: stable, overlay: "old" }, 1000);
89
+ expect(swapVerdict({ from, overlay: "new" }, running({ base: stable, overlay: "new" }, 2000))).toBe("landed");
90
+ expect(swapVerdict({ from, overlay: "new" }, running({ base: stable, overlay: "old" }, 2000))).toBe("unmoved");
91
+ expect(swapVerdict({ from, overlay: "new" }, from)).toBe("waiting");
92
+ // Pressed with nothing read: only the overlay can say.
93
+ expect(swapVerdict({ from: undefined, overlay: "new" }, running({ base: stable, overlay: "new" }, 2000))).toBe("landed");
94
+ expect(swapVerdict({ from: undefined }, running({ base: stable }, 2000))).toBe("waiting");
95
+ });