@intentic/sandbox-contract 1.232.0 → 1.233.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 (500) hide show
  1. package/README.md +7 -2
  2. package/dist/agent-catalog.d.ts +2 -1
  3. package/dist/agent-catalog.d.ts.map +1 -1
  4. package/dist/agent-catalog.js +1 -1
  5. package/dist/agent-catalog.js.map +1 -1
  6. package/dist/chores/chores.d.ts +1 -1
  7. package/dist/chores/chores.d.ts.map +1 -1
  8. package/dist/chores/probes.d.ts +1 -1
  9. package/dist/chores/probes.d.ts.map +1 -1
  10. package/dist/chores/stack.d.ts.map +1 -1
  11. package/dist/chores/stack.js +2 -1
  12. package/dist/chores/stack.js.map +1 -1
  13. package/dist/chores/verdict.d.ts +1 -1
  14. package/dist/chores/verdict.d.ts.map +1 -1
  15. package/dist/command-classes.d.ts +14 -0
  16. package/dist/command-classes.d.ts.map +1 -0
  17. package/dist/command-classes.js +168 -0
  18. package/dist/command-classes.js.map +1 -0
  19. package/dist/contracts/activity.contract.js +1 -1
  20. package/dist/contracts/activity.contract.js.map +1 -1
  21. package/dist/contracts/agent.contract.d.ts +40 -2
  22. package/dist/contracts/agent.contract.d.ts.map +1 -1
  23. package/dist/contracts/agent.contract.js +4 -1
  24. package/dist/contracts/agent.contract.js.map +1 -1
  25. package/dist/contracts/agents.contract.d.ts +24 -0
  26. package/dist/contracts/agents.contract.d.ts.map +1 -1
  27. package/dist/contracts/agents.contract.js +5 -1
  28. package/dist/contracts/agents.contract.js.map +1 -1
  29. package/dist/contracts/automations.contract.js +2 -1
  30. package/dist/contracts/automations.contract.js.map +1 -1
  31. package/dist/contracts/capabilities.contract.d.ts +63 -0
  32. package/dist/contracts/capabilities.contract.d.ts.map +1 -1
  33. package/dist/contracts/capabilities.contract.js +3 -1
  34. package/dist/contracts/capabilities.contract.js.map +1 -1
  35. package/dist/contracts/chores.contract.d.ts.map +1 -1
  36. package/dist/contracts/chores.contract.js +2 -1
  37. package/dist/contracts/chores.contract.js.map +1 -1
  38. package/dist/contracts/ci.contract.js +2 -1
  39. package/dist/contracts/ci.contract.js.map +1 -1
  40. package/dist/contracts/claude.contract.js +2 -1
  41. package/dist/contracts/claude.contract.js.map +1 -1
  42. package/dist/contracts/cursor.contract.js +2 -1
  43. package/dist/contracts/cursor.contract.js.map +1 -1
  44. package/dist/contracts/drafts.contract.d.ts.map +1 -1
  45. package/dist/contracts/drafts.contract.js +2 -1
  46. package/dist/contracts/drafts.contract.js.map +1 -1
  47. package/dist/contracts/endpoints.contract.d.ts.map +1 -1
  48. package/dist/contracts/endpoints.contract.js +2 -1
  49. package/dist/contracts/endpoints.contract.js.map +1 -1
  50. package/dist/contracts/exit.contract.d.ts.map +1 -1
  51. package/dist/contracts/exit.contract.js +2 -1
  52. package/dist/contracts/exit.contract.js.map +1 -1
  53. package/dist/contracts/extensions.contract.d.ts +42 -0
  54. package/dist/contracts/extensions.contract.d.ts.map +1 -1
  55. package/dist/contracts/extensions.contract.js +4 -1
  56. package/dist/contracts/extensions.contract.js.map +1 -1
  57. package/dist/contracts/git.contract.d.ts.map +1 -1
  58. package/dist/contracts/git.contract.js +4 -1
  59. package/dist/contracts/git.contract.js.map +1 -1
  60. package/dist/contracts/grok.contract.d.ts.map +1 -1
  61. package/dist/contracts/grok.contract.js +2 -1
  62. package/dist/contracts/grok.contract.js.map +1 -1
  63. package/dist/contracts/history.contract.d.ts.map +1 -1
  64. package/dist/contracts/history.contract.js +2 -1
  65. package/dist/contracts/history.contract.js.map +1 -1
  66. package/dist/contracts/host.contract.d.ts +7 -0
  67. package/dist/contracts/host.contract.d.ts.map +1 -1
  68. package/dist/contracts/host.contract.js +4 -1
  69. package/dist/contracts/host.contract.js.map +1 -1
  70. package/dist/contracts/intentic.contract.d.ts.map +1 -1
  71. package/dist/contracts/intentic.contract.js +2 -1
  72. package/dist/contracts/intentic.contract.js.map +1 -1
  73. package/dist/contracts/inventory.contract.js +1 -1
  74. package/dist/contracts/inventory.contract.js.map +1 -1
  75. package/dist/contracts/logs.contract.d.ts.map +1 -1
  76. package/dist/contracts/logs.contract.js +1 -1
  77. package/dist/contracts/logs.contract.js.map +1 -1
  78. package/dist/contracts/loops.contract.js +2 -1
  79. package/dist/contracts/loops.contract.js.map +1 -1
  80. package/dist/contracts/panels.contract.d.ts.map +1 -1
  81. package/dist/contracts/panels.contract.js +2 -1
  82. package/dist/contracts/panels.contract.js.map +1 -1
  83. package/dist/contracts/personas.contract.js +2 -1
  84. package/dist/contracts/personas.contract.js.map +1 -1
  85. package/dist/contracts/ports.contract.d.ts.map +1 -1
  86. package/dist/contracts/ports.contract.js +2 -1
  87. package/dist/contracts/ports.contract.js.map +1 -1
  88. package/dist/contracts/prepush.contract.d.ts.map +1 -1
  89. package/dist/contracts/prepush.contract.js +2 -1
  90. package/dist/contracts/prepush.contract.js.map +1 -1
  91. package/dist/contracts/providers.contract.d.ts.map +1 -1
  92. package/dist/contracts/providers.contract.js +2 -1
  93. package/dist/contracts/providers.contract.js.map +1 -1
  94. package/dist/contracts/public.contract.d.ts.map +1 -1
  95. package/dist/contracts/public.contract.js +2 -1
  96. package/dist/contracts/public.contract.js.map +1 -1
  97. package/dist/contracts/push.contract.d.ts.map +1 -1
  98. package/dist/contracts/push.contract.js +2 -1
  99. package/dist/contracts/push.contract.js.map +1 -1
  100. package/dist/contracts/runner.contract.d.ts +45 -2
  101. package/dist/contracts/runner.contract.d.ts.map +1 -1
  102. package/dist/contracts/runner.contract.js +10 -2
  103. package/dist/contracts/runner.contract.js.map +1 -1
  104. package/dist/contracts/secrets.contract.d.ts.map +1 -1
  105. package/dist/contracts/secrets.contract.js +2 -1
  106. package/dist/contracts/secrets.contract.js.map +1 -1
  107. package/dist/contracts/sessions.contract.js +1 -1
  108. package/dist/contracts/sessions.contract.js.map +1 -1
  109. package/dist/contracts/settings.contract.d.ts +20 -0
  110. package/dist/contracts/settings.contract.d.ts.map +1 -1
  111. package/dist/contracts/settings.contract.js +3 -1
  112. package/dist/contracts/settings.contract.js.map +1 -1
  113. package/dist/contracts/share.contract.d.ts.map +1 -1
  114. package/dist/contracts/share.contract.js +2 -1
  115. package/dist/contracts/share.contract.js.map +1 -1
  116. package/dist/contracts/skills.contract.d.ts.map +1 -1
  117. package/dist/contracts/skills.contract.js +2 -1
  118. package/dist/contracts/skills.contract.js.map +1 -1
  119. package/dist/contracts/system.contract.d.ts +31 -16
  120. package/dist/contracts/system.contract.d.ts.map +1 -1
  121. package/dist/contracts/system.contract.js +6 -1
  122. package/dist/contracts/system.contract.js.map +1 -1
  123. package/dist/contracts/translator.contract.d.ts.map +1 -1
  124. package/dist/contracts/translator.contract.js +4 -1
  125. package/dist/contracts/translator.contract.js.map +1 -1
  126. package/dist/contracts/usage.contract.js +1 -1
  127. package/dist/contracts/usage.contract.js.map +1 -1
  128. package/dist/contracts/vpn.contract.d.ts.map +1 -1
  129. package/dist/contracts/vpn.contract.js +2 -1
  130. package/dist/contracts/vpn.contract.js.map +1 -1
  131. package/dist/contracts/webext.contract.d.ts +45 -0
  132. package/dist/contracts/webext.contract.d.ts.map +1 -0
  133. package/dist/contracts/webext.contract.js +12 -0
  134. package/dist/contracts/webext.contract.js.map +1 -0
  135. package/dist/contracts/workflows.contract.js +2 -1
  136. package/dist/contracts/workflows.contract.js.map +1 -1
  137. package/dist/contracts/workspace.contract.d.ts +2 -2
  138. package/dist/contracts/workspace.contract.d.ts.map +1 -1
  139. package/dist/contracts/workspace.contract.js +7 -1
  140. package/dist/contracts/workspace.contract.js.map +1 -1
  141. package/dist/definition-action.d.ts +7 -0
  142. package/dist/definition-action.d.ts.map +1 -0
  143. package/dist/definition-action.js +3 -0
  144. package/dist/definition-action.js.map +1 -0
  145. package/dist/definition.d.ts +124 -21
  146. package/dist/definition.d.ts.map +1 -1
  147. package/dist/definition.js +29 -7
  148. package/dist/definition.js.map +1 -1
  149. package/dist/events.d.ts +101 -0
  150. package/dist/events.d.ts.map +1 -1
  151. package/dist/events.js +25 -1
  152. package/dist/events.js.map +1 -1
  153. package/dist/fast-tier.d.ts +1 -1
  154. package/dist/fast-tier.d.ts.map +1 -1
  155. package/dist/history-state.d.ts.map +1 -1
  156. package/dist/history-state.js +1 -0
  157. package/dist/history-state.js.map +1 -1
  158. package/dist/index.d.ts +355 -103
  159. package/dist/index.d.ts.map +1 -1
  160. package/dist/index.js +51 -1
  161. package/dist/index.js.map +1 -1
  162. package/dist/listener-protocol.js +1 -1
  163. package/dist/listener-protocol.js.map +1 -1
  164. package/dist/quick-model.d.ts +1 -1
  165. package/dist/quick-model.d.ts.map +1 -1
  166. package/dist/runner-protocol.d.ts +18 -0
  167. package/dist/runner-protocol.d.ts.map +1 -1
  168. package/dist/runner-protocol.js +8 -4
  169. package/dist/runner-protocol.js.map +1 -1
  170. package/dist/schemas/activity.d.ts +112 -0
  171. package/dist/schemas/activity.d.ts.map +1 -0
  172. package/dist/schemas/activity.js +70 -0
  173. package/dist/schemas/activity.js.map +1 -0
  174. package/dist/schemas/agent.d.ts +189 -0
  175. package/dist/schemas/agent.d.ts.map +1 -0
  176. package/dist/schemas/agent.js +170 -0
  177. package/dist/schemas/agent.js.map +1 -0
  178. package/dist/schemas/agents.d.ts +690 -0
  179. package/dist/schemas/agents.d.ts.map +1 -0
  180. package/dist/schemas/agents.js +314 -0
  181. package/dist/schemas/agents.js.map +1 -0
  182. package/dist/schemas/automations.d.ts +736 -0
  183. package/dist/schemas/automations.d.ts.map +1 -0
  184. package/dist/schemas/automations.js +218 -0
  185. package/dist/schemas/automations.js.map +1 -0
  186. package/dist/schemas/capabilities.d.ts +753 -0
  187. package/dist/schemas/capabilities.d.ts.map +1 -0
  188. package/dist/schemas/capabilities.js +269 -0
  189. package/dist/schemas/capabilities.js.map +1 -0
  190. package/dist/schemas/ci.d.ts +179 -0
  191. package/dist/schemas/ci.d.ts.map +1 -0
  192. package/dist/schemas/ci.js +99 -0
  193. package/dist/schemas/ci.js.map +1 -0
  194. package/dist/schemas/claude-gate.d.ts +13 -0
  195. package/dist/schemas/claude-gate.d.ts.map +1 -0
  196. package/dist/schemas/claude-gate.js +8 -0
  197. package/dist/schemas/claude-gate.js.map +1 -0
  198. package/dist/schemas/codebase-health.d.ts +56 -0
  199. package/dist/schemas/codebase-health.d.ts.map +1 -0
  200. package/dist/schemas/codebase-health.js +43 -0
  201. package/dist/schemas/codebase-health.js.map +1 -0
  202. package/dist/schemas/computers.d.ts +386 -0
  203. package/dist/schemas/computers.d.ts.map +1 -0
  204. package/dist/schemas/computers.js +107 -0
  205. package/dist/schemas/computers.js.map +1 -0
  206. package/dist/schemas/drafts.d.ts +84 -0
  207. package/dist/schemas/drafts.d.ts.map +1 -0
  208. package/dist/schemas/drafts.js +44 -0
  209. package/dist/schemas/drafts.js.map +1 -0
  210. package/dist/schemas/environment.d.ts +349 -0
  211. package/dist/schemas/environment.d.ts.map +1 -0
  212. package/dist/schemas/environment.js +111 -0
  213. package/dist/schemas/environment.js.map +1 -0
  214. package/dist/schemas/exit.d.ts +151 -0
  215. package/dist/schemas/exit.d.ts.map +1 -0
  216. package/dist/schemas/exit.js +115 -0
  217. package/dist/schemas/exit.js.map +1 -0
  218. package/dist/schemas/extension-updates.d.ts +1014 -0
  219. package/dist/schemas/extension-updates.d.ts.map +1 -0
  220. package/dist/schemas/extension-updates.js +197 -0
  221. package/dist/schemas/extension-updates.js.map +1 -0
  222. package/dist/schemas/fast-mode.d.ts +8 -0
  223. package/dist/schemas/fast-mode.d.ts.map +1 -0
  224. package/dist/schemas/fast-mode.js +3 -0
  225. package/dist/schemas/fast-mode.js.map +1 -0
  226. package/dist/schemas/git-history.d.ts +238 -0
  227. package/dist/schemas/git-history.d.ts.map +1 -0
  228. package/dist/schemas/git-history.js +152 -0
  229. package/dist/schemas/git-history.js.map +1 -0
  230. package/dist/schemas/git.d.ts +471 -0
  231. package/dist/schemas/git.d.ts.map +1 -0
  232. package/dist/schemas/git.js +204 -0
  233. package/dist/schemas/git.js.map +1 -0
  234. package/dist/schemas/history.d.ts +100 -0
  235. package/dist/schemas/history.d.ts.map +1 -0
  236. package/dist/schemas/history.js +54 -0
  237. package/dist/schemas/history.js.map +1 -0
  238. package/dist/schemas/hosts.d.ts +41 -0
  239. package/dist/schemas/hosts.d.ts.map +1 -0
  240. package/dist/schemas/hosts.js +18 -0
  241. package/dist/schemas/hosts.js.map +1 -0
  242. package/dist/schemas/intentic.d.ts +5 -0
  243. package/dist/schemas/intentic.d.ts.map +1 -0
  244. package/dist/schemas/intentic.js +3 -0
  245. package/dist/schemas/intentic.js.map +1 -0
  246. package/dist/schemas/internal.d.ts +8 -0
  247. package/dist/schemas/internal.d.ts.map +1 -0
  248. package/dist/schemas/internal.js +12 -0
  249. package/dist/schemas/internal.js.map +1 -0
  250. package/dist/schemas/inventory.d.ts +171 -0
  251. package/dist/schemas/inventory.d.ts.map +1 -0
  252. package/dist/schemas/inventory.js +51 -0
  253. package/dist/schemas/inventory.js.map +1 -0
  254. package/dist/schemas/logs.d.ts +67 -0
  255. package/dist/schemas/logs.d.ts.map +1 -0
  256. package/dist/schemas/logs.js +54 -0
  257. package/dist/schemas/logs.js.map +1 -0
  258. package/dist/schemas/loops.d.ts +415 -0
  259. package/dist/schemas/loops.d.ts.map +1 -0
  260. package/dist/schemas/loops.js +188 -0
  261. package/dist/schemas/loops.js.map +1 -0
  262. package/dist/schemas/maintenance.d.ts +557 -0
  263. package/dist/schemas/maintenance.d.ts.map +1 -0
  264. package/dist/schemas/maintenance.js +201 -0
  265. package/dist/schemas/maintenance.js.map +1 -0
  266. package/dist/schemas/marketplace.d.ts +64 -0
  267. package/dist/schemas/marketplace.d.ts.map +1 -0
  268. package/dist/schemas/marketplace.js +17 -0
  269. package/dist/schemas/marketplace.js.map +1 -0
  270. package/dist/schemas/panels.d.ts +61 -0
  271. package/dist/schemas/panels.d.ts.map +1 -0
  272. package/dist/schemas/panels.js +51 -0
  273. package/dist/schemas/panels.js.map +1 -0
  274. package/dist/schemas/personas.d.ts +122 -0
  275. package/dist/schemas/personas.d.ts.map +1 -0
  276. package/dist/schemas/personas.js +102 -0
  277. package/dist/schemas/personas.js.map +1 -0
  278. package/dist/schemas/plan-limits.d.ts +172 -0
  279. package/dist/schemas/plan-limits.d.ts.map +1 -0
  280. package/dist/schemas/plan-limits.js +126 -0
  281. package/dist/schemas/plan-limits.js.map +1 -0
  282. package/dist/schemas/ports.d.ts +71 -0
  283. package/dist/schemas/ports.d.ts.map +1 -0
  284. package/dist/schemas/ports.js +42 -0
  285. package/dist/schemas/ports.js.map +1 -0
  286. package/dist/schemas/provider-oauth.d.ts +128 -0
  287. package/dist/schemas/provider-oauth.d.ts.map +1 -0
  288. package/dist/schemas/provider-oauth.js +91 -0
  289. package/dist/schemas/provider-oauth.js.map +1 -0
  290. package/dist/schemas/provider-subscriptions.d.ts +9 -0
  291. package/dist/schemas/provider-subscriptions.d.ts.map +1 -0
  292. package/dist/schemas/provider-subscriptions.js +3 -0
  293. package/dist/schemas/provider-subscriptions.js.map +1 -0
  294. package/dist/schemas/public.d.ts +32 -0
  295. package/dist/schemas/public.d.ts.map +1 -0
  296. package/dist/schemas/public.js +29 -0
  297. package/dist/schemas/public.js.map +1 -0
  298. package/dist/schemas/push.d.ts +55 -0
  299. package/dist/schemas/push.d.ts.map +1 -0
  300. package/dist/schemas/push.js +60 -0
  301. package/dist/schemas/push.js.map +1 -0
  302. package/dist/schemas/secrets.d.ts +86 -0
  303. package/dist/schemas/secrets.d.ts.map +1 -0
  304. package/dist/schemas/secrets.js +51 -0
  305. package/dist/schemas/secrets.js.map +1 -0
  306. package/dist/schemas/sessions.d.ts +32 -0
  307. package/dist/schemas/sessions.d.ts.map +1 -0
  308. package/dist/schemas/sessions.js +11 -0
  309. package/dist/schemas/sessions.js.map +1 -0
  310. package/dist/schemas/settings.d.ts +548 -0
  311. package/dist/schemas/settings.d.ts.map +1 -0
  312. package/dist/schemas/settings.js +259 -0
  313. package/dist/schemas/settings.js.map +1 -0
  314. package/dist/schemas/share.d.ts +49 -0
  315. package/dist/schemas/share.d.ts.map +1 -0
  316. package/dist/schemas/share.js +26 -0
  317. package/dist/schemas/share.js.map +1 -0
  318. package/dist/schemas/shared.d.ts +22 -0
  319. package/dist/schemas/shared.d.ts.map +1 -0
  320. package/dist/schemas/shared.js +16 -0
  321. package/dist/schemas/shared.js.map +1 -0
  322. package/dist/schemas/system.d.ts +86 -0
  323. package/dist/schemas/system.d.ts.map +1 -0
  324. package/dist/schemas/system.js +64 -0
  325. package/dist/schemas/system.js.map +1 -0
  326. package/dist/schemas/terminal.d.ts +230 -0
  327. package/dist/schemas/terminal.d.ts.map +1 -0
  328. package/dist/schemas/terminal.js +133 -0
  329. package/dist/schemas/terminal.js.map +1 -0
  330. package/dist/schemas/usage.d.ts +113 -0
  331. package/dist/schemas/usage.d.ts.map +1 -0
  332. package/dist/schemas/usage.js +91 -0
  333. package/dist/schemas/usage.js.map +1 -0
  334. package/dist/schemas/vpn.d.ts +229 -0
  335. package/dist/schemas/vpn.d.ts.map +1 -0
  336. package/dist/schemas/vpn.js +115 -0
  337. package/dist/schemas/vpn.js.map +1 -0
  338. package/dist/schemas/webext.d.ts +98 -0
  339. package/dist/schemas/webext.d.ts.map +1 -0
  340. package/dist/schemas/webext.js +36 -0
  341. package/dist/schemas/webext.js.map +1 -0
  342. package/dist/schemas/workflows.d.ts +881 -0
  343. package/dist/schemas/workflows.d.ts.map +1 -0
  344. package/dist/schemas/workflows.js +164 -0
  345. package/dist/schemas/workflows.js.map +1 -0
  346. package/dist/schemas/workspace-repos.d.ts +143 -0
  347. package/dist/schemas/workspace-repos.d.ts.map +1 -0
  348. package/dist/schemas/workspace-repos.js +87 -0
  349. package/dist/schemas/workspace-repos.js.map +1 -0
  350. package/dist/schemas/workspace-search.d.ts +170 -0
  351. package/dist/schemas/workspace-search.d.ts.map +1 -0
  352. package/dist/schemas/workspace-search.js +85 -0
  353. package/dist/schemas/workspace-search.js.map +1 -0
  354. package/dist/schemas/workspace-setup.d.ts +48 -0
  355. package/dist/schemas/workspace-setup.d.ts.map +1 -0
  356. package/dist/schemas/workspace-setup.js +26 -0
  357. package/dist/schemas/workspace-setup.js.map +1 -0
  358. package/dist/schemas/workspace-tree.d.ts +120 -0
  359. package/dist/schemas/workspace-tree.d.ts.map +1 -0
  360. package/dist/schemas/workspace-tree.js +111 -0
  361. package/dist/schemas/workspace-tree.js.map +1 -0
  362. package/dist/webext-links.d.ts +13 -0
  363. package/dist/webext-links.d.ts.map +1 -0
  364. package/dist/webext-links.js +24 -0
  365. package/dist/webext-links.js.map +1 -0
  366. package/dist/webext-protocol.d.ts +8 -0
  367. package/dist/webext-protocol.d.ts.map +1 -0
  368. package/dist/webext-protocol.js +7 -0
  369. package/dist/webext-protocol.js.map +1 -0
  370. package/dist/workflow-faults.d.ts +1 -1
  371. package/dist/workflow-faults.d.ts.map +1 -1
  372. package/dist/workspace-state.d.ts +2 -2
  373. package/dist/workspace-state.d.ts.map +1 -1
  374. package/dist/workspace-state.js +2 -2
  375. package/dist/workspace-state.js.map +1 -1
  376. package/package.json +15 -4
  377. package/src/agent-catalog.test.ts +1 -1
  378. package/src/agent-catalog.ts +4 -11
  379. package/src/chores/chores.ts +1 -1
  380. package/src/chores/probes.ts +1 -1
  381. package/src/chores/stack.test.ts +19 -0
  382. package/src/chores/stack.ts +19 -3
  383. package/src/chores/verdict.test.ts +11 -1
  384. package/src/chores/verdict.ts +1 -1
  385. package/src/command-classes.test.ts +378 -0
  386. package/src/command-classes.ts +378 -0
  387. package/src/contracts/activity.contract.ts +1 -1
  388. package/src/contracts/agent.contract.ts +4 -13
  389. package/src/contracts/agents.contract.ts +6 -6
  390. package/src/contracts/automations.contract.ts +2 -2
  391. package/src/contracts/capabilities.contract.ts +3 -4
  392. package/src/contracts/chores.contract.ts +2 -1
  393. package/src/contracts/ci.contract.ts +2 -2
  394. package/src/contracts/claude.contract.ts +2 -2
  395. package/src/contracts/cursor.contract.ts +2 -2
  396. package/src/contracts/drafts.contract.ts +2 -1
  397. package/src/contracts/endpoints.contract.ts +2 -1
  398. package/src/contracts/exit.contract.ts +2 -1
  399. package/src/contracts/extensions.contract.ts +5 -5
  400. package/src/contracts/git.contract.ts +19 -18
  401. package/src/contracts/grok.contract.ts +2 -1
  402. package/src/contracts/history.contract.ts +2 -1
  403. package/src/contracts/host.contract.ts +4 -1
  404. package/src/contracts/intentic.contract.ts +2 -1
  405. package/src/contracts/inventory.contract.ts +1 -1
  406. package/src/contracts/logs.contract.ts +7 -1
  407. package/src/contracts/loops.contract.ts +2 -2
  408. package/src/contracts/panels.contract.ts +2 -1
  409. package/src/contracts/personas.contract.ts +3 -3
  410. package/src/contracts/ports.contract.ts +3 -2
  411. package/src/contracts/prepush.contract.ts +2 -1
  412. package/src/contracts/providers.contract.ts +2 -1
  413. package/src/contracts/public.contract.ts +3 -2
  414. package/src/contracts/push.contract.ts +2 -1
  415. package/src/contracts/runner.contract.ts +18 -2
  416. package/src/contracts/secrets.contract.ts +2 -1
  417. package/src/contracts/sessions.contract.ts +1 -1
  418. package/src/contracts/settings.contract.ts +3 -9
  419. package/src/contracts/share.contract.ts +3 -2
  420. package/src/contracts/skills.contract.ts +2 -1
  421. package/src/contracts/system.contract.ts +6 -9
  422. package/src/contracts/translator.contract.ts +4 -1
  423. package/src/contracts/usage.contract.ts +1 -1
  424. package/src/contracts/vpn.contract.ts +2 -8
  425. package/src/contracts/webext.contract.ts +37 -0
  426. package/src/contracts/workflows.contract.ts +2 -2
  427. package/src/contracts/workspace.contract.ts +10 -12
  428. package/src/conversation-ids.test.ts +1 -1
  429. package/src/definition-action.ts +8 -0
  430. package/src/definition.ts +74 -10
  431. package/src/events.ts +84 -22
  432. package/src/fast-tier.ts +1 -1
  433. package/src/history-state.ts +5 -0
  434. package/src/host-protocol.ts +1 -1
  435. package/src/hostnames.test.ts +2 -2
  436. package/src/index.ts +60 -1
  437. package/src/listener-protocol.ts +1 -1
  438. package/src/quick-model.ts +1 -1
  439. package/src/runner-protocol.ts +35 -5
  440. package/src/schemas/activity.ts +123 -0
  441. package/src/schemas/agent.ts +409 -0
  442. package/src/schemas/agents.ts +802 -0
  443. package/src/schemas/automations.ts +510 -0
  444. package/src/schemas/capabilities.ts +729 -0
  445. package/src/schemas/ci.ts +235 -0
  446. package/src/schemas/claude-gate.ts +13 -0
  447. package/src/schemas/codebase-health.ts +64 -0
  448. package/src/schemas/computers.ts +287 -0
  449. package/src/schemas/drafts.ts +108 -0
  450. package/src/schemas/environment.ts +276 -0
  451. package/src/schemas/exit.ts +222 -0
  452. package/src/schemas/extension-updates.ts +322 -0
  453. package/src/schemas/fast-mode.ts +8 -0
  454. package/src/schemas/git-history.ts +265 -0
  455. package/src/schemas/git.ts +430 -0
  456. package/src/schemas/history.ts +112 -0
  457. package/src/schemas/hosts.ts +37 -0
  458. package/src/schemas/intentic.ts +2 -0
  459. package/src/schemas/internal.ts +17 -0
  460. package/src/schemas/inventory.ts +68 -0
  461. package/src/schemas/logs.ts +96 -0
  462. package/src/schemas/loops.ts +401 -0
  463. package/src/schemas/maintenance.ts +421 -0
  464. package/src/schemas/marketplace.ts +23 -0
  465. package/src/schemas/panels.ts +99 -0
  466. package/src/schemas/personas.ts +281 -0
  467. package/src/schemas/plan-limits.ts +255 -0
  468. package/src/schemas/ports.ts +84 -0
  469. package/src/schemas/provider-oauth.ts +191 -0
  470. package/src/schemas/provider-subscriptions.ts +11 -0
  471. package/src/schemas/public.ts +52 -0
  472. package/src/schemas/push.ts +112 -0
  473. package/src/schemas/secrets.ts +68 -0
  474. package/src/schemas/sessions.ts +16 -0
  475. package/src/schemas/settings.ts +932 -0
  476. package/src/schemas/share.ts +71 -0
  477. package/src/schemas/shared.ts +32 -0
  478. package/src/schemas/system.ts +156 -0
  479. package/src/schemas/terminal.ts +286 -0
  480. package/src/schemas/usage.ts +303 -0
  481. package/src/{schemas.test.ts → schemas/version-seam.test.ts} +4 -2
  482. package/src/schemas/vpn.ts +215 -0
  483. package/src/schemas/webext.ts +79 -0
  484. package/src/schemas/workflows.ts +413 -0
  485. package/src/schemas/workspace-repos.ts +123 -0
  486. package/src/schemas/workspace-search.ts +141 -0
  487. package/src/schemas/workspace-setup.ts +43 -0
  488. package/src/schemas/workspace-tree.ts +234 -0
  489. package/src/title.test.ts +1 -1
  490. package/src/webext-links.ts +80 -0
  491. package/src/webext-protocol.ts +27 -0
  492. package/src/workflow-faults.test.ts +1 -1
  493. package/src/workflow-faults.ts +1 -1
  494. package/src/workspace-state.test.ts +3 -3
  495. package/src/workspace-state.ts +8 -13
  496. package/dist/schemas.d.ts +0 -9909
  497. package/dist/schemas.d.ts.map +0 -1
  498. package/dist/schemas.js +0 -4288
  499. package/dist/schemas.js.map +0 -1
  500. package/src/schemas.ts +0 -10090
@@ -0,0 +1,68 @@
1
+ // inventory: the i.have.* / i.want.service entries in deploy.config.ts's managed region
2
+ import { z } from "zod";
3
+ // The daemon renders/parses these; the browser edits them through the inventory routes. Moved here from the
4
+ // daemon's deploy-config.ts so the daemon and the browser validate against ONE schema (no cross-repo dupes).
5
+
6
+ export const InventoryProviderSchema = z.enum(["host", "cloudflare", "github", "gitlab", "stripe"]);
7
+ export type InventoryProvider = z.infer<typeof InventoryProviderSchema>;
8
+ export const ServiceKindSchema = z.enum(["signoz", "outline", "paperless", "openproject", "invoiceninja", "infisical"]);
9
+ export type ServiceKind = z.infer<typeof ServiceKindSchema>;
10
+ // Non-secret option values the user provides; secret options (sshKey, apiToken, apiKey) are emitted as env()
11
+ // references and never travel over the wire.
12
+ export const InventoryValuesSchema = z.record(z.string(), z.union([z.string(), z.number()]));
13
+ // `const <name>` binding in deploy.config.ts, so it must be a valid identifier.
14
+ const inventoryName = z
15
+ .string()
16
+ .min(1)
17
+ .max(60)
18
+ .regex(/^[a-zA-Z_][a-zA-Z0-9_]*$/);
19
+ export const BackendEntrySchema = z.object({
20
+ kind: z.literal("backend").describe("Something you already have: a machine, an account with a hosting provider."),
21
+ provider: InventoryProviderSchema.describe("Which provider it is with."),
22
+ name: z.string().describe("What to call it, which is also how everything else refers to it."),
23
+ values: InventoryValuesSchema.describe("Its settings. Anything secret is stored separately and referred to here, never written in."),
24
+ });
25
+ export const ServiceEntrySchema = z.object({
26
+ kind: z.literal("service").describe("Something you want provisioned."),
27
+ service: ServiceKindSchema.describe("Which service."),
28
+ name: z.string().describe("What to call it."),
29
+ values: InventoryValuesSchema.describe("Its settings."),
30
+ on: z.string().describe("Which of your machines to put it on."),
31
+ expose: z.string().describe("How it should be reachable."),
32
+ });
33
+ // i.want.app, a deployable app built from source. Single production environment on `main`; `values.domain` is
34
+ // where it's exposed. Multi-env/teams/use wiring is hand-authored outside the managed region.
35
+ export const AppEntrySchema = z.object({
36
+ kind: z.literal("app").describe("An app of your own, built from source and deployed."),
37
+ name: z.string().describe("What to call it."),
38
+ values: InventoryValuesSchema.describe("Its settings, including the address it should answer on."),
39
+ on: z.string().describe("Which of your machines to put it on."),
40
+ expose: z.string().describe("How it should be reachable."),
41
+ });
42
+ export const InventoryEntrySchema = z.discriminatedUnion("kind", [BackendEntrySchema, ServiceEntrySchema, AppEntrySchema]);
43
+ export type InventoryEntry = z.infer<typeof InventoryEntrySchema>;
44
+ export const AddInventoryInputSchema = z.discriminatedUnion("kind", [
45
+ BackendEntrySchema.extend({ name: inventoryName }),
46
+ ServiceEntrySchema.extend({ name: inventoryName }),
47
+ AppEntrySchema.extend({ name: inventoryName }),
48
+ ]);
49
+ export type AddInventoryInput = z.infer<typeof AddInventoryInputSchema>;
50
+ export const InventoryNameParamSchema = z.object({ name: z.string().describe("Which entry, by name.") });
51
+ export const InventoryListSchema = z.object({
52
+ entries: z.array(InventoryEntrySchema).describe("Everything declared: what you have, and what you want provisioned."),
53
+ });
54
+ // A deploy-target host self-registering via the connect-host script's POST /enroll (connect-token auth). The SSH
55
+ // key (+ optional Cloudflare token) is written to desired-state/.env; the host (+ cf) is upserted into inventory.
56
+ export const EnrollHostInputSchema = z.object({
57
+ name: inventoryName,
58
+ user: z.string().min(1),
59
+ address: z.string().min(1),
60
+ port: z.coerce.number().default(22),
61
+ via: z.enum(["direct", "cloudflared"]).default("cloudflared"),
62
+ sshKey: z.string().min(1),
63
+ cfToken: z.string().optional(),
64
+ // The zone the connect script resolved alongside cfToken, recorded on the i.have.cloudflare entry so
65
+ // resolve validates against it (no re-discovery) and the Add-service dialog offers `<subdomain>.<zone>`.
66
+ cfZone: z.string().optional(),
67
+ });
68
+ export type EnrollHostInput = z.infer<typeof EnrollHostInputSchema>;
@@ -0,0 +1,96 @@
1
+ // logs: daemon-owned debug logs (historyRoot/logs)
2
+ import { z } from "zod";
3
+ // Terminal pipe-pane captures (terminals/), intentic CLI run logs (intentic-runs/), and the daemon's own pino
4
+ // file (daemon.log), written by the daemon/tmux only, under historyRoot so the agent can't rewrite them.
5
+
6
+ export const LogFileEntrySchema = z.object({
7
+ // Path relative to the logs root, e.g. "terminals/web-1-%0.log" or "daemon.log".
8
+ name: z.string().describe("Its name, which is what the read route takes."),
9
+ sizeBytes: z.number().describe("Size in bytes."),
10
+ // Epoch ms mtime.
11
+ modifiedAt: z.number().describe("When it last changed, in milliseconds."),
12
+ });
13
+ export type LogFileEntry = z.infer<typeof LogFileEntrySchema>;
14
+ export const LogsListSchema = z.object({
15
+ files: z.array(LogFileEntrySchema).describe("Every log the sandbox keeps: captured terminal output, command runs, and its own log."),
16
+ });
17
+ // `name` rides the query (log names contain slashes, which don't fit a path segment); `bytes` is the tail
18
+ // size, the newest bytes win when the file is larger.
19
+ export const LogReadQuerySchema = z.object({
20
+ name: z.string().min(1).describe("Which log. It travels in the query rather than the address, because log names contain slashes."),
21
+ bytes: z.coerce
22
+ .number()
23
+ .min(1)
24
+ .max(1_048_576)
25
+ .default(65_536)
26
+ .describe("How much of the end to read. The newest bytes win when the file is larger."),
27
+ });
28
+ export const LogReadSchema = z.object({
29
+ name: z.string().describe("Which log this is from."),
30
+ sizeBytes: z.number().describe("How large the whole file is."),
31
+ // The tail text; truncated when the file holds more than the requested bytes.
32
+ text: z.string().describe("The end of it, as text."),
33
+ truncated: z.boolean().describe("There is more before what you got."),
34
+ });
35
+ export type LogRead = z.infer<typeof LogReadSchema>;
36
+ /* ---- client diagnostics: what the BROWSER saw, landed where the daemon's own records live ----
37
+ *
38
+ * The one gap no daemon-side record could ever close. Everything the editor measured or caught ended at
39
+ * `console.warn`: the perf ring buffer dies on reload, a render error reaches Vue's handler and stops there, and
40
+ * the startup self-heal CLEARS this origin's storage and reloads, destroying the evidence for the one class of
41
+ * bug that reproduces least often. So when a user hit a bug in their own browser the durable record was
42
+ * nothing, and the only way to investigate was to re-drive a browser and hope. Measured over 728 sessions that
43
+ * is 1,545 screenshots against 65 console reads, and a quarter of all prompts arriving with a picture attached
44
+ * because there was no other channel.
45
+ *
46
+ * Deliberately NARROW. This is not analytics (PostHog owns product events) and not a log pipe: it carries the
47
+ * things a person cannot describe and a screenshot cannot show, which are caught errors, self-heal wipes, and
48
+ * spans that blew their frame budget. Everything is capped at the schema so one looping component cannot fill
49
+ * the /history volume, and the daemon appends to logs/client.jsonl under the same prune sweep as the rest. */
50
+ export const ClientDiagnosticSchema = z.object({
51
+ // When the BROWSER saw it. Distinct from the `time` the daemon stamps on the record, because a batch can
52
+ // arrive seconds late and a reader correlating a stutter to a daemon span needs the moment it happened.
53
+ seenAt: z.number().describe("When the browser saw it, in milliseconds."),
54
+ level: z.enum(["warn", "error"]).describe("How bad it was."),
55
+ // A stable name, not free text: this is what a reader filters on. e.g. `vue.render`, `window.error`,
56
+ // `unhandled.rejection`, `self-heal.wipe`, `perf.slow`.
57
+ event: z.string().min(1).max(100).describe("What kind of thing it was, as a stable name."),
58
+ message: z.string().max(2_000).describe("What it said."),
59
+ // The app route the user was on, which is the single most useful field for reproducing anything.
60
+ route: z.string().max(300).optional().describe("Which page they were on."),
61
+ /* The id this browser put on the daemon call it was making, when there was one. The join key: without it
62
+ * "the UI stuttered at 15:22" and "slow http.request at 15:22" can only be matched by eye. */
63
+ requestId: z.string().max(100).optional().describe("Which daemon call it belonged to, when it belonged to one."),
64
+ // Which build this browser was running, so a report from a tab nobody has reloaded in a week says so.
65
+ build: z.string().max(100).optional().describe("Which build of the app was running."),
66
+ // Bounded and primitive: a stack, an op name, a duration. Kept flat so a line stays greppable.
67
+ fields: z
68
+ .record(z.string().max(60), z.union([z.string().max(4_000), z.number(), z.boolean()]))
69
+ .optional()
70
+ .describe("Whatever else was worth keeping."),
71
+ });
72
+ export type ClientDiagnostic = z.infer<typeof ClientDiagnosticSchema>;
73
+ // A batch. Capped: the client coalesces and drops on its own side too, and a route that accepts an unbounded
74
+ // array is a way to fill a disk with one request.
75
+ export const ClientDiagnosticsReportSchema = z.object({
76
+ events: z.array(ClientDiagnosticSchema).min(1).max(50).describe("What the browser has to report, oldest first."),
77
+ });
78
+ export type ClientDiagnosticsReport = z.infer<typeof ClientDiagnosticsReportSchema>;
79
+ export const ClientDiagnosticsAcceptedSchema = z.object({
80
+ recorded: z.number().describe("How many were written down."),
81
+ });
82
+ // A tab's self-report of what it is looking at, keyed by its /events connection's clientId. Full replace,
83
+ // not a merge, an absent field means "cleared", so a tab leaving a file drops the path with the same report.
84
+ export const PresenceReportSchema = z.object({
85
+ clientId: z.string().describe("This connection's own id, the same one it gave the event stream."),
86
+ idle: z.boolean().describe("Whether the person has stopped doing anything."),
87
+ view: z.string().optional().describe("Which view they are on."),
88
+ sessionId: z.string().optional().describe("Which conversation they have open."),
89
+ path: z
90
+ .string()
91
+ .optional()
92
+ .describe(
93
+ "Which file they are looking at. Sent whole rather than merged: leaving a field out clears it, so a tab that closes a file drops the path in the same report.",
94
+ ),
95
+ });
96
+ export type PresenceReport = z.infer<typeof PresenceReportSchema>;
@@ -0,0 +1,401 @@
1
+ // loops: run a conversation again, and again, until a goal is met
2
+ import { z } from "zod";
3
+ import { STATE_DIR } from "@intentic/constants";
4
+ import { OutputFieldsSchema } from "../output-fields.js";
5
+ import { AgentHarnessSchema, AgentProviderSchema, ConversationIdSchema, RepoBaseSchema } from "./agent.js";
6
+ import { entryId } from "./internal.js";
7
+ /* THE RALPH LOOP. An automation answers "run this at 3am"; a loop answers "run this until it is actually done".
8
+ * The two are the opposite question and neither substitutes for the other: a schedule repeats on CADENCE and
9
+ * never converges, a loop repeats on CONVERGENCE and stops the moment its goal is met.
10
+ *
11
+ * A loop is an ATTRIBUTE OF A CONVERSATION, not a new kind of object. It drives ordinary turns on an ordinary
12
+ * fleet agent, which is what makes the worktree, the cost ledger, the transcript, the /agents card and the Stop
13
+ * button work on it without a line of new code, the same bet the acceptance extension makes when it derives
14
+ * conversation ids instead of owning session machinery.
15
+ */
16
+
17
+ // How the next iteration meets its context, and the single most consequential field here.
18
+ //
19
+ // `fresh` is the canonical Ralph and the default: each iteration is a NEW provider session against the SAME
20
+ // worktree, so the filesystem, not the transcript, is the memory. Immune to context rot, so iteration 20 reads
21
+ // the tree as clearly as iteration 1, and it costs a re-read each time. The loop keeps a progress file for it
22
+ // (see LOOP_DIR) precisely because nothing else carries forward.
23
+ //
24
+ // `continue` resumes the provider session, so an iteration is a follow-up prompt. Cheaper (the prefix caches)
25
+ // and it keeps the reasoning, which is what a short refine-this loop wants. It degrades on long runs, and it
26
+ // degrades in the direction that matters: a session that has spent eleven turns arguing for its own approach is
27
+ // the worst available judge of whether that approach is finished.
28
+ export const LoopContextSchema = z.enum(["fresh", "continue"]);
29
+ export type LoopContext = z.infer<typeof LoopContextSchema>;
30
+ /* WHAT THE LOOP PRODUCES, asked separately from what ends it, because they are separate questions and
31
+ * conflating them is what makes a chain of sessions impossible to build.
32
+ *
33
+ * `none`, the loop produces nothing but its work. The classic "make the suite green": what it leaves behind
34
+ * is a green suite, and asking it to also file a report is asking it to spend a turn on paperwork.
35
+ * `claim`, the iteration writes `{done, reason, evidence?}`. Prose, but STRUCTURED prose: `done` is a boolean
36
+ * the daemon reads rather than a sentence it has to interpret. Self-assessment, so advisory by construction,
37
+ * it exists because plenty of goals have no command that can check them ("the README explains the auth
38
+ * flow"), not because a model's word for it is worth much.
39
+ * `json`, the iteration writes `{done, reason, data}` where `data` matches a declared field list. This is the
40
+ * one that makes a step's output usable as the next step's input: a paragraph mentioning three files cannot
41
+ * be fed to anything, `{files: [...]}` can.
42
+ *
43
+ * All three land in ONE file per iteration, with one shape, differing only in strictness. See LoopDocumentSchema.
44
+ */
45
+ export const LoopOutputSchema = z.discriminatedUnion("kind", [
46
+ z.object({
47
+ kind: z
48
+ .literal("none")
49
+ .describe(
50
+ "It produces nothing but its work. The classic make the suite pass: what it leaves behind is a passing suite, and asking it to also file a report is asking it to spend a round on paperwork.",
51
+ ),
52
+ }),
53
+ z.object({
54
+ kind: z
55
+ .literal("claim")
56
+ .describe(
57
+ "Each round says whether it is done and why. Structured prose: done is a value read rather than a sentence interpreted. Self-assessment, so advisory by construction; it exists because plenty of goals have no command that could check them.",
58
+ ),
59
+ }),
60
+ z.object({
61
+ kind: z
62
+ .literal("json")
63
+ .describe(
64
+ "Each round writes a real answer in a shape you declared. This is the one that makes a step's output usable as the next step's input: a paragraph mentioning three files cannot be fed to anything, a list of three files can.",
65
+ ),
66
+ fields: OutputFieldsSchema.describe("The shape that answer has to match."),
67
+ }),
68
+ ]);
69
+ export type LoopOutput = z.infer<typeof LoopOutputSchema>;
70
+ /* WHAT ELSE HAS TO BE TRUE, checks that are not the worker's own word, ANDed with the output above.
71
+ *
72
+ * `command` is a shell one-liner run in the conversation's tree; exit 0 ⇒ satisfied. Deterministic, free, and
73
+ * the only signal here whose answer does not come from a model. It is the automation `guard` with the sign
74
+ * flipped, and it runs through the same runner. `pnpm test` passing beats any amount of self-report.
75
+ *
76
+ * `judge` puts a SEPARATE, tool-less call on the question: it reads the iteration's own report and rules
77
+ * against a rubric, having done none of the work and nothing invested in it being finished.
78
+ *
79
+ * The rule both encode, and the reason they are kept apart from the output: the check must be a DIFFERENT CALL
80
+ * from the work, or it is not a check. An output is what the worker says; a check is what someone else says.
81
+ */
82
+ export const LoopCheckSchema = z.discriminatedUnion("kind", [
83
+ z.object({
84
+ kind: z
85
+ .literal("command")
86
+ .describe(
87
+ "Run something and see if it passes. Deterministic, free, and the only signal here whose answer does not come from a model. A passing test suite beats any amount of self-report.",
88
+ ),
89
+ command: z.string().min(1).describe("The command to run in the conversation's own tree. Exiting cleanly means satisfied."),
90
+ }),
91
+ // The rubric is what the judge is asked; absent `model` runs it on the quick rung the other helpers use.
92
+ z.object({
93
+ kind: z
94
+ .literal("judge")
95
+ .describe(
96
+ "Put the question to a separate model with no tools, which reads the round's own report and rules on it, having done none of the work and nothing invested in its being finished.",
97
+ ),
98
+ rubric: z.string().min(1).describe("What that judge is asked."),
99
+ model: z.string().optional().describe("Which model judges. Leave it out for the cheap one the other small jobs use."),
100
+ }),
101
+ ]);
102
+ export type LoopCheck = z.infer<typeof LoopCheckSchema>;
103
+ /* THE VERDICT FILE an iteration writes, one shape for all three output kinds, because the loop reads it the
104
+ * same way whatever was declared and only the validation of `data` differs.
105
+ *
106
+ * It is a FILE rather than a sentence in the reply for the reason every structured output in this codebase is
107
+ * a file: a reply has to be parsed out of prose the model is simultaneously using to talk to a person, and the
108
+ * two demands pull against each other until neither is served. A file has one job.
109
+ */
110
+ export const LoopDocumentSchema = z.object({
111
+ // Whether the goal is met NOW. The loop's own reading of this is the whole point of the file.
112
+ done: z.boolean().describe("Whether the goal is met. Reading this is the whole point of the file."),
113
+ // One line: why it is or is not met. The single most-read string in the feature, it is what the next
114
+ // iteration reads first and what the history row shows.
115
+ reason: z.string().describe("Why, in one line. The most-read sentence in the feature: the next round reads it first and the history shows it."),
116
+ // What the iteration checked to know that. Optional because a model with nothing to point at should say so
117
+ // by omitting it rather than by inventing a sentence.
118
+ evidence: z
119
+ .string()
120
+ .optional()
121
+ .describe(
122
+ "What was checked to know that. Optional, so a round with nothing to point at says so by leaving it out rather than by inventing a sentence.",
123
+ ),
124
+ // The declared fields, present only for a `json` output and validated against them there.
125
+ data: z
126
+ .record(z.string(), z.unknown())
127
+ .optional()
128
+ .describe("The declared answer, for a loop that asked for one, checked against the shape it declared."),
129
+ });
130
+ export type LoopDocument = z.infer<typeof LoopDocumentSchema>;
131
+ // Enough iterations for a real convergence, few enough that a misconfigured loop is a bounded mistake. A loop
132
+ // that has not converged in 50 turns is not one iteration short of it.
133
+ const LOOP_ITERATIONS_MAX = 50;
134
+ export const LoopSchema = z.object({
135
+ // The conversation the loop drives, its fleet card, its worktree, its transcript.
136
+ conversationId: ConversationIdSchema.describe(
137
+ "The conversation to loop. It need not exist yet: naming a fresh one opens it, which is what lets run this until it passes be the first thing you ever say.",
138
+ ),
139
+ // What "done" means, in the user's words. Rides into every iteration's prompt (and into the judge's
140
+ // question) so the model is told the goal it is being measured against rather than left to infer it.
141
+ goal: z
142
+ .string()
143
+ .min(1)
144
+ .describe(
145
+ "What done means, in your words. It goes into every round's instructions and into the judge's question, so the model is told the bar rather than left to infer it.",
146
+ ),
147
+ // What each iteration is asked to DO. Separate from `goal` because they are different sentences: "make the
148
+ // suite green" is the goal, "run the tests, pick the top failure, fix it" is the instruction.
149
+ prompt: z
150
+ .string()
151
+ .min(1)
152
+ .describe("What each round is asked to do. The suite passes is the goal; run the tests, take the top failure, fix it is the instruction."),
153
+ context: LoopContextSchema.describe(
154
+ "How each round meets the last. Starting fresh makes the files the memory rather than the conversation, so the twentieth round reads the tree as clearly as the first, and costs a re-read each time. Carrying on is cheaper and keeps the reasoning, which suits a short polish-this loop and degrades on long ones: a session that has spent eleven rounds arguing for its own approach is the worst available judge of whether that approach is finished.",
155
+ ),
156
+ output: LoopOutputSchema,
157
+ /* Everything besides the worker's own word that has to hold before the loop may end. Ordinarily one or
158
+ * none; a list because "the suite is green AND the report is written" is a real completion bar and
159
+ * expressing it as two loops would run the work twice. */
160
+ checks: z
161
+ .array(LoopCheckSchema)
162
+ .describe(
163
+ "What else has to be true, all of them together. A list because the suite passes and the report is written is a real bar, and running it as two loops would do the work twice.",
164
+ ),
165
+ maxIterations: z
166
+ .number()
167
+ .int()
168
+ .min(1)
169
+ .max(LOOP_ITERATIONS_MAX)
170
+ .describe("How many rounds before it gives up. A loop that has not got there in fifty is not one round short of it."),
171
+ // The spend ceiling in USD across the whole loop, summed from the turns' own usage frames. Optional because
172
+ // a 3-iteration loop does not need one; strongly wanted on anything unattended, since this is the first
173
+ // feature in the sandbox that can spend without a person pressing anything between turns.
174
+ maxSpendUsd: z
175
+ .number()
176
+ .positive()
177
+ .optional()
178
+ .describe(
179
+ "A ceiling on what the whole loop may spend, in dollars. Optional for a short loop somebody is watching, and strongly wanted otherwise: this is the first thing here that can keep spending with nobody pressing anything between rounds.",
180
+ ),
181
+ /* Stop after this many CONSECUTIVE iterations that changed nothing in the tree.
182
+ *
183
+ * The guard that matters most in practice, and the one whose absence is expensive. The failure mode of a
184
+ * loop is not runaway success, it is an agent that re-reads the same three files, restates the same plan,
185
+ * declares more work remains, and does that eleven times. Nothing about that is an error, every turn
186
+ * succeeds, so only "the tree did not move" catches it. */
187
+ stallLimit: z
188
+ .number()
189
+ .int()
190
+ .min(1)
191
+ .describe(
192
+ "Stop after this many rounds in a row that changed nothing on disk. The guard that matters most: a loop's failure is not runaway success, it is an agent re-reading the same three files, restating the same plan and declaring more work remains, eleven times. Every one of those rounds succeeds, so only the tree not moving catches it.",
193
+ ),
194
+ // Whether the iterations run in the conversation's own worktree or on the shared tree. Recorded on the loop
195
+ // rather than read off the conversation because a loop can OPEN one, and because it decides where the stop
196
+ // command runs: a check against /work would be testing code an isolated loop has not landed yet.
197
+ isolated: z
198
+ .boolean()
199
+ .describe(
200
+ "Whether it works in the conversation's own private copy or in the shared tree. It also decides where a check runs: testing the shared tree would be testing code this loop has not merged yet.",
201
+ ),
202
+ // Which provider / harness / model the iterations run on; absent ⇒ the conversation's own last choice, then
203
+ // the provider default. The same three passthroughs an automation carries, for the same reason: a headless
204
+ // driver has no composer to read them from.
205
+ agent: AgentProviderSchema.optional().describe("Which provider the rounds run on. Absent falls back to the conversation's own last choice."),
206
+ harness: AgentHarnessSchema.optional().describe("Which agentic loop they run on."),
207
+ account: z.string().optional().describe("Which account pays."),
208
+ model: z.string().optional().describe("Which model."),
209
+ // Which persona the iterations act as (AgentTurnSchema.actsAs, read its note for why this is not spelled
210
+ // `account`). The fourth passthrough an automation carries, and it matters here for the automation's
211
+ // reason: every iteration is unattended, and an unattended turn with no persona reaches no logged-in
212
+ // account at all, pinning a card is the one way a loop gets hands.
213
+ actsAs: entryId
214
+ .optional()
215
+ .describe(
216
+ "Which persona the rounds act as. It matters here: every round is unwatched, and an unwatched turn naming no persona reaches no signed-in account at all, so pinning one is how a loop gets hands.",
217
+ ),
218
+ // A workflow persists these on its underlying loop so restart recovery cannot silently change the checkout
219
+ // or let a candidate inherit the sandbox's global auto-land posture on a later iteration.
220
+ worktreeBase: z
221
+ .array(RepoBaseSchema)
222
+ .min(1)
223
+ .max(50)
224
+ .optional()
225
+ .describe("Pin the private copy to these exact commits, so a restart cannot quietly change what the loop is working on."),
226
+ autoLand: z.boolean().optional().describe("Whether the work merges as it goes."),
227
+ });
228
+ export type Loop = z.infer<typeof LoopSchema>;
229
+ // Can this loop ever end on its own terms? A loop with nothing to produce and nothing to check runs to its
230
+ // iteration ceiling and reports `exhausted`, having been unable to succeed from the moment it was configured.
231
+ // A predicate rather than a schema refinement because two routes want it as one, at different moments: `start`
232
+ // refuses an ad-hoc loop, and `saveDesign` refuses a SAVED one, which is the more valuable of the two, since a
233
+ // saved loop that cannot converge is a trap everyone who picks it afterwards pays a full run to discover.
234
+ export const loopCanConverge = (loop: Pick<Loop, "output" | "checks">): boolean => loop.output.kind !== "none" || loop.checks.length > 0;
235
+ /* Where a loop keeps what it must not lose between iterations: <workspace>/.intentic/records/artifacts/loops/<conversationId>/.
236
+ *
237
+ * Under `.intentic` for the reason the acceptance runs are, it is outside every repo and bound back SHARED
238
+ * into an isolated turn's worktree, so the agent writes and the browser reads the same tree, with nothing to
239
+ * land and no git noise. `progress.md` is the loop's memory in `fresh` mode and its audit trail in `continue`
240
+ * mode; `iteration-<n>.json` is the verdict a `claim` stop reads. */
241
+ export const LOOP_DIR = `${STATE_DIR}/records/artifacts/loops`;
242
+ // Why an iteration ended, which is not the same question as how the LOOP ended. `continue` is the ordinary
243
+ // "not done yet"; `error` is a turn that surfaced an error frame, which does NOT end the loop by itself, a
244
+ // failing turn is often exactly what the next iteration is supposed to fix.
245
+ export const LoopIterationSchema = z.object({
246
+ n: z.number().int().min(1).describe("Which round this was."),
247
+ at: z.number().describe("When it ran, in milliseconds."),
248
+ outcome: z
249
+ .enum(["continue", "done", "error"])
250
+ .describe(
251
+ "How the round ended, which is not the same question as how the loop did. A round that errored does not end the loop by itself: a failing turn is often exactly what the next round is meant to fix.",
252
+ ),
253
+ // The stop check's own words, the guard's output tail, the claim's reason, the judge's verdict. What the
254
+ // run history is actually read for: "why did it keep going" and "why did it stop".
255
+ detail: z
256
+ .string()
257
+ .optional()
258
+ .describe("What the check said, in its own words. What a run history is actually read for: why it kept going, and why it stopped."),
259
+ costUsd: z.number().optional().describe("What the round cost, in dollars."),
260
+ // Whether the tree moved this iteration. Feeds the stall detector, and is worth showing per row: three
261
+ // unchanged iterations in a history is the shape of a loop that is not working.
262
+ changed: z.boolean().describe("Whether anything on disk moved. Three unchanged rounds in a row is the shape of a loop that is not working."),
263
+ // The provider session this iteration ran on, the door from a history row to a readable transcript.
264
+ sessionId: z.string().optional().describe("The session it ran on, and the way from a history row to a readable record."),
265
+ });
266
+ export type LoopIteration = z.infer<typeof LoopIterationSchema>;
267
+ /* How a loop ended, and every one of these is a distinct thing to tell the user.
268
+ *
269
+ * `done`, the stop condition was met. The only success.
270
+ * `exhausted`, maxIterations ran out with the goal unmet.
271
+ * `stalled`, stallLimit consecutive iterations changed nothing. Reported apart from `exhausted` because the
272
+ * remedy is different: exhausted says "give it more room", stalled says "it is not making progress and more
273
+ * room will not help".
274
+ * `overspent`, maxSpendUsd was reached.
275
+ * `stopped`, the user pressed Stop.
276
+ * `error`, the loop itself failed (not a turn inside it; see LoopIteration.outcome).
277
+ */
278
+ export const LoopStateSchema = z.enum(["running", "done", "exhausted", "stalled", "overspent", "stopped", "error"]);
279
+ export type LoopState = z.infer<typeof LoopStateSchema>;
280
+ export const LoopRecordSchema = LoopSchema.extend({
281
+ state: LoopStateSchema.describe(
282
+ "How it ended, and each of these is a different thing to be told. Out of rounds says give it more room; stalled says it is not making progress and more room will not help. Overspent, stopped by a person, and the loop itself failing are all their own answers.",
283
+ ),
284
+ startedAt: z.number().describe("When it began, in milliseconds."),
285
+ endedAt: z.number().optional().describe("When it ended, in milliseconds."),
286
+ /* How many times a daemon BOOT has picked this loop back up. The record is its own journal: a loop still
287
+ * marked `running` at boot is exactly one the daemon died under, which is the same trick turn-journal.ts
288
+ * plays with its files and needs no second store to play it.
289
+ *
290
+ * Counted, not just flagged, for the reason the turn journal counts its attempts, a loop whose iteration
291
+ * reliably kills the daemon (an OOM in a test it keeps running) would otherwise be resurrected on every
292
+ * boot forever, and the container is recreated on every sandbox update. */
293
+ resumed: z
294
+ .number()
295
+ .int()
296
+ .min(0)
297
+ .describe(
298
+ "How many times the sandbox restarted under it and picked it back up. Counted rather than flagged, so a loop whose round reliably kills the sandbox is not resurrected on every boot for ever.",
299
+ ),
300
+ // Why the loop ended, for the states whose reason isn't in their name (`error`, and a `done` whose stop
301
+ // check said something worth keeping).
302
+ detail: z.string().optional().describe("Why it ended, for the endings whose reason is not in their name."),
303
+ iterations: z
304
+ .array(LoopIterationSchema)
305
+ .describe("Every round, in order. Why it stopped at the fourth is the question a loop gets read for, and this is the answer."),
306
+ });
307
+ export type LoopRecord = z.infer<typeof LoopRecordSchema>;
308
+ export const LoopsListSchema = z.object({
309
+ loops: z.array(LoopRecordSchema).describe("Every loop this workspace has run, newest first, kept after they end."),
310
+ });
311
+ export const LoopIdParamSchema = z.object({ conversationId: ConversationIdSchema.describe("Which conversation's loop.") });
312
+ /* ---- saved loops: the machinery, kept; the job, typed fresh each time ----
313
+ *
314
+ * A SAVED LOOP IS A LOOP WITH ITS GOAL TAKEN OUT, and that subtraction is the whole idea. Everything a loop
315
+ * needs besides "what are we doing" is the same every time somebody sets one up, end on `pnpm test`, fresh
316
+ * context, eight rounds, five dollars, stop after two idle ones, and every one of those was being retyped, in
317
+ * a modal, before any work could begin. The goal is the only field that is genuinely new each time, and it is
318
+ * the one field the user has ALREADY WRITTEN: it is sitting in the composer.
319
+ *
320
+ * So this holds the machinery and the composer holds the job, which makes a loop the same gesture as a
321
+ * workflow, pick the shape, type the request, send. `WorkflowSchema` and this are deliberately siblings: both
322
+ * are designs, both are picked from the composer, both leave the sentence to the message. What a workflow
323
+ * spreads across sessions, a loop repeats in one.
324
+ *
325
+ * NO `conversationId` AND NO `isolated`, unlike the Loop this becomes. Both are facts about the agent the loop
326
+ * is aimed at, decided at the moment of sending and unknowable when the design is written, a saved loop that
327
+ * remembered a conversation would be a loop that could only ever be run once.
328
+ */
329
+ export const LoopDesignSchema = z.object({
330
+ id: entryId.describe("The design's id."),
331
+ // What it is called on the composer badge and in the picker, so it has to survive being read at pill width.
332
+ name: z.string().min(1).max(60).describe("What to call it. Short, because it has to be readable on a small badge."),
333
+ // One line: what this loop is FOR. Optional, because a well-named loop has already said it.
334
+ description: z.string().max(280).optional().describe("What it is for, in one line. Optional, because a well-named loop has already said it."),
335
+ /* What each iteration is asked to do, when that is worth saying twice. Optional for the reason the ad-hoc
336
+ * form made it optional: `goal` and `prompt` are different sentences, but making somebody write both before
337
+ * anything runs doubles the cost of trying a loop at all. Absent ⇒ the iteration works towards the goal
338
+ * however it sees fit. */
339
+ prompt: z
340
+ .string()
341
+ .optional()
342
+ .describe(
343
+ "What each round is asked to do, when that is worth saying separately from the goal. Absent means each round works towards the goal however it sees fit.",
344
+ ),
345
+ context: LoopContextSchema.describe("How each round meets the last: starting clean, or carrying on."),
346
+ output: LoopOutputSchema.describe("What it has to produce."),
347
+ checks: z.array(LoopCheckSchema).describe("What else has to be true."),
348
+ maxIterations: z.number().int().min(1).max(LOOP_ITERATIONS_MAX).describe("How many rounds before it gives up."),
349
+ maxSpendUsd: z.number().positive().optional().describe("A ceiling on what it may spend, in dollars."),
350
+ stallLimit: z.number().int().min(1).describe("Stop after this many rounds in a row that changed nothing."),
351
+ });
352
+ export type LoopDesign = z.infer<typeof LoopDesignSchema>;
353
+ export const LoopDesignsListSchema = z.object({
354
+ designs: z
355
+ .array(LoopDesignSchema)
356
+ .describe("Saved loops: the machinery with the goal left out, so one design can be pointed at a different job every time."),
357
+ });
358
+ // Create and update on one route with the intent spelled out, exactly as a workflow saves, so an id collision
359
+ // cannot silently turn "new loop" into "replace the one you had".
360
+ export const LoopDesignSaveSchema = z.object({
361
+ design: LoopDesignSchema.describe("The design to write."),
362
+ create: z
363
+ .boolean()
364
+ .describe(
365
+ "Whether you mean to make a new one or replace an existing one, so an id that happens to collide cannot silently overwrite the one you had.",
366
+ ),
367
+ });
368
+ export const LoopDesignIdParamSchema = z.object({ id: entryId.describe("Which saved loop.") });
369
+ /* The design, aimed at an agent, the one conversion in the feature, kept here so the composer and anything
370
+ * else that starts a saved loop cannot disagree about what a saved loop MEANS. The goal is the message the user
371
+ * typed; `isolated` is a fact about the agent it is aimed at. */
372
+ export const loopFromDesign = (design: LoopDesign, aim: { conversationId: string; goal: string; isolated: boolean }): Loop => ({
373
+ conversationId: aim.conversationId,
374
+ goal: aim.goal,
375
+ prompt: design.prompt ?? "Work towards the goal above. Do the next most useful thing.",
376
+ context: design.context,
377
+ output: design.output,
378
+ checks: design.checks,
379
+ maxIterations: design.maxIterations,
380
+ ...(design.maxSpendUsd === undefined ? {} : { maxSpendUsd: design.maxSpendUsd }),
381
+ stallLimit: design.stallLimit,
382
+ isolated: aim.isolated,
383
+ });
384
+ /* HOW A SAVED LOOP ENDS, IN ONE LINE, the sentence under its name in the picker and on its card, computed
385
+ * rather than stored so the two can never describe the same loop differently. Ordered as it is read: the bar it
386
+ * has to clear first, then how far it may go trying. */
387
+ export const loopDesignLine = (design: LoopDesign): string => {
388
+ const command = design.checks.find((check) => check.kind === "command");
389
+ const ends =
390
+ command !== undefined
391
+ ? command.command
392
+ : design.checks.some((check) => check.kind === "judge")
393
+ ? "a reviewer agrees"
394
+ : design.output.kind === "none"
395
+ ? "nothing checks it"
396
+ : "the agent says so";
397
+ const ceilings = [`${design.maxIterations} rounds`, design.maxSpendUsd === undefined ? `` : `$${design.maxSpendUsd}`].filter(
398
+ (part) => part !== ``,
399
+ );
400
+ return [ends, ...ceilings].join(" · ");
401
+ };