@intentic/sandbox-contract 1.248.0 → 1.250.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 (879) hide show
  1. package/README.md +18 -15
  2. package/dist/chores/chores.d.ts.map +1 -1
  3. package/dist/chores/chores.js.map +1 -1
  4. package/dist/chores/digest.d.ts.map +1 -1
  5. package/dist/chores/digest.js.map +1 -1
  6. package/dist/chores/extension-update.d.ts.map +1 -1
  7. package/dist/chores/extension-update.js.map +1 -1
  8. package/dist/chores/fix-deps.d.ts.map +1 -1
  9. package/dist/chores/fix-deps.js.map +1 -1
  10. package/dist/chores/index.d.ts +2 -2
  11. package/dist/chores/index.d.ts.map +1 -1
  12. package/dist/chores/index.js +1 -1
  13. package/dist/chores/index.js.map +1 -1
  14. package/dist/chores/probes.d.ts.map +1 -1
  15. package/dist/chores/probes.js.map +1 -1
  16. package/dist/chores/prompt.d.ts.map +1 -1
  17. package/dist/chores/prompt.js.map +1 -1
  18. package/dist/chores/stack.d.ts.map +1 -1
  19. package/dist/chores/stack.js.map +1 -1
  20. package/dist/chores/verdict.d.ts +7 -1
  21. package/dist/chores/verdict.d.ts.map +1 -1
  22. package/dist/chores/verdict.js +8 -0
  23. package/dist/chores/verdict.js.map +1 -1
  24. package/dist/contracts/accounts.contract.d.ts.map +1 -1
  25. package/dist/contracts/accounts.contract.js.map +1 -1
  26. package/dist/contracts/activity.contract.d.ts +1 -0
  27. package/dist/contracts/activity.contract.d.ts.map +1 -1
  28. package/dist/contracts/agent.contract.d.ts +12 -205
  29. package/dist/contracts/agent.contract.d.ts.map +1 -1
  30. package/dist/contracts/agent.contract.js +2 -1
  31. package/dist/contracts/agent.contract.js.map +1 -1
  32. package/dist/contracts/agents.contract.d.ts +228 -54
  33. package/dist/contracts/agents.contract.d.ts.map +1 -1
  34. package/dist/contracts/agents.contract.js +11 -2
  35. package/dist/contracts/agents.contract.js.map +1 -1
  36. package/dist/contracts/automations.contract.d.ts +35 -17
  37. package/dist/contracts/automations.contract.d.ts.map +1 -1
  38. package/dist/contracts/automations.contract.js +10 -1
  39. package/dist/contracts/automations.contract.js.map +1 -1
  40. package/dist/contracts/capabilities.contract.d.ts +0 -12
  41. package/dist/contracts/capabilities.contract.d.ts.map +1 -1
  42. package/dist/contracts/capabilities.contract.js +1 -1
  43. package/dist/contracts/capabilities.contract.js.map +1 -1
  44. package/dist/contracts/chores.contract.d.ts.map +1 -1
  45. package/dist/contracts/chores.contract.js.map +1 -1
  46. package/dist/contracts/ci.contract.d.ts +9 -0
  47. package/dist/contracts/ci.contract.d.ts.map +1 -1
  48. package/dist/contracts/endpoints.contract.d.ts.map +1 -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 +1 -1
  52. package/dist/contracts/exit.contract.js.map +1 -1
  53. package/dist/contracts/extensions.contract.d.ts.map +1 -1
  54. package/dist/contracts/extensions.contract.js.map +1 -1
  55. package/dist/contracts/git.contract.d.ts +45 -6
  56. package/dist/contracts/git.contract.d.ts.map +1 -1
  57. package/dist/contracts/git.contract.js +9 -9
  58. package/dist/contracts/git.contract.js.map +1 -1
  59. package/dist/contracts/host.contract.d.ts +2 -0
  60. package/dist/contracts/host.contract.d.ts.map +1 -1
  61. package/dist/contracts/host.contract.js.map +1 -1
  62. package/dist/contracts/intentic.contract.js +1 -1
  63. package/dist/contracts/intentic.contract.js.map +1 -1
  64. package/dist/contracts/logs.contract.d.ts.map +1 -1
  65. package/dist/contracts/logs.contract.js.map +1 -1
  66. package/dist/contracts/loops.contract.d.ts.map +1 -1
  67. package/dist/contracts/loops.contract.js.map +1 -1
  68. package/dist/contracts/personas.contract.d.ts +1 -0
  69. package/dist/contracts/personas.contract.d.ts.map +1 -1
  70. package/dist/contracts/personas.contract.js +1 -1
  71. package/dist/contracts/personas.contract.js.map +1 -1
  72. package/dist/contracts/providers.contract.d.ts.map +1 -1
  73. package/dist/contracts/providers.contract.js.map +1 -1
  74. package/dist/contracts/runner.contract.d.ts +97 -171
  75. package/dist/contracts/runner.contract.d.ts.map +1 -1
  76. package/dist/contracts/runner.contract.js +2 -2
  77. package/dist/contracts/runner.contract.js.map +1 -1
  78. package/dist/contracts/safety.contract.d.ts.map +1 -1
  79. package/dist/contracts/safety.contract.js +1 -1
  80. package/dist/contracts/safety.contract.js.map +1 -1
  81. package/dist/contracts/secrets.contract.d.ts.map +1 -1
  82. package/dist/contracts/secrets.contract.js.map +1 -1
  83. package/dist/contracts/sessions.contract.d.ts +2 -41
  84. package/dist/contracts/sessions.contract.d.ts.map +1 -1
  85. package/dist/contracts/sessions.contract.js +1 -1
  86. package/dist/contracts/sessions.contract.js.map +1 -1
  87. package/dist/contracts/settings.contract.d.ts +8 -18
  88. package/dist/contracts/settings.contract.d.ts.map +1 -1
  89. package/dist/contracts/settings.contract.js.map +1 -1
  90. package/dist/contracts/share.contract.d.ts.map +1 -1
  91. package/dist/contracts/share.contract.js.map +1 -1
  92. package/dist/contracts/skills.contract.d.ts +6 -0
  93. package/dist/contracts/skills.contract.d.ts.map +1 -1
  94. package/dist/contracts/skills.contract.js +13 -4
  95. package/dist/contracts/skills.contract.js.map +1 -1
  96. package/dist/contracts/system.contract.d.ts +49 -73
  97. package/dist/contracts/system.contract.d.ts.map +1 -1
  98. package/dist/contracts/system.contract.js +12 -2
  99. package/dist/contracts/system.contract.js.map +1 -1
  100. package/dist/contracts/usage.contract.d.ts.map +1 -1
  101. package/dist/contracts/usage.contract.js.map +1 -1
  102. package/dist/contracts/vpn.contract.d.ts.map +1 -1
  103. package/dist/contracts/vpn.contract.js +1 -1
  104. package/dist/contracts/vpn.contract.js.map +1 -1
  105. package/dist/contracts/webext.contract.d.ts.map +1 -1
  106. package/dist/contracts/webext.contract.js.map +1 -1
  107. package/dist/contracts/workflows.contract.d.ts +7 -6
  108. package/dist/contracts/workflows.contract.d.ts.map +1 -1
  109. package/dist/contracts/workflows.contract.js +12 -3
  110. package/dist/contracts/workflows.contract.js.map +1 -1
  111. package/dist/contracts/workspace.contract.d.ts.map +1 -1
  112. package/dist/contracts/workspace.contract.js.map +1 -1
  113. package/dist/events/agent-events.d.ts +1237 -0
  114. package/dist/events/agent-events.d.ts.map +1 -0
  115. package/dist/events/agent-events.js +226 -0
  116. package/dist/events/agent-events.js.map +1 -0
  117. package/dist/events/cards.d.ts +404 -0
  118. package/dist/events/cards.d.ts.map +1 -0
  119. package/dist/events/cards.js +179 -0
  120. package/dist/events/cards.js.map +1 -0
  121. package/dist/events/resume.d.ts +23 -0
  122. package/dist/events/resume.d.ts.map +1 -0
  123. package/dist/events/resume.js +31 -0
  124. package/dist/events/resume.js.map +1 -0
  125. package/dist/events/system-events.d.ts +615 -0
  126. package/dist/events/system-events.d.ts.map +1 -0
  127. package/dist/events/system-events.js +64 -0
  128. package/dist/events/system-events.js.map +1 -0
  129. package/dist/events/transcript.d.ts +1755 -0
  130. package/dist/events/transcript.d.ts.map +1 -0
  131. package/dist/events/transcript.js +205 -0
  132. package/dist/events/transcript.js.map +1 -0
  133. package/dist/ids/conversation-ids.d.ts +8 -0
  134. package/dist/ids/conversation-ids.d.ts.map +1 -0
  135. package/dist/{conversation-ids.js → ids/conversation-ids.js} +13 -0
  136. package/dist/ids/conversation-ids.js.map +1 -0
  137. package/dist/ids/hostnames.d.ts.map +1 -0
  138. package/dist/ids/hostnames.js.map +1 -0
  139. package/dist/ids/session-names.d.ts.map +1 -0
  140. package/dist/ids/session-names.js.map +1 -0
  141. package/dist/ids/share-paths.d.ts.map +1 -0
  142. package/dist/ids/share-paths.js.map +1 -0
  143. package/dist/{tunnel-ids.d.ts → ids/tunnel-ids.d.ts} +1 -0
  144. package/dist/ids/tunnel-ids.d.ts.map +1 -0
  145. package/dist/{tunnel-ids.js → ids/tunnel-ids.js} +1 -0
  146. package/dist/ids/tunnel-ids.js.map +1 -0
  147. package/dist/index.d.ts +429 -450
  148. package/dist/index.d.ts.map +1 -1
  149. package/dist/index.js +54 -46
  150. package/dist/index.js.map +1 -1
  151. package/dist/{agent-catalog.d.ts → models/agent-catalog.d.ts} +2 -2
  152. package/dist/models/agent-catalog.d.ts.map +1 -0
  153. package/dist/models/agent-catalog.js.map +1 -0
  154. package/dist/models/agent-runtimes.d.ts.map +1 -0
  155. package/dist/models/agent-runtimes.js.map +1 -0
  156. package/dist/{fast-tier.d.ts → models/fast-tier.d.ts} +1 -1
  157. package/dist/models/fast-tier.d.ts.map +1 -0
  158. package/dist/models/fast-tier.js.map +1 -0
  159. package/dist/models/model-order.d.ts.map +1 -0
  160. package/dist/{model-order.js → models/model-order.js} +2 -0
  161. package/dist/models/model-order.js.map +1 -0
  162. package/dist/{model-pins.d.ts → models/model-pins.d.ts} +1 -1
  163. package/dist/models/model-pins.d.ts.map +1 -0
  164. package/dist/models/model-pins.js.map +1 -0
  165. package/dist/{model-roles.d.ts → models/model-roles.d.ts} +0 -33
  166. package/dist/models/model-roles.d.ts.map +1 -0
  167. package/dist/{model-roles.js → models/model-roles.js} +0 -35
  168. package/dist/models/model-roles.js.map +1 -0
  169. package/dist/{plan-pools.d.ts → models/plan-pools.d.ts} +1 -1
  170. package/dist/models/plan-pools.d.ts.map +1 -0
  171. package/dist/models/plan-pools.js.map +1 -0
  172. package/dist/models/prompt-complexity.d.ts.map +1 -0
  173. package/dist/models/prompt-complexity.js.map +1 -0
  174. package/dist/models/provider-specs.d.ts.map +1 -0
  175. package/dist/models/provider-specs.js.map +1 -0
  176. package/dist/policy/approvals-execution.d.ts.map +1 -0
  177. package/dist/policy/approvals-execution.js.map +1 -0
  178. package/dist/{batch-runs.d.ts → policy/batch-runs.d.ts} +5 -1
  179. package/dist/policy/batch-runs.d.ts.map +1 -0
  180. package/dist/{batch-runs.js → policy/batch-runs.js} +10 -7
  181. package/dist/policy/batch-runs.js.map +1 -0
  182. package/dist/policy/capability-env.d.ts.map +1 -0
  183. package/dist/policy/capability-env.js.map +1 -0
  184. package/dist/policy/capability-secrets.d.ts.map +1 -0
  185. package/dist/policy/capability-secrets.js.map +1 -0
  186. package/dist/{card-status.d.ts → policy/card-status.d.ts} +2 -2
  187. package/dist/policy/card-status.d.ts.map +1 -0
  188. package/dist/{card-status.js → policy/card-status.js} +1 -5
  189. package/dist/policy/card-status.js.map +1 -0
  190. package/dist/{command-classes.d.ts → policy/command-classes.d.ts} +6 -2
  191. package/dist/policy/command-classes.d.ts.map +1 -0
  192. package/dist/{command-classes.js → policy/command-classes.js} +48 -11
  193. package/dist/policy/command-classes.js.map +1 -0
  194. package/dist/{command-run.d.ts → policy/command-run.d.ts} +1 -1
  195. package/dist/policy/command-run.d.ts.map +1 -0
  196. package/dist/policy/command-run.js.map +1 -0
  197. package/dist/policy/control-scopes.d.ts +16 -0
  198. package/dist/policy/control-scopes.d.ts.map +1 -0
  199. package/dist/policy/control-scopes.js +26 -0
  200. package/dist/policy/control-scopes.js.map +1 -0
  201. package/dist/policy/credential-material.d.ts.map +1 -0
  202. package/dist/policy/credential-material.js.map +1 -0
  203. package/dist/policy/needs-action.d.ts.map +1 -0
  204. package/dist/policy/needs-action.js.map +1 -0
  205. package/dist/policy/output-fields.d.ts.map +1 -0
  206. package/dist/policy/output-fields.js.map +1 -0
  207. package/dist/policy/overlay-lint.d.ts.map +1 -0
  208. package/dist/policy/overlay-lint.js.map +1 -0
  209. package/dist/policy/owner-ticket.d.ts.map +1 -0
  210. package/dist/{owner-ticket.js → policy/owner-ticket.js} +1 -1
  211. package/dist/policy/owner-ticket.js.map +1 -0
  212. package/dist/{safety-policy.d.ts → policy/safety-policy.d.ts} +6 -5
  213. package/dist/policy/safety-policy.d.ts.map +1 -0
  214. package/dist/{safety-policy.js → policy/safety-policy.js} +12 -12
  215. package/dist/policy/safety-policy.js.map +1 -0
  216. package/dist/policy/search-globs.d.ts.map +1 -0
  217. package/dist/policy/search-globs.js.map +1 -0
  218. package/dist/protocol/container-requirements.d.ts +20 -0
  219. package/dist/protocol/container-requirements.d.ts.map +1 -0
  220. package/dist/protocol/container-requirements.js +23 -0
  221. package/dist/protocol/container-requirements.js.map +1 -0
  222. package/dist/{host-protocol.d.ts → protocol/host-protocol.d.ts} +1 -0
  223. package/dist/protocol/host-protocol.d.ts.map +1 -0
  224. package/dist/{host-protocol.js → protocol/host-protocol.js} +1 -0
  225. package/dist/protocol/host-protocol.js.map +1 -0
  226. package/dist/protocol/ingress-contract.d.ts.map +1 -0
  227. package/dist/{ingress-contract.js → protocol/ingress-contract.js} +1 -1
  228. package/dist/protocol/ingress-contract.js.map +1 -0
  229. package/dist/protocol/ingress-protocol.d.ts.map +1 -0
  230. package/dist/protocol/ingress-protocol.js.map +1 -0
  231. package/dist/protocol/listener-protocol.d.ts.map +1 -0
  232. package/dist/{listener-protocol.js → protocol/listener-protocol.js} +1 -1
  233. package/dist/protocol/listener-protocol.js.map +1 -0
  234. package/dist/{peer-dial.d.ts → protocol/peer-dial.d.ts} +4 -1
  235. package/dist/protocol/peer-dial.d.ts.map +1 -0
  236. package/dist/{peer-dial.js → protocol/peer-dial.js} +51 -10
  237. package/dist/protocol/peer-dial.js.map +1 -0
  238. package/dist/protocol/peer-mcp-server.d.ts.map +1 -0
  239. package/dist/protocol/peer-mcp-server.js.map +1 -0
  240. package/dist/protocol/request-id.d.ts.map +1 -0
  241. package/dist/protocol/request-id.js.map +1 -0
  242. package/dist/protocol/routes.d.ts.map +1 -0
  243. package/dist/protocol/routes.js.map +1 -0
  244. package/dist/{runner-protocol.d.ts → protocol/runner-protocol.d.ts} +1 -0
  245. package/dist/protocol/runner-protocol.d.ts.map +1 -0
  246. package/dist/{runner-protocol.js → protocol/runner-protocol.js} +2 -1
  247. package/dist/protocol/runner-protocol.js.map +1 -0
  248. package/dist/protocol/sse.d.ts.map +1 -0
  249. package/dist/protocol/sse.js.map +1 -0
  250. package/dist/{terminal-protocol.d.ts → protocol/terminal-protocol.d.ts} +1 -3
  251. package/dist/protocol/terminal-protocol.d.ts.map +1 -0
  252. package/dist/protocol/terminal-protocol.js.map +1 -0
  253. package/dist/protocol/webext-links.d.ts.map +1 -0
  254. package/dist/protocol/webext-links.js.map +1 -0
  255. package/dist/{webext-protocol.d.ts → protocol/webext-protocol.d.ts} +1 -0
  256. package/dist/protocol/webext-protocol.d.ts.map +1 -0
  257. package/dist/{webext-protocol.js → protocol/webext-protocol.js} +1 -0
  258. package/dist/protocol/webext-protocol.js.map +1 -0
  259. package/dist/schemas/activity.d.ts +2 -0
  260. package/dist/schemas/activity.d.ts.map +1 -1
  261. package/dist/schemas/activity.js +4 -0
  262. package/dist/schemas/activity.js.map +1 -1
  263. package/dist/schemas/agent.d.ts +16 -4
  264. package/dist/schemas/agent.d.ts.map +1 -1
  265. package/dist/schemas/agent.js +21 -4
  266. package/dist/schemas/agent.js.map +1 -1
  267. package/dist/schemas/agents.d.ts +17 -4
  268. package/dist/schemas/agents.d.ts.map +1 -1
  269. package/dist/schemas/agents.js +15 -4
  270. package/dist/schemas/agents.js.map +1 -1
  271. package/dist/schemas/approvals.d.ts.map +1 -1
  272. package/dist/schemas/approvals.js.map +1 -1
  273. package/dist/schemas/automations.d.ts +54 -28
  274. package/dist/schemas/automations.d.ts.map +1 -1
  275. package/dist/schemas/automations.js +26 -8
  276. package/dist/schemas/automations.js.map +1 -1
  277. package/dist/schemas/capabilities.d.ts +0 -8
  278. package/dist/schemas/capabilities.d.ts.map +1 -1
  279. package/dist/schemas/capabilities.js +0 -4
  280. package/dist/schemas/capabilities.js.map +1 -1
  281. package/dist/schemas/ci.d.ts +10 -0
  282. package/dist/schemas/ci.d.ts.map +1 -1
  283. package/dist/schemas/ci.js +9 -1
  284. package/dist/schemas/ci.js.map +1 -1
  285. package/dist/schemas/codebase-health.d.ts.map +1 -1
  286. package/dist/schemas/codebase-health.js.map +1 -1
  287. package/dist/schemas/devices.d.ts +92 -0
  288. package/dist/schemas/devices.d.ts.map +1 -1
  289. package/dist/schemas/devices.js +12 -1
  290. package/dist/schemas/devices.js.map +1 -1
  291. package/dist/schemas/engines.d.ts.map +1 -1
  292. package/dist/schemas/engines.js.map +1 -1
  293. package/dist/schemas/environment.d.ts.map +1 -1
  294. package/dist/schemas/environment.js.map +1 -1
  295. package/dist/schemas/exit.d.ts.map +1 -1
  296. package/dist/schemas/exit.js.map +1 -1
  297. package/dist/schemas/extension-updates.d.ts.map +1 -1
  298. package/dist/schemas/extension-updates.js.map +1 -1
  299. package/dist/schemas/git-history.d.ts.map +1 -1
  300. package/dist/schemas/git-history.js.map +1 -1
  301. package/dist/schemas/git.d.ts +80 -16
  302. package/dist/schemas/git.d.ts.map +1 -1
  303. package/dist/schemas/git.js +37 -25
  304. package/dist/schemas/git.js.map +1 -1
  305. package/dist/schemas/history.d.ts.map +1 -1
  306. package/dist/schemas/history.js.map +1 -1
  307. package/dist/schemas/hosts.d.ts.map +1 -1
  308. package/dist/schemas/hosts.js.map +1 -1
  309. package/dist/schemas/inventory.d.ts.map +1 -1
  310. package/dist/schemas/inventory.js.map +1 -1
  311. package/dist/schemas/issues.d.ts +0 -1
  312. package/dist/schemas/issues.d.ts.map +1 -1
  313. package/dist/schemas/issues.js +0 -1
  314. package/dist/schemas/issues.js.map +1 -1
  315. package/dist/schemas/logs.d.ts.map +1 -1
  316. package/dist/schemas/logs.js.map +1 -1
  317. package/dist/schemas/loops.d.ts.map +1 -1
  318. package/dist/schemas/loops.js +1 -1
  319. package/dist/schemas/loops.js.map +1 -1
  320. package/dist/schemas/maintenance.d.ts.map +1 -1
  321. package/dist/schemas/maintenance.js.map +1 -1
  322. package/dist/schemas/marketplace.d.ts +0 -4
  323. package/dist/schemas/marketplace.d.ts.map +1 -1
  324. package/dist/schemas/panels.d.ts.map +1 -1
  325. package/dist/schemas/panels.js.map +1 -1
  326. package/dist/schemas/personas.d.ts +2 -1
  327. package/dist/schemas/personas.d.ts.map +1 -1
  328. package/dist/schemas/personas.js +6 -2
  329. package/dist/schemas/personas.js.map +1 -1
  330. package/dist/schemas/plan-limits.d.ts +2 -4
  331. package/dist/schemas/plan-limits.d.ts.map +1 -1
  332. package/dist/schemas/plan-limits.js +5 -8
  333. package/dist/schemas/plan-limits.js.map +1 -1
  334. package/dist/schemas/ports.d.ts.map +1 -1
  335. package/dist/schemas/ports.js.map +1 -1
  336. package/dist/schemas/provider-oauth.d.ts.map +1 -1
  337. package/dist/schemas/provider-oauth.js.map +1 -1
  338. package/dist/schemas/provider-subscriptions.d.ts +1 -1
  339. package/dist/schemas/provider-subscriptions.d.ts.map +1 -1
  340. package/dist/schemas/provider-subscriptions.js +1 -1
  341. package/dist/schemas/provider-subscriptions.js.map +1 -1
  342. package/dist/schemas/public.d.ts.map +1 -1
  343. package/dist/schemas/public.js.map +1 -1
  344. package/dist/schemas/push.d.ts.map +1 -1
  345. package/dist/schemas/push.js.map +1 -1
  346. package/dist/schemas/secrets.d.ts.map +1 -1
  347. package/dist/schemas/secrets.js.map +1 -1
  348. package/dist/schemas/settings.d.ts +11 -9
  349. package/dist/schemas/settings.d.ts.map +1 -1
  350. package/dist/schemas/settings.js +22 -7
  351. package/dist/schemas/settings.js.map +1 -1
  352. package/dist/schemas/share.d.ts.map +1 -1
  353. package/dist/schemas/share.js.map +1 -1
  354. package/dist/schemas/shared.d.ts +4 -0
  355. package/dist/schemas/shared.d.ts.map +1 -1
  356. package/dist/schemas/shared.js +3 -0
  357. package/dist/schemas/shared.js.map +1 -1
  358. package/dist/schemas/system.d.ts +6 -0
  359. package/dist/schemas/system.d.ts.map +1 -1
  360. package/dist/schemas/system.js +10 -0
  361. package/dist/schemas/system.js.map +1 -1
  362. package/dist/schemas/terminal.d.ts.map +1 -1
  363. package/dist/schemas/terminal.js.map +1 -1
  364. package/dist/schemas/usage.d.ts.map +1 -1
  365. package/dist/schemas/usage.js.map +1 -1
  366. package/dist/schemas/vpn.d.ts.map +1 -1
  367. package/dist/schemas/vpn.js.map +1 -1
  368. package/dist/schemas/webext.d.ts.map +1 -1
  369. package/dist/schemas/webext.js.map +1 -1
  370. package/dist/schemas/workflows.d.ts +66 -9
  371. package/dist/schemas/workflows.d.ts.map +1 -1
  372. package/dist/schemas/workflows.js +6 -5
  373. package/dist/schemas/workflows.js.map +1 -1
  374. package/dist/schemas/workspace-repos.d.ts.map +1 -1
  375. package/dist/schemas/workspace-repos.js.map +1 -1
  376. package/dist/schemas/workspace-search.d.ts.map +1 -1
  377. package/dist/schemas/workspace-search.js.map +1 -1
  378. package/dist/schemas/workspace-setup.d.ts.map +1 -1
  379. package/dist/schemas/workspace-setup.js.map +1 -1
  380. package/dist/schemas/workspace-tree.d.ts.map +1 -1
  381. package/dist/schemas/workspace-tree.js.map +1 -1
  382. package/dist/state/arrival.d.ts.map +1 -0
  383. package/dist/{arrival.js → state/arrival.js} +1 -1
  384. package/dist/state/arrival.js.map +1 -0
  385. package/dist/state/contract-lock.d.ts.map +1 -0
  386. package/dist/{contract-lock.js → state/contract-lock.js} +1 -1
  387. package/dist/state/contract-lock.js.map +1 -0
  388. package/dist/{definition.d.ts → state/definition.d.ts} +21 -17
  389. package/dist/state/definition.d.ts.map +1 -0
  390. package/dist/{definition.js → state/definition.js} +4 -4
  391. package/dist/state/definition.js.map +1 -0
  392. package/dist/state/history-state.d.ts.map +1 -0
  393. package/dist/{history-state.js → state/history-state.js} +1 -0
  394. package/dist/state/history-state.js.map +1 -0
  395. package/dist/state/runtime-state.d.ts.map +1 -0
  396. package/dist/state/runtime-state.js.map +1 -0
  397. package/dist/state/starter.d.ts.map +1 -0
  398. package/dist/state/starter.js.map +1 -0
  399. package/dist/state/state-portability.d.ts.map +1 -0
  400. package/dist/state/state-portability.js.map +1 -0
  401. package/dist/state/versions.d.ts.map +1 -0
  402. package/dist/state/versions.js.map +1 -0
  403. package/dist/{workspace-state.d.ts → state/workspace-state.d.ts} +8 -0
  404. package/dist/state/workspace-state.d.ts.map +1 -0
  405. package/dist/{workspace-state.js → state/workspace-state.js} +25 -0
  406. package/dist/state/workspace-state.js.map +1 -0
  407. package/dist/{documents.d.ts → text/documents.d.ts} +1 -1
  408. package/dist/text/documents.d.ts.map +1 -0
  409. package/dist/{documents.js → text/documents.js} +1 -1
  410. package/dist/text/documents.js.map +1 -0
  411. package/dist/text/embed.d.ts.map +1 -0
  412. package/dist/text/embed.js.map +1 -0
  413. package/dist/text/mentions.d.ts.map +1 -0
  414. package/dist/text/mentions.js.map +1 -0
  415. package/dist/text/model-answer.d.ts +3 -0
  416. package/dist/text/model-answer.d.ts.map +1 -0
  417. package/dist/text/model-answer.js +3 -0
  418. package/dist/text/model-answer.js.map +1 -0
  419. package/dist/text/path-refs.d.ts.map +1 -0
  420. package/dist/text/path-refs.js.map +1 -0
  421. package/dist/{shell-regions.d.ts → text/shell-regions.d.ts} +1 -1
  422. package/dist/text/shell-regions.d.ts.map +1 -0
  423. package/dist/text/shell-regions.js.map +1 -0
  424. package/dist/text/title.d.ts.map +1 -0
  425. package/dist/text/title.js.map +1 -0
  426. package/dist/{transcript-fold.d.ts → text/transcript-fold.d.ts} +2 -1
  427. package/dist/text/transcript-fold.d.ts.map +1 -0
  428. package/dist/{transcript-fold.js → text/transcript-fold.js} +2 -16
  429. package/dist/text/transcript-fold.js.map +1 -0
  430. package/dist/text/whisper.d.ts +3 -0
  431. package/dist/text/whisper.d.ts.map +1 -0
  432. package/dist/text/whisper.js +11 -0
  433. package/dist/text/whisper.js.map +1 -0
  434. package/dist/{workflow-faults.d.ts → text/workflow-faults.d.ts} +1 -1
  435. package/dist/text/workflow-faults.d.ts.map +1 -0
  436. package/dist/{workflow-faults.js → text/workflow-faults.js} +1 -1
  437. package/dist/text/workflow-faults.js.map +1 -0
  438. package/package.json +70 -70
  439. package/src/chores/chores.test.ts +4 -10
  440. package/src/chores/chores.ts +148 -392
  441. package/src/chores/digest.ts +8 -28
  442. package/src/chores/extension-update.ts +3 -8
  443. package/src/chores/fix-deps.ts +4 -18
  444. package/src/chores/index.ts +2 -2
  445. package/src/chores/probes.test.ts +7 -43
  446. package/src/chores/probes.ts +62 -167
  447. package/src/chores/prompt.ts +10 -34
  448. package/src/chores/stack.test.ts +6 -45
  449. package/src/chores/stack.ts +27 -118
  450. package/src/chores/verdict.test.ts +101 -80
  451. package/src/chores/verdict.ts +54 -99
  452. package/src/contracts/accounts.contract.ts +4 -19
  453. package/src/contracts/agent.contract.ts +7 -22
  454. package/src/contracts/agents.contract.ts +25 -71
  455. package/src/contracts/automations.contract.ts +14 -30
  456. package/src/contracts/capabilities.contract.ts +8 -35
  457. package/src/contracts/chores.contract.ts +4 -15
  458. package/src/contracts/endpoints.contract.ts +5 -22
  459. package/src/contracts/exit.contract.ts +7 -30
  460. package/src/contracts/extensions.contract.ts +8 -30
  461. package/src/contracts/git.contract.ts +25 -49
  462. package/src/contracts/host.contract.ts +9 -44
  463. package/src/contracts/intentic.contract.ts +1 -1
  464. package/src/contracts/logs.contract.ts +3 -13
  465. package/src/contracts/loops.contract.ts +9 -40
  466. package/src/contracts/personas.contract.ts +10 -35
  467. package/src/contracts/providers.contract.ts +4 -17
  468. package/src/contracts/runner.contract.ts +12 -39
  469. package/src/contracts/safety.contract.ts +5 -14
  470. package/src/contracts/secrets.contract.ts +4 -22
  471. package/src/contracts/sessions.contract.ts +1 -1
  472. package/src/contracts/settings.contract.ts +4 -10
  473. package/src/contracts/share.contract.ts +3 -9
  474. package/src/contracts/skills.contract.ts +21 -19
  475. package/src/contracts/system.contract.ts +26 -52
  476. package/src/contracts/usage.contract.ts +7 -21
  477. package/src/contracts/vpn.contract.ts +9 -16
  478. package/src/contracts/webext.contract.ts +9 -25
  479. package/src/contracts/workflows.contract.ts +34 -58
  480. package/src/contracts/workspace.contract.ts +19 -50
  481. package/src/events/agent-events.ts +345 -0
  482. package/src/events/cards.ts +286 -0
  483. package/src/{events.test.ts → events/resume.test.ts} +4 -19
  484. package/src/events/resume.ts +60 -0
  485. package/src/events/system-events.ts +139 -0
  486. package/src/events/transcript.ts +320 -0
  487. package/src/{conversation-ids.test.ts → ids/conversation-ids.test.ts} +25 -13
  488. package/src/ids/conversation-ids.ts +178 -0
  489. package/src/ids/hostnames.ts +129 -0
  490. package/src/ids/session-names.ts +29 -0
  491. package/src/ids/share-paths.ts +43 -0
  492. package/src/{tunnel-ids.test.ts → ids/tunnel-ids.test.ts} +1 -14
  493. package/src/ids/tunnel-ids.ts +29 -0
  494. package/src/index.ts +71 -87
  495. package/src/{agent-catalog.test.ts → models/agent-catalog.test.ts} +19 -93
  496. package/src/models/agent-catalog.ts +174 -0
  497. package/src/models/agent-runtimes.ts +201 -0
  498. package/src/models/capability-ledger.test.ts +84 -0
  499. package/src/{fast-tier.test.ts → models/fast-tier.test.ts} +7 -18
  500. package/src/models/fast-tier.ts +36 -0
  501. package/src/{model-order.test.ts → models/model-order.test.ts} +54 -40
  502. package/src/models/model-order.ts +171 -0
  503. package/src/{model-pins.test.ts → models/model-pins.test.ts} +12 -46
  504. package/src/models/model-pins.ts +57 -0
  505. package/src/models/model-roles.test.ts +38 -0
  506. package/src/models/model-roles.ts +180 -0
  507. package/src/{plan-pools.test.ts → models/plan-pools.test.ts} +6 -11
  508. package/src/models/plan-pools.ts +65 -0
  509. package/src/{prompt-complexity.test.ts → models/prompt-complexity.test.ts} +8 -60
  510. package/src/models/prompt-complexity.ts +215 -0
  511. package/src/{provider-specs.test.ts → models/provider-specs.test.ts} +18 -47
  512. package/src/models/provider-specs.ts +272 -0
  513. package/src/policy/approvals-execution.ts +58 -0
  514. package/src/{batch-runs.test.ts → policy/batch-runs.test.ts} +4 -20
  515. package/src/policy/batch-runs.ts +137 -0
  516. package/src/policy/capability-secrets.ts +5 -0
  517. package/src/{card-status.ts → policy/card-status.ts} +11 -26
  518. package/src/{command-classes.test.ts → policy/command-classes.test.ts} +11 -118
  519. package/src/policy/command-classes.ts +395 -0
  520. package/src/policy/command-run.ts +65 -0
  521. package/src/policy/control-scopes.ts +38 -0
  522. package/src/{credential-material.test.ts → policy/credential-material.test.ts} +4 -26
  523. package/src/policy/credential-material.ts +91 -0
  524. package/src/policy/needs-action.ts +5 -0
  525. package/src/policy/output-fields.ts +86 -0
  526. package/src/policy/overlay-lint.ts +100 -0
  527. package/src/{owner-ticket.test.ts → policy/owner-ticket.test.ts} +1 -1
  528. package/src/{owner-ticket.ts → policy/owner-ticket.ts} +9 -31
  529. package/src/policy/safety-policy.test.ts +84 -0
  530. package/src/policy/safety-policy.ts +142 -0
  531. package/src/policy/search-globs.ts +60 -0
  532. package/src/protocol/container-requirements.test.ts +72 -0
  533. package/src/protocol/container-requirements.ts +58 -0
  534. package/src/protocol/host-protocol.ts +29 -0
  535. package/src/protocol/ingress-contract.ts +103 -0
  536. package/src/{ingress-protocol.test.ts → protocol/ingress-protocol.test.ts} +25 -90
  537. package/src/protocol/ingress-protocol.ts +441 -0
  538. package/src/protocol/listener-protocol.ts +75 -0
  539. package/src/{peer-dial.test.ts → protocol/peer-dial.test.ts} +52 -1
  540. package/src/protocol/peer-dial.ts +207 -0
  541. package/src/{peer-mcp-server.ts → protocol/peer-mcp-server.ts} +16 -41
  542. package/src/protocol/request-id.ts +5 -0
  543. package/src/{routes.test.ts → protocol/routes.test.ts} +14 -22
  544. package/src/protocol/routes.ts +159 -0
  545. package/src/protocol/runner-protocol.ts +197 -0
  546. package/src/protocol/terminal-protocol.ts +13 -0
  547. package/src/protocol/webext-links.ts +50 -0
  548. package/src/protocol/webext-protocol.ts +24 -0
  549. package/src/schemas/activity.ts +22 -30
  550. package/src/schemas/agent.ts +130 -238
  551. package/src/schemas/agents.ts +165 -483
  552. package/src/schemas/approvals.ts +23 -71
  553. package/src/schemas/automations.ts +142 -250
  554. package/src/schemas/capabilities.ts +127 -414
  555. package/src/schemas/ci.ts +56 -108
  556. package/src/schemas/codebase-health.ts +7 -11
  557. package/src/schemas/devices.ts +103 -321
  558. package/src/schemas/engines.ts +16 -44
  559. package/src/schemas/environment.ts +41 -91
  560. package/src/schemas/exit.ts +24 -81
  561. package/src/schemas/extension-updates.ts +42 -87
  562. package/src/schemas/git-history.ts +30 -84
  563. package/src/schemas/git.ts +141 -256
  564. package/src/schemas/history.ts +14 -40
  565. package/src/schemas/hosts.ts +9 -15
  566. package/src/schemas/inventory.ts +8 -10
  567. package/src/schemas/issues.ts +66 -134
  568. package/src/schemas/logs.ts +15 -34
  569. package/src/schemas/loops.ts +46 -163
  570. package/src/schemas/maintenance.ts +47 -172
  571. package/src/schemas/panels.ts +20 -45
  572. package/src/schemas/personas.ts +50 -200
  573. package/src/schemas/plan-limits.ts +58 -197
  574. package/src/schemas/ports.ts +14 -32
  575. package/src/schemas/provider-oauth.ts +23 -76
  576. package/src/schemas/provider-subscriptions.ts +4 -13
  577. package/src/schemas/public.ts +4 -15
  578. package/src/schemas/push.ts +8 -36
  579. package/src/schemas/secrets.ts +20 -64
  580. package/src/schemas/settings.ts +182 -602
  581. package/src/schemas/share.ts +14 -32
  582. package/src/schemas/shared.ts +14 -13
  583. package/src/schemas/system.ts +46 -78
  584. package/src/schemas/terminal.ts +41 -120
  585. package/src/schemas/usage.ts +44 -233
  586. package/src/schemas/version-seam.test.ts +9 -26
  587. package/src/schemas/vpn.ts +27 -64
  588. package/src/schemas/webext.ts +22 -53
  589. package/src/schemas/workflows.ts +57 -183
  590. package/src/schemas/workspace-repos.ts +12 -24
  591. package/src/schemas/workspace-search.ts +17 -35
  592. package/src/schemas/workspace-setup.ts +4 -11
  593. package/src/schemas/workspace-tree.ts +32 -91
  594. package/src/state/arrival.ts +109 -0
  595. package/src/state/contract-lock.test.ts +17 -0
  596. package/src/state/contract-lock.ts +49 -0
  597. package/src/state/definition.ts +143 -0
  598. package/src/state/history-state.ts +103 -0
  599. package/src/{runtime-state.test.ts → state/runtime-state.test.ts} +3 -10
  600. package/src/state/runtime-state.ts +63 -0
  601. package/src/state/starter.ts +5 -0
  602. package/src/state/state-portability.ts +27 -0
  603. package/src/state/versions.ts +26 -0
  604. package/src/{workspace-state.test.ts → state/workspace-state.test.ts} +65 -172
  605. package/src/state/workspace-state.ts +669 -0
  606. package/src/{documents.test.ts → text/documents.test.ts} +1 -1
  607. package/src/text/documents.ts +42 -0
  608. package/src/text/embed.ts +132 -0
  609. package/src/text/mentions.ts +21 -0
  610. package/src/text/model-answer.ts +9 -0
  611. package/src/text/path-refs.ts +39 -0
  612. package/src/text/shell-regions.ts +224 -0
  613. package/src/{title.test.ts → text/title.test.ts} +13 -32
  614. package/src/text/title.ts +202 -0
  615. package/src/{transcript-fold.test.ts → text/transcript-fold.test.ts} +5 -83
  616. package/src/{transcript-fold.ts → text/transcript-fold.ts} +65 -170
  617. package/src/text/whisper.test.ts +19 -0
  618. package/src/text/whisper.ts +17 -0
  619. package/src/{workflow-faults.test.ts → text/workflow-faults.test.ts} +6 -24
  620. package/src/{workflow-faults.ts → text/workflow-faults.ts} +20 -60
  621. package/dist/agent-catalog.d.ts.map +0 -1
  622. package/dist/agent-catalog.js.map +0 -1
  623. package/dist/agent-runtimes.d.ts.map +0 -1
  624. package/dist/agent-runtimes.js.map +0 -1
  625. package/dist/approvals-execution.d.ts.map +0 -1
  626. package/dist/approvals-execution.js.map +0 -1
  627. package/dist/arrival.d.ts.map +0 -1
  628. package/dist/arrival.js.map +0 -1
  629. package/dist/batch-runs.d.ts.map +0 -1
  630. package/dist/batch-runs.js.map +0 -1
  631. package/dist/capability-env.d.ts.map +0 -1
  632. package/dist/capability-env.js.map +0 -1
  633. package/dist/capability-secrets.d.ts.map +0 -1
  634. package/dist/capability-secrets.js.map +0 -1
  635. package/dist/card-status.d.ts.map +0 -1
  636. package/dist/card-status.js.map +0 -1
  637. package/dist/command-classes.d.ts.map +0 -1
  638. package/dist/command-classes.js.map +0 -1
  639. package/dist/command-run.d.ts.map +0 -1
  640. package/dist/command-run.js.map +0 -1
  641. package/dist/contract-lock.d.ts.map +0 -1
  642. package/dist/contract-lock.js.map +0 -1
  643. package/dist/conversation-ids.d.ts +0 -4
  644. package/dist/conversation-ids.d.ts.map +0 -1
  645. package/dist/conversation-ids.js.map +0 -1
  646. package/dist/credential-material.d.ts.map +0 -1
  647. package/dist/credential-material.js.map +0 -1
  648. package/dist/definition.d.ts.map +0 -1
  649. package/dist/definition.js.map +0 -1
  650. package/dist/documents.d.ts.map +0 -1
  651. package/dist/documents.js.map +0 -1
  652. package/dist/embed.d.ts.map +0 -1
  653. package/dist/embed.js.map +0 -1
  654. package/dist/events.d.ts +0 -4336
  655. package/dist/events.d.ts.map +0 -1
  656. package/dist/events.js +0 -725
  657. package/dist/events.js.map +0 -1
  658. package/dist/fast-tier.d.ts.map +0 -1
  659. package/dist/fast-tier.js.map +0 -1
  660. package/dist/history-state.d.ts.map +0 -1
  661. package/dist/history-state.js.map +0 -1
  662. package/dist/host-protocol.d.ts.map +0 -1
  663. package/dist/host-protocol.js.map +0 -1
  664. package/dist/hostnames.d.ts.map +0 -1
  665. package/dist/hostnames.js.map +0 -1
  666. package/dist/ingress-contract.d.ts.map +0 -1
  667. package/dist/ingress-contract.js.map +0 -1
  668. package/dist/ingress-protocol.d.ts.map +0 -1
  669. package/dist/ingress-protocol.js.map +0 -1
  670. package/dist/listener-protocol.d.ts.map +0 -1
  671. package/dist/listener-protocol.js.map +0 -1
  672. package/dist/mentions.d.ts.map +0 -1
  673. package/dist/mentions.js.map +0 -1
  674. package/dist/model-order.d.ts.map +0 -1
  675. package/dist/model-order.js.map +0 -1
  676. package/dist/model-pins.d.ts.map +0 -1
  677. package/dist/model-pins.js.map +0 -1
  678. package/dist/model-roles.d.ts.map +0 -1
  679. package/dist/model-roles.js.map +0 -1
  680. package/dist/needs-action.d.ts.map +0 -1
  681. package/dist/needs-action.js.map +0 -1
  682. package/dist/output-fields.d.ts.map +0 -1
  683. package/dist/output-fields.js.map +0 -1
  684. package/dist/overlay-lint.d.ts.map +0 -1
  685. package/dist/overlay-lint.js.map +0 -1
  686. package/dist/owner-ticket.d.ts.map +0 -1
  687. package/dist/owner-ticket.js.map +0 -1
  688. package/dist/path-refs.d.ts.map +0 -1
  689. package/dist/path-refs.js.map +0 -1
  690. package/dist/peer-dial.d.ts.map +0 -1
  691. package/dist/peer-dial.js.map +0 -1
  692. package/dist/peer-mcp-server.d.ts.map +0 -1
  693. package/dist/peer-mcp-server.js.map +0 -1
  694. package/dist/plan-pools.d.ts.map +0 -1
  695. package/dist/plan-pools.js.map +0 -1
  696. package/dist/prompt-complexity.d.ts.map +0 -1
  697. package/dist/prompt-complexity.js.map +0 -1
  698. package/dist/provider-specs.d.ts.map +0 -1
  699. package/dist/provider-specs.js.map +0 -1
  700. package/dist/request-id.d.ts.map +0 -1
  701. package/dist/request-id.js.map +0 -1
  702. package/dist/routes.d.ts.map +0 -1
  703. package/dist/routes.js.map +0 -1
  704. package/dist/runner-protocol.d.ts.map +0 -1
  705. package/dist/runner-protocol.js.map +0 -1
  706. package/dist/runtime-state.d.ts.map +0 -1
  707. package/dist/runtime-state.js.map +0 -1
  708. package/dist/safety-policy.d.ts.map +0 -1
  709. package/dist/safety-policy.js.map +0 -1
  710. package/dist/search-globs.d.ts.map +0 -1
  711. package/dist/search-globs.js.map +0 -1
  712. package/dist/session-names.d.ts.map +0 -1
  713. package/dist/session-names.js.map +0 -1
  714. package/dist/share-paths.d.ts.map +0 -1
  715. package/dist/share-paths.js.map +0 -1
  716. package/dist/shell-regions.d.ts.map +0 -1
  717. package/dist/shell-regions.js.map +0 -1
  718. package/dist/sse.d.ts.map +0 -1
  719. package/dist/sse.js.map +0 -1
  720. package/dist/starter.d.ts.map +0 -1
  721. package/dist/starter.js.map +0 -1
  722. package/dist/state-portability.d.ts.map +0 -1
  723. package/dist/state-portability.js.map +0 -1
  724. package/dist/terminal-protocol.d.ts.map +0 -1
  725. package/dist/terminal-protocol.js.map +0 -1
  726. package/dist/title.d.ts.map +0 -1
  727. package/dist/title.js.map +0 -1
  728. package/dist/transcript-fold.d.ts.map +0 -1
  729. package/dist/transcript-fold.js.map +0 -1
  730. package/dist/tunnel-ids.d.ts.map +0 -1
  731. package/dist/tunnel-ids.js.map +0 -1
  732. package/dist/versions.d.ts.map +0 -1
  733. package/dist/versions.js.map +0 -1
  734. package/dist/webext-links.d.ts.map +0 -1
  735. package/dist/webext-links.js.map +0 -1
  736. package/dist/webext-protocol.d.ts.map +0 -1
  737. package/dist/webext-protocol.js.map +0 -1
  738. package/dist/workflow-faults.d.ts.map +0 -1
  739. package/dist/workflow-faults.js.map +0 -1
  740. package/dist/workspace-state.d.ts.map +0 -1
  741. package/dist/workspace-state.js.map +0 -1
  742. package/src/agent-catalog.ts +0 -316
  743. package/src/agent-runtimes.ts +0 -419
  744. package/src/approvals-execution.ts +0 -96
  745. package/src/arrival.ts +0 -160
  746. package/src/batch-runs.ts +0 -188
  747. package/src/capability-ledger.test.ts +0 -140
  748. package/src/capability-secrets.ts +0 -20
  749. package/src/command-classes.ts +0 -617
  750. package/src/command-run.ts +0 -78
  751. package/src/contract-lock.test.ts +0 -23
  752. package/src/contract-lock.ts +0 -66
  753. package/src/conversation-ids.ts +0 -207
  754. package/src/credential-material.ts +0 -181
  755. package/src/definition.ts +0 -207
  756. package/src/documents.ts +0 -67
  757. package/src/embed.ts +0 -164
  758. package/src/events.ts +0 -1870
  759. package/src/fast-tier.ts +0 -72
  760. package/src/history-state.ts +0 -174
  761. package/src/host-protocol.ts +0 -36
  762. package/src/hostnames.ts +0 -180
  763. package/src/ingress-contract.ts +0 -157
  764. package/src/ingress-protocol.ts +0 -625
  765. package/src/listener-protocol.ts +0 -96
  766. package/src/mentions.ts +0 -25
  767. package/src/model-order.ts +0 -262
  768. package/src/model-pins.ts +0 -132
  769. package/src/model-roles.test.ts +0 -52
  770. package/src/model-roles.ts +0 -320
  771. package/src/needs-action.ts +0 -14
  772. package/src/output-fields.ts +0 -111
  773. package/src/overlay-lint.ts +0 -116
  774. package/src/path-refs.ts +0 -59
  775. package/src/peer-dial.ts +0 -163
  776. package/src/plan-pools.ts +0 -92
  777. package/src/prompt-complexity.ts +0 -334
  778. package/src/provider-specs.ts +0 -432
  779. package/src/request-id.ts +0 -41
  780. package/src/routes.ts +0 -219
  781. package/src/runner-protocol.ts +0 -239
  782. package/src/runtime-state.ts +0 -140
  783. package/src/safety-policy.test.ts +0 -88
  784. package/src/safety-policy.ts +0 -258
  785. package/src/search-globs.ts +0 -76
  786. package/src/session-names.ts +0 -44
  787. package/src/share-paths.ts +0 -68
  788. package/src/shell-regions.ts +0 -289
  789. package/src/starter.ts +0 -13
  790. package/src/state-portability.ts +0 -56
  791. package/src/terminal-protocol.ts +0 -16
  792. package/src/title.ts +0 -267
  793. package/src/tunnel-ids.ts +0 -57
  794. package/src/versions.ts +0 -48
  795. package/src/webext-links.ts +0 -90
  796. package/src/webext-protocol.ts +0 -27
  797. package/src/workspace-state.ts +0 -1090
  798. /package/dist/{hostnames.d.ts → ids/hostnames.d.ts} +0 -0
  799. /package/dist/{hostnames.js → ids/hostnames.js} +0 -0
  800. /package/dist/{session-names.d.ts → ids/session-names.d.ts} +0 -0
  801. /package/dist/{session-names.js → ids/session-names.js} +0 -0
  802. /package/dist/{share-paths.d.ts → ids/share-paths.d.ts} +0 -0
  803. /package/dist/{share-paths.js → ids/share-paths.js} +0 -0
  804. /package/dist/{agent-catalog.js → models/agent-catalog.js} +0 -0
  805. /package/dist/{agent-runtimes.d.ts → models/agent-runtimes.d.ts} +0 -0
  806. /package/dist/{agent-runtimes.js → models/agent-runtimes.js} +0 -0
  807. /package/dist/{fast-tier.js → models/fast-tier.js} +0 -0
  808. /package/dist/{model-order.d.ts → models/model-order.d.ts} +0 -0
  809. /package/dist/{model-pins.js → models/model-pins.js} +0 -0
  810. /package/dist/{plan-pools.js → models/plan-pools.js} +0 -0
  811. /package/dist/{prompt-complexity.d.ts → models/prompt-complexity.d.ts} +0 -0
  812. /package/dist/{prompt-complexity.js → models/prompt-complexity.js} +0 -0
  813. /package/dist/{provider-specs.d.ts → models/provider-specs.d.ts} +0 -0
  814. /package/dist/{provider-specs.js → models/provider-specs.js} +0 -0
  815. /package/dist/{approvals-execution.d.ts → policy/approvals-execution.d.ts} +0 -0
  816. /package/dist/{approvals-execution.js → policy/approvals-execution.js} +0 -0
  817. /package/dist/{capability-env.d.ts → policy/capability-env.d.ts} +0 -0
  818. /package/dist/{capability-env.js → policy/capability-env.js} +0 -0
  819. /package/dist/{capability-secrets.d.ts → policy/capability-secrets.d.ts} +0 -0
  820. /package/dist/{capability-secrets.js → policy/capability-secrets.js} +0 -0
  821. /package/dist/{command-run.js → policy/command-run.js} +0 -0
  822. /package/dist/{credential-material.d.ts → policy/credential-material.d.ts} +0 -0
  823. /package/dist/{credential-material.js → policy/credential-material.js} +0 -0
  824. /package/dist/{needs-action.d.ts → policy/needs-action.d.ts} +0 -0
  825. /package/dist/{needs-action.js → policy/needs-action.js} +0 -0
  826. /package/dist/{output-fields.d.ts → policy/output-fields.d.ts} +0 -0
  827. /package/dist/{output-fields.js → policy/output-fields.js} +0 -0
  828. /package/dist/{overlay-lint.d.ts → policy/overlay-lint.d.ts} +0 -0
  829. /package/dist/{overlay-lint.js → policy/overlay-lint.js} +0 -0
  830. /package/dist/{owner-ticket.d.ts → policy/owner-ticket.d.ts} +0 -0
  831. /package/dist/{search-globs.d.ts → policy/search-globs.d.ts} +0 -0
  832. /package/dist/{search-globs.js → policy/search-globs.js} +0 -0
  833. /package/dist/{ingress-contract.d.ts → protocol/ingress-contract.d.ts} +0 -0
  834. /package/dist/{ingress-protocol.d.ts → protocol/ingress-protocol.d.ts} +0 -0
  835. /package/dist/{ingress-protocol.js → protocol/ingress-protocol.js} +0 -0
  836. /package/dist/{listener-protocol.d.ts → protocol/listener-protocol.d.ts} +0 -0
  837. /package/dist/{peer-mcp-server.d.ts → protocol/peer-mcp-server.d.ts} +0 -0
  838. /package/dist/{peer-mcp-server.js → protocol/peer-mcp-server.js} +0 -0
  839. /package/dist/{request-id.d.ts → protocol/request-id.d.ts} +0 -0
  840. /package/dist/{request-id.js → protocol/request-id.js} +0 -0
  841. /package/dist/{routes.d.ts → protocol/routes.d.ts} +0 -0
  842. /package/dist/{routes.js → protocol/routes.js} +0 -0
  843. /package/dist/{sse.d.ts → protocol/sse.d.ts} +0 -0
  844. /package/dist/{sse.js → protocol/sse.js} +0 -0
  845. /package/dist/{terminal-protocol.js → protocol/terminal-protocol.js} +0 -0
  846. /package/dist/{webext-links.d.ts → protocol/webext-links.d.ts} +0 -0
  847. /package/dist/{webext-links.js → protocol/webext-links.js} +0 -0
  848. /package/dist/{arrival.d.ts → state/arrival.d.ts} +0 -0
  849. /package/dist/{contract-lock.d.ts → state/contract-lock.d.ts} +0 -0
  850. /package/dist/{history-state.d.ts → state/history-state.d.ts} +0 -0
  851. /package/dist/{runtime-state.d.ts → state/runtime-state.d.ts} +0 -0
  852. /package/dist/{runtime-state.js → state/runtime-state.js} +0 -0
  853. /package/dist/{starter.d.ts → state/starter.d.ts} +0 -0
  854. /package/dist/{starter.js → state/starter.js} +0 -0
  855. /package/dist/{state-portability.d.ts → state/state-portability.d.ts} +0 -0
  856. /package/dist/{state-portability.js → state/state-portability.js} +0 -0
  857. /package/dist/{versions.d.ts → state/versions.d.ts} +0 -0
  858. /package/dist/{versions.js → state/versions.js} +0 -0
  859. /package/dist/{embed.d.ts → text/embed.d.ts} +0 -0
  860. /package/dist/{embed.js → text/embed.js} +0 -0
  861. /package/dist/{mentions.d.ts → text/mentions.d.ts} +0 -0
  862. /package/dist/{mentions.js → text/mentions.js} +0 -0
  863. /package/dist/{path-refs.d.ts → text/path-refs.d.ts} +0 -0
  864. /package/dist/{path-refs.js → text/path-refs.js} +0 -0
  865. /package/dist/{shell-regions.js → text/shell-regions.js} +0 -0
  866. /package/dist/{title.d.ts → text/title.d.ts} +0 -0
  867. /package/dist/{title.js → text/title.js} +0 -0
  868. /package/src/{hostnames.test.ts → ids/hostnames.test.ts} +0 -0
  869. /package/src/{share-paths.test.ts → ids/share-paths.test.ts} +0 -0
  870. /package/src/{capability-env.ts → policy/capability-env.ts} +0 -0
  871. /package/src/{overlay-lint.test.ts → policy/overlay-lint.test.ts} +0 -0
  872. /package/src/{search-globs.test.ts → policy/search-globs.test.ts} +0 -0
  873. /package/src/{ingress-contract.test.ts → protocol/ingress-contract.test.ts} +0 -0
  874. /package/src/{peer-mcp-server.test.ts → protocol/peer-mcp-server.test.ts} +0 -0
  875. /package/src/{sse.ts → protocol/sse.ts} +0 -0
  876. /package/src/{versions.test.ts → state/versions.test.ts} +0 -0
  877. /package/src/{embed.test.ts → text/embed.test.ts} +0 -0
  878. /package/src/{mentions.test.ts → text/mentions.test.ts} +0 -0
  879. /package/src/{path-refs.test.ts → text/path-refs.test.ts} +0 -0
@@ -1,1090 +0,0 @@
1
- import { STATE_DIR } from "@intentic/constants";
2
- import type { FileContribution } from "@intentic/extension-manifest";
3
- import type { StateFile } from "./state-portability.js";
4
-
5
- /* WHICH WORKSPACE FILE BACKS WHICH CORE VIEW, one declaration, read by both sides of the wire.
6
- *
7
- * The daemon's own state lives under `<workspace>/.intentic/`, the agent edits it out-of-band with its file
8
- * tools, and the file watcher pushes every change as a `workspaceChanged` batch. Turning those paths back into
9
- * "and therefore this view is stale" used to be a hand-written table in the BROWSER (web's systemEventRouting),
10
- * maintained separately from the paths the daemon actually writes (composition.ts), two lists of the same
11
- * fact, in two packages, with nothing tying them together.
12
- *
13
- * They drifted, exactly as that shape always does. The approvals queue is written by the AGENT (the approvals
14
- * skill puts a file there) and rendered by the Approvals view, but it was never added to the browser's table,
15
- * so a proposal appearing on disk while the owner watched the page changed nothing until they refocused the
16
- * tab. Extension settings and the members list were missing for the same reason; writing them out is what
17
- * showed that neither is an approvals-shaped hole, see their entries.
18
- *
19
- * So the binding is declared HERE, once, in the package both the daemon and the browser already import, and
20
- * each side derives what it needs: the daemon builds its store paths from `path`, the browser builds its
21
- * invalidation table from `invalidates`. Adding a manifest without saying what it makes stale is now a change
22
- * to one visible list rather than an omission in a file nobody edits, and `workspace-state.test.ts` fails when
23
- * a daemon store names a `.intentic` path this list doesn't carry.
24
- *
25
- * This mirrors what routes.ts does for the route surface ("nothing is generated and nothing is hand-maintained")
26
- * one layer over: the same refusal to keep the same knowledge in two places.
27
- *
28
- * EXTENSIONS declare their own half in their manifest (`contributes.files`, @intentic/extension-api), in the same
29
- * two fields, and the browser unions the two lists, see staleQueryKeys. That split is what this table is FOR:
30
- * before it existed the core enumeration had to carry `automations` and `automation-approvals`, query keys owned
31
- * by the automations extension, because the extension had no way to say so itself. A key belongs to whoever
32
- * queries it. */
33
-
34
- /* A core entry is an extension's `contributes.files` entry plus the two things only the core list needs: the
35
- * right to declare NO invalidations (for a daemon-owned file, the answer more often than not), and a
36
- * portability class, because the daemon's own state is what an environment export has to reason about.
37
- *
38
- * `path` is workspace-root-relative, forward-slash, the space `workspaceChanged` paths arrive in. Matching is
39
- * by PREFIX, which lets one entry cover three shapes without a second matching rule:
40
- * - an exact file `.intentic/config/settings.json`
41
- * - a directory `.intentic/config/approvals/` (one file per approval)
42
- * - a name family `.intentic/config/environment.custom.` (…Dockerfile and anything later named beside it)
43
- * A directory entry keeps its trailing slash so it can never prefix-match a sibling file. Entries may NEST,
44
- * see stateFileFor, which resolves the longest match rather than the first. */
45
- export interface WorkspaceStateFile extends StateFile {
46
- /* The browser query keys this file's contents feed. EMPTY is a real answer, not a gap, a file the browser
47
- * renders nothing from, or one deliberately kept off the push path, and `why` says which. Never a prefix
48
- * test over `.intentic/` as a whole: one stray write must not cost every view a refetch, which is the
49
- * amplification that once turned an iq index rebuild into an endless request storm. */
50
- readonly invalidates: readonly string[];
51
- // Why this file has no invalidations, for the entries that declare none. Absent when it has some.
52
- readonly why?: string;
53
- /* Whether this entry is TRACKED by the root repo, the third thing an entry declares, and the one an owner
54
- * sees most directly: a tracked entry gets a diff in the Changes review and a line in `git log`, so a change
55
- * to how this sandbox behaves can be read, reverted, and attributed.
56
- *
57
- * ABSENT IS THE ANSWER FOR ALMOST EVERYTHING, and deliberately so. The root repo excludes `.intentic`
58
- * wholesale and this flag is the only thing that carves an entry back out, so a store added later is
59
- * untracked until someone says otherwise, the same default-deny the `portability` classes are built on, for
60
- * the same reason. An ignore-pattern list would invert it: a credential store added next month would be
61
- * committed on its first write, and nothing would have had to change for that to happen.
62
- *
63
- * WHAT EARNS IT is one question, asked of the entry rather than of its shape: does a change here change what
64
- * this sandbox DOES? Two families answer yes.
65
- * - CONFIGURATION, the small, slow-moving files that decide how the sandbox behaves: settings, personas,
66
- * skills, automations, workflow designs, the environment overlay, which extensions are on.
67
- * - AUTHORED CONTENT WHOSE CONSEQUENCES LEAVE THE SANDBOX, a workspace extension is code that runs in the
68
- * app with a declared permission surface and a backend of its own; a post draft is words that go out
69
- * under the owner's name. Neither is configuration, and reading `versioned` as config-only is what kept
70
- * both of them out: an agent could write, and then run, a whole extension with a diff nowhere, and
71
- * propose a public post that left no trace once declined. The rule was never "is this a setting", it was
72
- * "can this be read, reverted and attributed", and for the two things the AGENT authors on its own,
73
- * that matters more than it does for a file a person edited on purpose.
74
- *
75
- * Two kinds of entry stay out on purpose even though they are `carry` and hold no secret:
76
- * - LEDGERS (workflow runs, loop iterations, thread bookkeeping, permission-usage batches, held-wake
77
- * queues), which are rewritten on a timer or several times per step. Tracking them buries the owner's
78
- * code review under machine noise, one of them is written every few seconds while a browser has the app
79
- * open. A queue is a ledger too: it records that something was ASKED, and is emptied when it is answered.
80
- * - BULK (session transcripts, artifacts), which are hundreds of megabytes of constantly-rewritten
81
- * content. They travel in a bundle; they do not belong in a diff.
82
- * `versioned` is therefore NARROWER than `carry`, and the two answer different questions: carry is "does it
83
- * move to a new sandbox", this is "should a human review it changing". */
84
- readonly versioned?: true;
85
- /* AUTHORED but not configuration, the fourth question an entry can answer, and the narrowest: is this
86
- * human- or agent-written TEXT that a workspace search should surface? Every `versioned` entry already is
87
- * (a setting, a persona, a skill, things the agent is asked to find and edit), so this flag exists only
88
- * for the entries that are authored content without being config: a draft awaiting approval, a staged
89
- * README, an extension the agent wrote in place. Two of those three are now `versioned` as well, which makes
90
- * the flag redundant to `SEARCHABLE_STATE_PATHS` on them and is why it stays anyway: searchability is a
91
- * property of the content, and hanging it on `versioned` would mean a future decision to stop TRACKING a
92
- * draft silently also stopped anyone FINDING one. Everything else under `.intentic` is machine state, and
93
- * `SEARCHABLE_STATE_PATHS` below is what lets the search engine deny the rest BY DEFAULT instead of
94
- * hand-keeping a deny list that goes stale the day a store is added (which is how a 98 kB loop ledger and
95
- * whole third-party extension checkouts ended up ranking in code search). */
96
- readonly authored?: true;
97
- /* WHETHER DESKTOP-SYNC COPIES THIS DOWN, the fifth question, and the one `portability` cannot answer even
98
- * though it looks like it should.
99
- *
100
- * Portability asks whether a piece of state may RESTORE into a different sandbox. Backup asks whether it may
101
- * be COPIED to the owner's own machine so the loss of this sandbox is not the loss of the work. Those read as
102
- * the same question and are not: `members.json` is the clearest case, and its own entry argues the half that
103
- * was already written down, an access list that TRAVELLED would let a source sandbox hand itself the
104
- * target's ownership, which is why it may never be `carry`. None of that reasoning says the owner may not
105
- * hold a copy of who could drive their own sandbox. Conflating the two is what made the sync ignore the state
106
- * dir wholesale, so a sandbox that went away took every persona, skill, draft and transcript with it.
107
- *
108
- * SO IT DERIVES, and this flag exists only to carve out the entry where the derivation is wrong. The default
109
- * (backedUp below) is `carry` plus `identity`: ordinary state and the small records that bind this sandbox to
110
- * its owner. `derived` is excluded for size, it is the caches, the checkouts and the browser profiles, all
111
- * rebuildable and all bulk, and `secret` is excluded because a credential's exposure is the number of
112
- * places it exists, and a laptop is one more place.
113
- *
114
- * `false` is the only value: an entry either accepts the derived answer or opts out of the copy, and there is
115
- * no entry that needs opting IN against its class. Anything opting out says why on the entry. */
116
- readonly backup?: false;
117
- /* WHO BUILDS THIS TREE, when it is not the daemon, an extension, pnpm, another process entirely. Declared
118
- * on the entry because the coverage guard's second direction ("every declared entry is built somewhere in
119
- * the daemon") is only meaningful for entries the daemon owns: one it can never build must say who does, or
120
- * the guard would read the entry as dead. Absent for everything the daemon writes itself. */
121
- readonly outsideWriter?: string;
122
- }
123
-
124
- /* Declared `as const` so the paths survive as literal types (see WorkspaceStatePath below), then published under
125
- * the interface. Both bindings are needed and neither is redundant: the const is the only thing that can produce
126
- * the path union, and every consumer reads entries as `WorkspaceStateFile`, an exact-literal tuple loses the
127
- * optional members (`note`, `why`) on the entries that omit them, which is a worse type for reading than the
128
- * interface it satisfies. One list, two views of it. */
129
- const STATE_FILES = [
130
- /* A capability add/remove recomposes the environment overlay and can add or drop a repo's panel.
131
- *
132
- * SPLIT ALREADY, and this entry's classification had not caught up, which is the whole of what changed here.
133
- * It read `secret` on a claim that had stopped being true: that each entry's `config` carries that
134
- * capability's credential, so the manifest is a secret in full. It does not. capabilities-store.ts's
135
- * withSecretVault keeps credential VALUES off /work entirely, the manifest holds `__intentic_vaulted__`
136
- * where one used to be, reads rehydrate so no caller noticed, and main.ts sweeps a hand-written value out at
137
- * boot. What is left is the SHAPE of a connection: a kind, a URL, a username, a purpose, which permissions a
138
- * connected device was granted.
139
- *
140
- * WHICH KEYS THOSE ARE IS DERIVED, not listed a second time: `echo` already answers "what of this config may
141
- * a browser see", and the credential keys are exactly its complement (capabilities/secret-fields.ts). A kind
142
- * that starts withholding a new field starts vaulting it on the same commit. That is what makes this
143
- * classification a property of the code rather than a promise to re-audit it, the reason the entry can be
144
- * reclassified at all, and the reason a hand-kept "these fields are safe" list could not have earned it.
145
- *
146
- * `carry`, and this is the entry where that earns the most. composeEnvironment reads its Dockerfile fragments
147
- * from here, so a bundle that dropped it arrived on a stock overlay with an import report listing every
148
- * connection to re-add by hand. It now arrives listing them itself, each visibly unconnected and waiting for
149
- * one credential apiece, the shape personas.json has had all along, for the same reason.
150
- *
151
- * `versioned`, which is the point. Connecting this sandbox to a deployment orchestrator, or granting a
152
- * connected device shell and screen control, is the largest change anyone makes to what it can DO, and it
153
- * left a diff nowhere. One consequence worth stating rather than discovering: an identifier that pairs with a
154
- * credential. Komodo's api key beside its api secret, which its own connector card calls "like a database
155
- * user", is echoed, and therefore lands in the diff exactly as a database username would. */
156
- {
157
- path: ".intentic/config/capabilities.json",
158
- invalidates: ["capabilities", "environment", "panels", "manifests"],
159
- portability: "carry",
160
- versioned: true,
161
- },
162
-
163
- /* Which workspace-derived recommendations the owner has said "not needed" to, and the evidence each was
164
- * declined against. It rides the `capabilities` key because the catalog is what changes when one lands, and
165
- * it travels because a decision about what this workspace does NOT need is as much the owner's as the
166
- * connections themselves, an export that dropped it would greet them on the target with the same
167
- * suggestions they had already dismissed. Holds no credential: it is a card name and a file path. */
168
- { path: ".intentic/config/capability-dismissals.json", invalidates: ["capabilities"], portability: "carry", versioned: true },
169
-
170
- /* The secret use ledger, one row per moment the agent's exits spent a stored secret (a `{{secret:name}}`
171
- * reference resolved into a shell command, a value typed into a browser field), joined onto the secrets
172
- * inventory as each entry's "last used" (sandbox's secrets/secret-uses.ts). Holds names and destinations,
173
- * never values, which is why it may `carry`: like the automations' run ledger, a use history is about the
174
- * secrets, and an export that dropped it would arrive claiming none had ever been touched. */
175
- { path: ".intentic/records/secret-uses.json", invalidates: ["secrets"], portability: "carry" },
176
-
177
- /* The wallet's payment ledger, one row per payment attempt that reached policy (sandbox's
178
- * wallet/wallet-ledger.ts): what was paid, to whom, how it settled, with the onchain transaction hash
179
- * when the endpoint stated one. Holds amounts, hosts and addresses, never a credential, the signing key
180
- * never enters the container at all, so it may `carry`: like the secret-use ledger, a spend history is
181
- * about the owner's money, and an export that dropped it would arrive claiming none was ever spent. */
182
- {
183
- path: ".intentic/records/wallet-ledger.json",
184
- invalidates: [],
185
- why: "Rendered through the wallet CLI and the capability card's live status probe, not from a browser query key.",
186
- portability: "carry",
187
- },
188
-
189
- /* The named personas this sandbox shows the outside world, which connected accounts each one speaks for,
190
- * what a session wearing it may do, where it works (PersonaSchema, schemas/personas.ts). It invalidates `capabilities` as well as
191
- * its own key because a card and the accounts it names are read together everywhere they are shown: connect
192
- * a second Reddit and the persona list has a new candidate; remove one and a card points at nothing.
193
- *
194
- * It is `carry`, and that is the whole design rather than an oversight, a card is a NAME and a list of ids,
195
- * never a credential, so it travels to a new sandbox in full while the logins it refers to stay behind. What
196
- * arrives is a workspace that already knows it has a work-reddit and a studio-x, both visibly unconnected,
197
- * each waiting for one sign-in. It was also the FIRST file under .intentic the root repo tracked, and the
198
- * argument it was carved out on, a card is configuration, holds no secret, and belongs in review, is the
199
- * one `versioned` now generalises to the rest of the config slice (personas/personas-store.ts argues it at
200
- * length, and its reasoning is why the flag exists rather than a second hand-kept list). */
201
- { path: ".intentic/config/personas.json", invalidates: ["personas", "capabilities", "manifests"], portability: "carry", versioned: true },
202
-
203
- /* The overlay Dockerfile, four files that a single `.intentic/environment.` prefix used to cover. They are
204
- * split here because they answer PORTABILITY differently while answering invalidation identically, and the
205
- * split is the whole difference between an export that reproduces an environment and one that reproduces a
206
- * stale copy of it:
207
- * - custom is the owner-approved SOURCE OF TRUTH and the only one that must travel;
208
- * - approved is COMPOSED from custom + the capability fragments + this container's base image, and is
209
- * rewritten on the target's first boot, carrying it would ship a FROM naming an image the target may
210
- * not be on (see composeEnvironment's baseImageOf);
211
- * - the proposal and the per-tool drafts under environment.d/ are the agent's pending requests, which the
212
- * owner has not answered yet; they travel so the question survives the move. */
213
- { path: ".intentic/config/environment.custom.Dockerfile", invalidates: ["environment"], portability: "carry", versioned: true },
214
- { path: ".intentic/config/environment.Dockerfile", invalidates: ["environment"], portability: "carry", versioned: true },
215
- { path: ".intentic/config/environment.d/", invalidates: ["environment"], portability: "carry", versioned: true },
216
- {
217
- path: ".intentic/local/environment.approved.Dockerfile",
218
- invalidates: ["environment"],
219
- portability: "derived",
220
- note: "The target composes its own overlay on first boot; rebuild it there to install the tools it names.",
221
- },
222
-
223
- { path: ".intentic/config/settings.json", invalidates: ["settings", "manifests"], portability: "carry", versioned: true },
224
- /* The safety policy the command judge reads before every flagged command (safety-policy.ts).
225
- *
226
- * `carry` and `versioned`, and both matter more here than for any other config file. It is a decision about
227
- * how much an agent may do unasked in THIS workspace, so a fresh sandbox should arrive already governed by
228
- * it rather than by the shipped default; and a change to it is exactly the kind a reviewer should see, since
229
- * "since when did we stop asking about force-pushes" is a question only `git log` can answer. Being prose
230
- * rather than JSON is what makes that diff worth reading.
231
- *
232
- * Absent is a normal state and not an unconfigured one: the daemon falls back to DEFAULT_SAFETY_POLICY,
233
- * which describes the posture the product already had. */
234
- { path: ".intentic/config/safety.md", invalidates: ["safety-policy"], portability: "carry", versioned: true },
235
- /* What the policy above actually decided, newest first, written several times a turn by the command gate.
236
- *
237
- * `derived`, and therefore under `local/` rather than beside the session transcripts in `records/`: it is
238
- * evidence about what ran on THIS machine, bounded and self-trimming, and an export that carried it would
239
- * arrive claiming a fresh sandbox had already judged three hundred commands. The folder is the rule here,
240
- * not a filing preference — the git exclude, the search allow-list and the export bundle all read the
241
- * prefix (see the layout guard in workspace-state.test.ts).
242
- *
243
- * Its own query key rather than the policy's, because the two change at completely different rates and a
244
- * verdict landing must not invalidate the document somebody is editing. */
245
- {
246
- path: ".intentic/local/safety-log.json",
247
- invalidates: ["safety-log"],
248
- portability: "derived",
249
- note: "The target starts its own record of what it decided.",
250
- },
251
- /* Which of the workspace's apps the daemon starts on EVERY boot (scaffold/autostart.ts). The starter-site
252
- * seed writes the first entry; the `autostart` boot step reads it, which is what puts the starter's dev
253
- * server up on a first boot, on a boot over a prewarmed pool volume (where the seed has nothing to do), and
254
- * after every wake of a hosted machine (panels are stopped by a restart, so without this a returning user
255
- * met "isn't running" every time). `carry`: an exported workspace should arrive with the same things
256
- * running. Invalidates nothing: the browser reads what is running off /panels, never off this file. */
257
- {
258
- path: ".intentic/config/autostart.json",
259
- invalidates: [],
260
- why: "The browser reads what is running off /panels; this file only tells the daemon what to start at boot.",
261
- portability: "carry",
262
- versioned: true,
263
- },
264
- /* Which agent commands are heavy enough to take turns, and how many may run at once (the daemon reads it
265
- * per Bash command: platform/heavy-commands.ts).
266
- *
267
- * `carry`, because the answer is a property of the WORKSPACE rather than of this machine: `pnpm test` fans
268
- * out to the same 74 packages wherever the repo is cloned, so a fresh sandbox should arrive already knowing
269
- * which commands to queue rather than rediscovering it by freezing once.
270
- *
271
- * `versioned` for the reason the config slice generally is (personas.json's entry argues it): the file
272
- * changes at human speed, it holds no secret, and a change to it is exactly the kind a reviewer should see
273
- * — raising the limit is a decision about everyone's sessions on that box, and `git log` is the only thing
274
- * that answers "since when have we allowed four of these at once". */
275
- { path: ".intentic/config/heavy-commands.json", invalidates: ["settings"], portability: "carry", versioned: true },
276
- /* THE SCRIPTS THE RULE TABLE RUNS, one file per reader, at the moments settings.json points them at: the
277
- * per-edit linter and byte scan today (`file.edited`), whatever the owner adds beside them tomorrow.
278
- *
279
- * IT IS HERE BECAUSE IT WAS NOT, and the gap was silent. The root repository excludes `.intentic/config/*`
280
- * with one carve-out per tracked entry, derived from this table's `versioned` flags (history.ts
281
- * rootExcludes), so a directory nobody marked is ignored — and an ignored file is invisible to the land.
282
- * The two scripts were written in an agent's worktree; the rules naming them were written into
283
- * settings.json, which IS tracked; and only the rules arrived. What the workspace held from then on was two
284
- * hooks pointing at files that did not exist: a per-edit gate that looked armed on the settings screen,
285
- * spawned a process on every edit, and read nothing. The linter and the byte scan ran nowhere between an
286
- * edit and a push for as long as that stood.
287
- *
288
- * `versioned` for the strongest form of the reason the config slice generally is. This is not a setting that
289
- * decides how the sandbox behaves, it is the CODE that runs when it does, against every file an agent
290
- * writes: a change here deserves review more than a change to the rule that calls it. `carry`, because it is
291
- * authored text about this workspace's own conventions, holding no credential and nothing about this
292
- * machine. Invalidating nothing is a real answer here rather than a gap: the settings screen renders the
293
- * RULES, which live in settings.json and have their own key. */
294
- {
295
- path: ".intentic/config/hooks/",
296
- invalidates: [],
297
- why: "The settings screen renders the rules that name these scripts, out of settings.json; nothing in the browser reads the scripts themselves.",
298
- portability: "carry",
299
- versioned: true,
300
- // The daemon never BUILDS this path, it only runs what a rule's command names, so there is no statePath
301
- // call for the coverage pair to find. Whoever authors a reader is the writer here.
302
- outsideWriter: "the owner or an agent, authoring them; the daemon only ever RUNS one, by the path a rule's command names",
303
- },
304
- // The rule table's last-fired stamps, beside the rules themselves. `derived` rather than `carry`: it is a
305
- // record of what happened in THIS sandbox, and carrying it to a fresh one would date every rule to work
306
- // that machine never did.
307
- {
308
- path: ".intentic/local/rule-firings.json",
309
- invalidates: ["rule-firings"],
310
- portability: "derived",
311
- note: "Stamps of when each rule last did something; the new sandbox starts its own record.",
312
- },
313
- /* The runtime-install ledger: which tools sessions installed into the container at runtime, how often, and
314
- * the last drift snapshot (environment/runtime-installs.ts). `carry` where rule-firings chose `derived`,
315
- * because the two record different subjects: a firing is about what THIS machine did, while the ledger is
316
- * about what this WORKSPACE's tasks keep needing — a workspace moved to a fresh sandbox will hit the same
317
- * missing tools, and arriving with the recurrence memory is the whole reason it is kept. The drift snapshot
318
- * inside is machine-scoped, and self-expires on the move: its bornAt can never match the new container. */
319
- { path: ".intentic/records/runtime-installs.json", invalidates: ["environment"], portability: "carry" },
320
- /* Where each agent ENGINE's version comes from: the blessed list, upstream's newest, a pin, or the image
321
- * (schemas/engines.ts). The versions themselves are machine state and live on the daemon's volume, because
322
- * they are architecture-specific binaries; the POLICY is a decision about this workspace's work and travels
323
- * with it — a team that pins Claude Code while a regression is open wants that pin to survive the move to a
324
- * fresh sandbox rather than to be rediscovered by hitting the regression again.
325
- *
326
- * `versioned` for the config slice's usual reason (personas.json's entry argues it): it changes at human
327
- * speed, holds no secret, and "since when have we been tracking upstream's newest on this repo" is a
328
- * question only `git log` answers. Its own key rather than `environment`'s: the engines card is drawn on
329
- * that page but reads its own route, and a channel change must not cost every open Environment tab a
330
- * re-read of the overlay it did not touch. */
331
- { path: ".intentic/config/engines.json", invalidates: ["engines"], portability: "carry", versioned: true },
332
- /* Written by the AGENT's file tools (the approvals skill), read by the owner's approval inbox, the one entry
333
- * here whose whole point is that a change arrives from outside the browser that renders it. `authored`:
334
- * an approval is text somebody wrote, a post or a description of an action, and "find the reddit post
335
- * about X" is an ordinary search.
336
- *
337
- * `versioned` because an approval is the furthest-reaching thing the agent writes: a post goes out under the
338
- * owner's name, to an audience, and cannot be recalled; an action spends or sends or deletes. The inbox
339
- * already gates that, but a gate is not a record. Declining one used to erase it, so the question "what has
340
- * this agent tried to do" had no answer at all, and an approved item's own history (what was proposed, what
341
- * the owner changed, when it actually happened) lived only in a file nobody could diff.
342
- *
343
- * It costs almost nothing to track, which is why the ledger objection does not reach it: an approval is one
344
- * small file, written a handful of times across its whole life (proposed → approved → done, with
345
- * `finishedAt`/`result` stamped at the end), and it is KEPT afterwards rather than consumed, so tracking
346
- * yields a durable record instead of the add/delete churn a queue would produce. Nothing in one is a
347
- * credential: a platform, a target, the words, a description of what will be done, all of it meant to be
348
- * read by the owner anyway. */
349
- { path: ".intentic/config/approvals/", invalidates: ["approvals"], portability: "carry", versioned: true, authored: true },
350
- // ---- declared by the extension that renders them (contributes.files), not here ----
351
- // The path is the DAEMON's (automations-store writes both), the query keys are the intentic.automations
352
- // extension's. It declares them in its own manifest and the browser unions the two lists, so uninstalling
353
- // the extension takes its invalidations with it instead of leaving a rule for a view that no longer exists.
354
- {
355
- path: ".intentic/config/automations.json",
356
- invalidates: [],
357
- why: "Declared by the intentic.automations extension's contributes.files, `automations` is its query key, not core's.",
358
- portability: "carry",
359
- versioned: true,
360
- },
361
- /* The run history, keyed by automation id, the LEDGER half of what automations.json used to be, and split
362
- * out of it for the one reason this table's `versioned` note already gives: a tracked file must be worth
363
- * reviewing. A scheduled automation records a run every time it fires, so every fire dirtied the manifest
364
- * the owner reviews, and the run records went into `git log` with it, timestamps and conversation ids
365
- * committed beside the prompt they belong to, burying an actual edit to the automation's config under
366
- * machine noise. Config is now the only thing in the tracked file, and a fire touches nothing tracked.
367
- *
368
- * It is `carry` for the same reason the workflow ledger is: a run history is about the automation, not about
369
- * the machine, and an export that dropped it would arrive claiming every automation had never run.
370
- *
371
- * Its invalidation is the extension's, exactly like the manifest above, and it has to be DECLARED there
372
- * rather than inherited, because the row renders its run history from this file now: without its own entry
373
- * a completed run would stop refreshing the view the moment it stopped living in automations.json. */
374
- {
375
- path: ".intentic/records/automation-runs.json",
376
- invalidates: [],
377
- why: "Declared by the intentic.automations extension's contributes.files, `automations` is its query key, not core's.",
378
- portability: "carry",
379
- },
380
- {
381
- path: ".intentic/records/approvals/",
382
- invalidates: [],
383
- why: "Declared by the intentic.approvals extension's contributes.files (the page that lists held wakes), `automation-approvals` is its query key, not core's.",
384
- portability: "carry",
385
- },
386
- /* The bug-report inbox, one file per fingerprint, written by the daemon's issues-store as reports arrive
387
- * from the owner's own sites and apps, and rendered by the intentic.issues extension. Its invalidation is
388
- * the extension's own (`issues`), declared in that manifest, the automations shape exactly.
389
- *
390
- * `carry` rather than `local`: an issue is a fact about the PRODUCT, not about this container. A workspace
391
- * exported and restored elsewhere that arrived claiming nothing had ever crashed would have thrown away
392
- * the one record that says which bug is worth fixing first, and the counts are the whole of that record.
393
- *
394
- * NOT `versioned`, and the approvals entry is the contrast worth reading: an approval is authored, reviewable
395
- * and acts under the owner's name, so it earns a diff. An issue is machine-recorded telemetry whose count
396
- * moves on every crash: tracking it would put a commit's worth of churn in `git log` per bad afternoon,
397
- * and nothing in it is a decision anybody made. */
398
- {
399
- path: ".intentic/records/issues/",
400
- invalidates: [],
401
- why: "Declared by the intentic.issues extension's contributes.files, `issues` is its query key, not core's.",
402
- portability: "carry",
403
- },
404
- /* The maintenance ledger and probe evidence, written by the daemon's chores-store and rendered by the
405
- * intentic.maintenance extension, the automations shape exactly: the path is the daemon's, the query keys
406
- * (`maintenance-report`, `maintenance-runs`) are the extension's own contributes.files. Point-in-time
407
- * evidence about this workspace, so `carry` like the run ledgers: an export that dropped it would arrive
408
- * claiming no chore had ever been checked. */
409
- {
410
- path: ".intentic/records/chores/",
411
- invalidates: [],
412
- why: "Declared by the intentic.maintenance extension's contributes.files, `maintenance-report`/`maintenance-runs` are its query keys, not core's.",
413
- portability: "carry",
414
- },
415
- /* The documentation STAGING tree (documentation extension's paths.ts): generation writes here, the owner
416
- * reads and approves here, publishing copies into the repo. `authored` is the whole nature of the entry,
417
- * these are draft READMEs, approvals-shaped in every way that matters, and "find the staged page about X" is
418
- * as ordinary a search as finding a post draft. */
419
- {
420
- path: ".intentic/config/docs/",
421
- invalidates: [],
422
- why: "Declared by the intentic.documentation extension's contributes.files, `documentation`/`documentation-runs` are its query keys, not core's.",
423
- portability: "carry",
424
- authored: true,
425
- outsideWriter: "the intentic.documentation extension's staging writes (its paths.ts)",
426
- },
427
- /* The workflow designs and their run ledger became CORE keys the day runs got cards on the fleet board and
428
- * a mode of the chat panel (web's useWorkflowRuns): those surfaces exist whether or not the workflows
429
- * extension is enabled, so their freshness cannot ride an extension's contributes.files, an owner turning
430
- * the extension off would have frozen the board's run cards mid-run. This push is the ONLY live feed the
431
- * run surfaces have: the scheduler writes the ledger several times per step and nothing polls for it.
432
- * The runs file invalidates `workflows` too, because GET /workflows embeds each design's runs
433
- * (WorkflowSummary), a settled step changes that answer as surely as an edited design does. */
434
- { path: ".intentic/config/workflows.json", invalidates: ["workflows"], portability: "carry", versioned: true },
435
- { path: ".intentic/records/workflow-runs.json", invalidates: ["workflows", "workflow-runs"], portability: "carry" },
436
- /* The SAVED loops, which are a manifest and so the opposite of the ledger below them: a handful of entries
437
- * a person authors, read by two surfaces at once, the workflows page that owns them, and every chat
438
- * composer's loop picker. Those two are in different windows as often as not (a popped-out chat is its own
439
- * window), so an edit made on the page has to reach a picker nobody is going to think to reopen. A CORE key
440
- * rather than the workflows extension's, for the reason the workflow designs beside it are: the composer
441
- * lists saved loops whether or not that extension is switched on. */
442
- { path: ".intentic/config/loop-designs.json", invalidates: ["loop-designs"], portability: "carry", versioned: true },
443
- {
444
- path: ".intentic/records/loops.json",
445
- invalidates: [],
446
- why: "Ralph loops and their iteration history. Nothing observes it: where a RUNNING loop stands rides on the fleet roster (AgentSummary.loop), which the /events stream already pushes about once a second, and a second source invalidating on this file could only ever disagree with the card beside it. The iteration list of an ENDED loop is an on-demand read, nothing renders it until someone opens it (web's useLoops, which holds no query for exactly this reason).",
447
- portability: "carry",
448
- },
449
-
450
- /* ---- reached by no query, for reasons that are not oversights ----
451
- *
452
- * This channel's currency is a QUERY KEY, and invalidation only reaches a query something is observing.
453
- * Both entries below are outside that by design, so an empty set is the honest record, naming a key no
454
- * query uses would put the drift this table exists to remove straight back into it. Each says which
455
- * constraint would have to move first, so the next reader doesn't re-derive it. */
456
- {
457
- path: ".intentic/records/webchat-installs.json",
458
- invalidates: [],
459
- why: "Which origins have loaded a Front Desk's widget, written on a 30s flush timer while a customer's site serves page views. The install panel that renders it fetches on open and polls itself while it is on screen, which is the whole window in which the answer changes for anyone. Pushing instead would bill every connected browser a refetch per flush, for a panel almost nobody has open.",
460
- portability: "carry",
461
- },
462
- {
463
- path: ".intentic/records/issue-installs.json",
464
- invalidates: [],
465
- why: "The same probe for the bug reporter's script, on the same flush timer and read by the same kind of panel, so it is outside the push path for the same reason the Front Desk's is.",
466
- portability: "carry",
467
- },
468
- {
469
- path: ".intentic/records/thread-sessions.json",
470
- invalidates: [],
471
- why: "Thread bookkeeping (an inbound thread, a Front Desk visitor, a Discord or Slack channel, → sandbox conversation + provider session), written on EVERY inbound message. Nothing in the browser reads it: what a thread produces is a conversation, and the fleet board already learns about that from the agent registry's own push. Naming a key here would bill every connected browser a refetch per inbound message, the request storm this table's own note warns about, to refresh nothing it can see.",
472
- portability: "carry",
473
- },
474
- /* SPLIT, so that "what an extension is configured to do" and "the token it does it with" stop being one file.
475
- *
476
- * This entry used to be `secret` and untracked, classed by what a value COULD hold: values are a primitive
477
- * union an extension chooses the meaning of, and "an API key for the service I talk to" is squarely within
478
- * it. That classification was honest about the risk and wrong about the file, it meant an extension's whole
479
- * configuration was unreviewable because one of its keys might be a credential, AND the credential was in
480
- * there anyway, in a file the workspace API does not lock. A turn could simply read it.
481
- *
482
- * A descriptor already says which keys those are (`contributes.settings[].secret`), so the values it names
483
- * now live in the vault off /work and this file keeps the rest, the capability manifest's split, applied to
484
- * the same problem one table over (extensions/extension-settings.ts holds it, and the reasoning). Reads
485
- * rehydrate, so no caller changed.
486
- *
487
- * What the split earns: `carry`, because what is left is an extension's configuration and a bundle should
488
- * arrive with it; and `versioned`, because turning an extension's behaviour on is a decision, and the file
489
- * that records it can now be read without reading anybody's token. The boot sweep is what keeps that true of
490
- * a file the agent can also edit, see vaultExtensionSettingSecrets.
491
- *
492
- * NO `note`, and the split is why: a note is printed by the import report beside a SKIPPED entry, so an entry
493
- * that carries can never show one. "Re-enter the credentials" is now the vault's instruction to give, and the
494
- * vault is under `.intentic/auth/`, which is skipped, and says so there. */
495
- {
496
- path: ".intentic/config/extension-settings.json",
497
- invalidates: [],
498
- why: "Held in a module-level shallowRef store per extension (web's extensionSettingsStore) with no query observer, and deliberately so: api.settings.get must answer SYNCHRONOUSLY from an extension's first activate() line, and the store outlives every component scope. A module-level QueryObserver is the one shape that would make invalidation refetch, and this app already ruled it out, it detaches on the queryClient.clear() at logout (see useSandbox's sandbox-list mirror). So a remote member's setting edit reaches this browser on its next load, not live.",
499
- portability: "carry",
500
- versioned: true,
501
- },
502
- /* Unlike the settings file above it, the on/off switch IS observed by a query, the Extensions tab's list,
503
- * which carries each row's switch position, so a flip made elsewhere (another member, the agent writing the
504
- * file) shows up here live. It does not re-run the host: activating or retiring an extension is the loader's
505
- * reconcile, which the tab's own toggle triggers, so a remote flip takes effect on this browser's next load. */
506
- {
507
- path: ".intentic/config/extension-enablement.json",
508
- invalidates: ["extensions"],
509
- portability: "carry",
510
- versioned: true,
511
- },
512
- /* Workspace extensions: one directory per extension, consumed straight from the workspace, no clone, no
513
- * install moment. Written like approvals, by the agent's own file tools (which is the point: an agent authors
514
- * an extension and it is live for the daemon and every session at once, since .intentic is shared), so this
515
- * push is what makes one appearing or changing show up on the Extensions tab while the owner watches.
516
- * `authored` for the same reason as approvals: this is source the agent wrote and will be asked to find,
517
- * unlike `.intentic/extensions/` below, which is CLONES of source that lives elsewhere.
518
- *
519
- * `versioned` FOR THAT SAME REASON, which is the whole argument. Every other load path an extension can take
520
- * is already reviewable by construction: a git-installed one is a sha in `capabilities.json` that an owner
521
- * approved, a baked one shipped in the image. This one is neither, it is code that appears because an agent
522
- * wrote a file, runs in the app on the owner's session, may register a rail tile, and may serve HTTP from a
523
- * node process with the workspace under `node:fs` and whatever `permissions.daemon` names. Untracked, the
524
- * switch that turns it on was in `git log` (extension-enablement.json, below) while the thing being switched
525
- * on was not: a commit could record enabling something nobody else could read. It is also the one extension
526
- * kind with no install moment to review at, so the diff is the only review there is.
527
- *
528
- * Not a ledger and not bulk: a handful of small authored files per extension, written when someone edits them.
529
- * The daemon restarts the backend host on a change here, so an edit is already a consequential event, this
530
- * makes it a legible one. */
531
- { path: ".intentic/config/workspace-extensions/", invalidates: ["extensions"], portability: "carry", versioned: true, authored: true },
532
- /* What the registry comparison found per installed extension (update available / advisory / post-update
533
- * health), written by the periodic check and by the update/revert transactions, pushed to the tab because
534
- * an advisory that auto-disabled something must not wait for a reload to be seen. */
535
- { path: ".intentic/records/extension-updates.json", invalidates: ["extensions"], portability: "carry" },
536
- /* The owner's per-extension update posture (notify / agent / auto, and the advisory opt-out). Carried:
537
- * it is a decision about the extension, not about this machine. */
538
- { path: ".intentic/config/extension-update-policy.json", invalidates: ["extensions"], portability: "carry", versioned: true },
539
- /* Carried, because the evidence is about the extension rather than about the machine: an export that dropped
540
- * it would arrive claiming every permission was unused, which is worse than arriving with no figures at all. */
541
- {
542
- path: ".intentic/records/extension-usage.json",
543
- invalidates: [],
544
- why: "Which of the routes each extension DECLARED it has actually called, the evidence behind the permissions list on its row. The one entry here whose empty set is a RATE decision rather than an architectural one: every browser with the app open reports its batch on a timer, so wiring this to the `extensions` query would refetch the whole list every few seconds for a figure nobody is watching change. The tab reads it when it loads, which is when anyone is reading it.",
545
- portability: "carry",
546
- },
547
- /* THE ONE ENTRY WHERE "HOLDS NO CREDENTIAL" IS TRUE AND `versioned` IS STILL WRONG, which is worth stating
548
- * because it looks like the two above it: an email and a role per row, nothing to vault, and "who may drive
549
- * this sandbox" is as consequential a fact as any this table tracks.
550
- *
551
- * It stays out for two reasons that are not about secrecy. It is a MIRROR, the platform's invite records are
552
- * the grant, this is the copy the enforcer keeps so a grant it never received is never honoured, and a change
553
- * here is the two disagreeing rather than anyone deciding something. Review of the decision already exists,
554
- * on the Access tab, against the record that is authoritative. And tracking it would mean reclassifying it
555
- * `carry` to satisfy the guard, which is the one thing it must never be: an access list that travelled would
556
- * let a source sandbox hand itself the target's ownership. Widening the guard for this single entry is the
557
- * worse trade, it protects every `identity` entry, and most of those ARE credentials. */
558
- {
559
- path: ".intentic/identity/members.json",
560
- invalidates: [],
561
- why: "Not this view's source at all: SandboxAccess renders the PLATFORM's invite records (apiClient.invite.list), and this file is the daemon's ENFORCED copy, written first so a grant the enforcer never got is never recorded, then never read back. A change here means the two disagreed, which the write order makes fail-closed rather than stale.",
562
- portability: "identity",
563
- note: "Re-invite collaborators from the Access tab, a grant is the platform's record, and the target enforces its own copy.",
564
- },
565
-
566
- // ---- daemon-owned, nothing derives from watching them ----
567
- /* Keep credentials and conversation state in disjoint top-level trees. Provider homes are intentionally
568
- * classified as a single secret unit: several CLIs mix OAuth, config, and provider-native thread metadata,
569
- * and no generic export can safely distinguish those files. The broad root also makes a newly-added provider
570
- * secret by construction instead of relying on another hand-maintained provider-name list.
571
- *
572
- * IT IS NO LONGER ONLY THE AI LOGINS. Both credential splits put their vault here, `capability-secrets.json`
573
- * and `extension-secrets.json`, sited beside the provider homes precisely because this tree is already
574
- * outside the file routes, the workspace walk and the search index (composition.ts sites them, and the two
575
- * stores argue why). So this is now the ONE entry a secret-less bundle leaves behind, and its note is
576
- * therefore the only place the owner is told what to re-enter: the manifests that name those connections
577
- * travel, and would otherwise arrive looking complete. */
578
- {
579
- path: ".intentic/secrets/auth/",
580
- invalidates: [],
581
- why: "AI-provider credentials and runtime homes, plus the capability and extension-settings secret vaults; each account is rendered through owner-gated provider routes.",
582
- portability: "secret",
583
- note: "Sign the agent's AI accounts in again on the Agent tab, then re-enter each connection's credential on Capabilities and each extension's secret settings on Extensions, both arrived listed but unauthenticated.",
584
- },
585
- /* Agent session transcripts, rewritten on every streamed token: nothing renders them off disk, so nothing
586
- * under here is watched. The exclusion is a DESCENT filter, which is what makes it cheap: the watcher never
587
- * walks `projects` and its per-slug subtrees at all. Measured on the live workspace, descending would add
588
- * +119 watched directories against ~593 (a fifth more), with 314 continuously-rewritten transcripts inside
589
- * the newly-watched set. If a surface here ever needs to be live, weigh that 20% against a poll first. */
590
- {
591
- path: ".intentic/records/sessions/claude/",
592
- invalidates: [],
593
- why: "Agent session transcripts; nothing derives from watching them, and descending into them would cost a fifth of the watcher.",
594
- portability: "carry",
595
- },
596
- {
597
- path: ".intentic/records/artifacts/",
598
- invalidates: [],
599
- why: "Durable outputs owned by conversations and extension runs: attachments, browser captures, generated images, acceptance reports, workflow step reports, voice transcripts, and loop ledgers.",
600
- portability: "carry",
601
- },
602
- {
603
- path: ".intentic/local/cache/",
604
- invalidates: [],
605
- why: "Rebuildable indexes and caches, the iq index and its vector sidecar, the whisper model, fileq's derived/ markdown shadows of binary files; ignored by the watcher and recreated from carried workspace content.",
606
- portability: "derived",
607
- },
608
- /* Connector and extension scratch, one directory per extension under runtime/extensions/<id>
609
- * (extensionRuntimeDir below, the ONLY way an extension names a home here, so a new one lands under its
610
- * own id by construction instead of minting a file at the .intentic root). Resume watermarks, cached
611
- * hour-tokens, gateway discovery state: all of it either expires or re-establishes itself, and classifying
612
- * the root once is what keeps a token an extension caches tomorrow out of bundles without a second edit. */
613
- {
614
- path: ".intentic/local/runtime/",
615
- invalidates: [],
616
- why: "Extension runtime scratch (watermarks, cached short-lived tokens); nothing renders it and gateways re-derive it.",
617
- portability: "derived",
618
- outsideWriter: "extensions, through extensionRuntimeDir below",
619
- },
620
- {
621
- path: ".intentic/local/tmp/",
622
- invalidates: [],
623
- why: "Scratch that agents and tools leave behind (build logs, demo checkouts); nothing reads it after the turn that wrote it. The state janitor empties it at boot.",
624
- portability: "derived",
625
- },
626
- /* Not written by the daemon at all: pnpm auto-creates its content-addressable store at the project's
627
- * mountpoint, and `.intentic` is its own mount in an isolated turn, so an install run from under it mints
628
- * this. Declared anyway, because the table's job is to say what everything under `.intentic` IS: hardlink
629
- * sources a fresh install rebuilds, which an export must not ship (it reached 1.3 GB on the workspace this
630
- * entry was written against). */
631
- {
632
- path: ".intentic/local/.pnpm-store/",
633
- invalidates: [],
634
- why: "pnpm's content-addressable store, auto-created by installs run from under .intentic; the next install rebuilds it.",
635
- portability: "derived",
636
- outsideWriter: "pnpm itself, when an install runs from under .intentic",
637
- },
638
- {
639
- path: ".intentic/local/newest-run.json",
640
- invalidates: [],
641
- why: "The newest daemon version that ever ran this workspace (store/newest-run.ts), a downgrade tripwire, about THIS sandbox the way rule-firings is.",
642
- portability: "derived",
643
- note: "The target stamps its own daemon version on first boot.",
644
- },
645
- {
646
- path: ".intentic/records/verify.json",
647
- invalidates: [],
648
- why: "The dependency verifier's verdict memory; nothing renders it directly, outcomes reach the owner as activity entries and workspace events.",
649
- portability: "carry",
650
- },
651
- {
652
- path: ".intentic/local/verify/",
653
- invalidates: [],
654
- why: "A running check's wrapper artifacts (log + exit status), read once by the daemon when the panel finishes.",
655
- portability: "derived",
656
- },
657
- {
658
- path: ".intentic/secrets/ci.json",
659
- invalidates: [],
660
- why: "Webhook secret + conclusion memory; the Pipelines view reads it through /ci/runs, not off disk.",
661
- portability: "secret",
662
- note: "Re-add the CI webhook on the Pipelines view, its secret is per-sandbox.",
663
- },
664
- /* THE ONE ENTRY THAT OPTS OUT OF THE BACKUP, and the reason the flag exists rather than the rule simply
665
- * reading `portability !== "derived"`. It is `identity` like the three below it, so the derived answer would
666
- * copy it down with them, but where those are a name, a workspace id and a role per row, these are tokens
667
- * that AUTHENTICATE against this sandbox from outside it. Hashed, which lowers the stakes and does not
668
- * settle them: the point of a backup is to be readable after the thing it backs up is gone, and a file whose
669
- * only purpose is to admit callers has no business sitting in one. Nothing is lost by leaving it out, the
670
- * entry's own note already says the tokens must be re-minted on any new sandbox, so a copy could never have
671
- * been restored anyway. */
672
- {
673
- path: ".intentic/identity/control-tokens.json",
674
- invalidates: [],
675
- why: "Hashed control tokens (the ACP editor bridge, and anything else driving this sandbox from outside), listed on demand by the owner.",
676
- portability: "identity",
677
- backup: false,
678
- note: "Mint fresh control tokens, the old ones authenticate against the source sandbox.",
679
- },
680
- {
681
- path: ".intentic/identity/owner.json",
682
- invalidates: [],
683
- why: "Bound once on first use; a change here means the sandbox was re-owned, which re-authenticates anyway.",
684
- portability: "identity",
685
- },
686
- {
687
- path: ".intentic/identity/workspace.json",
688
- invalidates: [],
689
- why: "The workspace identity, read from the /events hello frame rather than as a file.",
690
- portability: "identity",
691
- },
692
- {
693
- path: ".intentic/config/templates.json",
694
- invalidates: [],
695
- why: "Scaffold templates, read when the scaffold dialog opens.",
696
- portability: "carry",
697
- versioned: true,
698
- },
699
- /* Classed `derived` for size rather than for safety, and it is the one entry where that costs the owner
700
- * something real: the profiles ARE logged-in sessions. They are also gigabytes of a store Chromium rewrites
701
- * constantly and versions against its own build, so carrying them ships bulk that the target's Chromium may
702
- * refuse anyway. The note is what keeps the loss visible instead of silent. */
703
- {
704
- path: ".intentic/local/browser/",
705
- invalidates: [],
706
- why: "Browser-login profiles: Chromium rewrites these constantly. Descent-ignored by the watcher outright.",
707
- portability: "derived",
708
- note: "Log the agent's browser back into any site it needs, profiles do not travel.",
709
- },
710
- {
711
- path: ".intentic/local/extensions/",
712
- invalidates: [],
713
- why: "Extension checkouts, whole git clones. The `extensions` query is driven by the capability manifest above, not by their contents.",
714
- portability: "derived",
715
- note: "Extensions re-clone from the capability manifest on the target's next reconcile.",
716
- },
717
- { path: ".intentic/records/plugins/", invalidates: [], why: "Agent plugin dirs, read by the SDK's loader each turn.", portability: "carry" },
718
- /* THE SKILLS THE OWNER WROTE THEMSELVES, one directory per skill, the source of truth the reconciler copies
719
- * into `.agents/skills` for the ones currently switched on (settings.json's `skills` list). It is here rather
720
- * than in the loaded folder for the reason the plugin dirs are: that tree holds only what is currently ON,
721
- * and a skill switched off has to keep its text somewhere the loaders will not read it from.
722
- *
723
- * `versioned`, like the rest of the config slice: a skill changes how the agent behaves, so it earns a diff
724
- * in the Changes review and a line in `git log` the same way a rule or a persona does. `carry` for the same
725
- * reason, it is text the owner wrote, with no credential in it and nothing about this machine. */
726
- { path: ".intentic/config/skills/", invalidates: ["skills"], portability: "carry", versioned: true },
727
- /* ONE FOLDER PER PERSONA, what a session wearing that card is told, and the skills and tools only it gets.
728
- * Laid out as a Claude Code plugin (`.claude-plugin/plugin.json`, `skills/`, `agents/`, `commands/`,
729
- * `hooks/`, `.mcp.json`) so the runtime's own loader reads it and this daemon parses none of it, exactly as
730
- * the plugin checkouts above are read (personas/persona-kit.ts).
731
- *
732
- * A SECOND ENTRY BESIDE `personas.json` RATHER THAN A FIELD INSIDE IT, because the two are different kinds
733
- * of thing to review. The card is a name, some ids and some switches, a few lines that diff cleanly. This
734
- * is prose and files: a system prompt, a skill, a subagent. Folding a 20k prompt into the JSON would make
735
- * every persona edit an unreadable diff and put text somebody wrote inside a record nobody writes by hand.
736
- *
737
- * `versioned` and `carry` for the same reasons the card and the skills above are: it changes how the agent
738
- * behaves, it holds no credential, and it belongs in a pull request, which is also what makes it
739
- * searchable, since every versioned entry already is. */
740
- { path: ".intentic/config/personas/", invalidates: ["personas"], portability: "carry", versioned: true },
741
- ] as const satisfies readonly WorkspaceStateFile[];
742
-
743
- export const WORKSPACE_STATE_FILES: readonly WorkspaceStateFile[] = STATE_FILES;
744
-
745
- /* The entries the root repo tracks, workspace-root-relative and in declaration order, what history.ts turns
746
- * into the negations that carve them back out of the wholesale `.intentic` exclusion.
747
- *
748
- * Derived rather than written down beside the exclude rule, for the reason this whole file exists: the git rule
749
- * lives in the daemon and the classification lives here, and a second hand-kept copy of "which config is
750
- * reviewable" is a copy that goes stale the first time someone adds a store. Marking an entry `versioned` is now
751
- * the entire change, the exclude list follows on the next boot, in both places it is written. */
752
- export const VERSIONED_STATE_PATHS: readonly string[] = WORKSPACE_STATE_FILES.filter((file) => file.versioned).map((file) => file.path);
753
-
754
- /* The `.intentic` slice a workspace SEARCH may surface: configuration a person reviews (`versioned`) plus the
755
- * authored-content dirs (`authored`), approvals, staged docs, workspace extensions. Everything else under
756
- * `.intentic` is machine state, and the search engine (iq's floor) denies it BY DEFAULT off this list, the
757
- * same default-deny the portability classes are built on and for the same reason: a deny list is a list a new
758
- * ledger is forgotten from, and the forgetting is silent, it ranked loop iteration history and cloned
759
- * third-party extension source against the user's own code for months before this derivation existed.
760
- *
761
- * WHAT THE CREDENTIAL SPLITS MOVED ACROSS THIS LINE, since the note that used to sit here said the opposite and
762
- * was worth replacing rather than deleting. `capabilities.json` was `secret` and unversioned, and the sentence
763
- * celebrated that the index therefore stopped copying capability tokens into search text. It is `versioned` now
764
- * and searchable, and the guarantee is unchanged, because the tokens are not in the file any more. The floor
765
- * moved from "keep the index away from the file that holds credentials" to "the file holds none", which is the
766
- * stronger of the two: it also holds for the shell, which never consulted this list at all. `auth/`, where those
767
- * values went, both vaults included, is still denied, and is the entry that was doing the real work all along. */
768
- export const SEARCHABLE_STATE_PATHS: readonly string[] = WORKSPACE_STATE_FILES.filter((file) => file.versioned || file.authored).map(
769
- (file) => file.path,
770
- );
771
-
772
- /* WHAT KIND OF THING THIS IS, in the one word a person browsing the state dir would use, and the axis the
773
- * DIRECTORY LAYOUT is built on, so the folder you open explains itself before you read a table about it.
774
- *
775
- * It is DERIVED, and that is the whole reason it can be trusted. Forty-nine entries already answer three
776
- * questions between them (is it reviewed, is it authored, does it travel), and those answers turn out to nest
777
- * perfectly rather than cut across each other: every `versioned` entry is `carry`, every `authored` entry is
778
- * `carry`, and nothing is both a credential and a thing a person edits. A nested set of answers is exactly what
779
- * a directory tree can express, which is why five folders can carry rules that used to take five hand-kept path
780
- * lists, the git exclude, the search allow-list, the sync ignore, the watcher skip, the export bundle.
781
- *
782
- * Declaring the group on each entry instead would have made it a fourth independent fact to keep in step with
783
- * the other three, which is the failure this file exists to argue against. Adding a store still means answering
784
- * the same three questions it always did; the group, the folder it belongs in, and every rule that reads them
785
- * follow with no further edit. */
786
- export type StateGroup =
787
- /* Reviewed and reviewable: settings, personas, skills, approvals, staged docs, the environment overlay. Tracked
788
- * by the root repo, searchable, backed up, and carried into a new sandbox. Two of its members (approvals, staged
789
- * docs) are authored content rather than configuration, and the folder is still called `config`, the word
790
- * that makes seventeen of the nineteen instantly clear beats one that makes all nineteen vague. */
791
- | "config"
792
- /* What HAPPENED here, run ledgers, approvals, chores, transcripts, artifacts. Machine-written, so untracked
793
- * and unsearchable, but the owner's history all the same: backed up and carried. */
794
- | "records"
795
- /* Rebuildable from something that does travel: caches, indexes, extension checkouts, scratch, the composed
796
- * overlay, browser profiles. Neither backed up nor carried, and the janitor may delete it. `local` in the
797
- * sense every other tool uses it, belongs to this machine, is not shared, and losing it costs nothing. */
798
- | "local"
799
- /* Who owns this sandbox and who may drive it. Backed up so the owner keeps a copy of their own access, never
800
- * carried, a list that travelled would let a source sandbox claim the target. */
801
- | "identity"
802
- /* Credentials. Never backed up; carried only when the owner opts in at export and the bundle records it. */
803
- | "secrets";
804
-
805
- /* THE FOLDER EACH GROUP LIVES IN.
806
- *
807
- * The group name IS the directory name, one vocabulary, not a name and a translation of it. That is what lets
808
- * the guard in workspace-state.test.ts check the whole layout with one rule ("every entry sits under its own
809
- * group's folder") rather than trusting forty-nine literals to have been typed correctly, and it is why renaming
810
- * a folder is an edit here plus the literals the compiler then points at, with nothing able to half-move.
811
- *
812
- * WHICH RULES THE LAYOUT ACTUALLY CARRIES, stated plainly because it is fewer than the tidy version of this
813
- * story. The sync backup collapses to two folder names (BACKUP_IGNORES) and workspace search to one, because
814
- * "may the owner keep this" and "is this authored text" are exactly what the grouping sorts on. Two others do
815
- * NOT collapse, and both are worth knowing about before someone tries:
816
- * - THE GIT EXCLUDE tracks `versioned`, which is eighteen of `config`'s nineteen. The exception is the staged
817
- * docs tree: searchable, deliberately untracked (publishing copies those pages into the repo, so tracking
818
- * the staging copy too would double every one of them). A `config/` prefix would quietly start tracking it.
819
- * - THE WATCHER skips what churns, which is most of `local` but not all of it: the composed overlay and the
820
- * rule-firing stamps are `derived` and therefore `local`, and both still feed a view. A `local/` prefix
821
- * would stop the environment page refreshing when the overlay is recomposed.
822
- * Both stay derived from the flags instead, which costs a longer generated list and no correctness. The folders
823
- * are the layout; the flags are still the authority. */
824
- export const STATE_GROUP_DIR: Readonly<Record<StateGroup, string>> = {
825
- config: `${STATE_DIR}/config`,
826
- records: `${STATE_DIR}/records`,
827
- local: `${STATE_DIR}/local`,
828
- identity: `${STATE_DIR}/identity`,
829
- secrets: `${STATE_DIR}/secrets`,
830
- };
831
-
832
- // Every group, derived off the folder map so the two can never disagree about how many there are. Declaration
833
- // order is the order a person should read them in: what you wrote, what happened, what can be thrown away, who
834
- // owns this, and the keys.
835
- export const STATE_GROUPS = Object.keys(STATE_GROUP_DIR) as readonly StateGroup[];
836
-
837
- /* The group each entry falls in. Ordered most-specific-first: a credential is a credential whatever else it is,
838
- * and only once those are out of the way does "did a person write this" separate the two `carry` groups. */
839
- export const stateGroupOf = (file: WorkspaceStateFile): StateGroup => {
840
- switch (file.portability) {
841
- case "secret":
842
- return "secrets";
843
- case "identity":
844
- return "identity";
845
- case "derived":
846
- return "local";
847
- case "carry":
848
- return file.versioned === true || file.authored === true ? "config" : "records";
849
- }
850
- };
851
-
852
- // The entries of one group, workspace-root-relative and in declaration order, what each rule that used to keep
853
- // its own path list now asks for instead.
854
- export const stateGroupPaths = (group: StateGroup): readonly string[] =>
855
- WORKSPACE_STATE_FILES.filter((file) => stateGroupOf(file) === group).map((file) => file.path);
856
-
857
- /* WHAT AN ISOLATED TURN SHARES LIVE WITH THE MAIN TREE, and what is its own. The state dir is split along ONE
858
- * line, and it is the line git already draws: what the root repo TRACKS (`versioned`) is the worktree's own
859
- * checkout, edited on the agent's branch, reviewed in its diff and landed like code; everything git does NOT
860
- * track is bound in from the main tree (agents/isolation.ts), one directory for every conversation, because a
861
- * transcript, a ledger, a browser capture or a staged doc written into a per-worktree copy is simply lost.
862
- *
863
- * The two used to be one bind over the whole dir, with the tracked slice sparse-excluded from every worktree to
864
- * keep git from writing through it. That put the ONE thing a person reviews outside the one door that records
865
- * provenance: an agent's settings edit, approval, environment fragment or skill went straight into the owner's
866
- * working tree, unattributed, with no branch commit and nothing for a land to conflict on. Binding by group
867
- * ends both problems at once, nothing tracked sits behind a bind, so nothing git does in a worktree can reach
868
- * the live tree, and the sparse machinery has nothing left to guard.
869
- *
870
- * WHOLE GROUP DIRS WHERE THE WHOLE GROUP IS UNTRACKED (records, local, identity, secrets), not their entries: a
871
- * file an extension writes under `records/` without declaring it must still land in the shared tree, and a
872
- * per-entry bind would strand it in the worktree. Only a group that MIXES tracked and untracked entries (config,
873
- * for the staged docs tree) is bound entry by entry. Derived, so a store added tomorrow is placed by its
874
- * `versioned` flag alone, and the layout guard in workspace-state.test.ts pins that no tracked entry can ever
875
- * sit under a shared prefix. Trailing slash kept on every entry, as the table spells directories. */
876
- export const SHARED_STATE_PATHS: readonly string[] = STATE_GROUPS.flatMap((group) => {
877
- const files = WORKSPACE_STATE_FILES.filter((file) => stateGroupOf(file) === group);
878
- return files.some((file) => file.versioned === true)
879
- ? files.filter((file) => file.versioned !== true).map((file) => file.path)
880
- : [`${STATE_GROUP_DIR[group]}/`];
881
- });
882
-
883
- /* THE SLICE DESKTOP-SYNC COPIES DOWN, ordinary state and the records that bind this sandbox to its owner,
884
- * minus anything that opted out (see `backup` on the interface).
885
- *
886
- * The sync used to ignore `.intentic` WHOLE, which is the same conflation the `backup` flag exists to undo: the
887
- * dir holds credentials, so the dir was excluded, so a sandbox going away also took every persona, skill,
888
- * automation, draft and transcript the owner had. This is the list that makes the owner's machine an actual
889
- * backup instead of a copy of the source tree only.
890
- *
891
- * It is deliberately NOT the same as the export bundle. A bundle asks what may be reconstituted somewhere else;
892
- * this asks what the owner may keep. `ownership` is the entries where those differ, and it is in here. */
893
- export const BACKED_UP_STATE_PATHS: readonly string[] = WORKSPACE_STATE_FILES.filter(
894
- (file) => file.backup !== false && (file.portability === "carry" || file.portability === "identity"),
895
- ).map((file) => file.path);
896
-
897
- /* Its complement, which is what a sync ignore list actually needs: everything under the state dir that must NOT
898
- * come down. Derived from the same predicate rather than listed, so a store added tomorrow is excluded until its
899
- * class says otherwise, the same default-deny the search floor and the portability classes are built on. */
900
- export const UNBACKED_STATE_PATHS: readonly string[] = WORKSPACE_STATE_FILES.filter((file) => !BACKED_UP_STATE_PATHS.includes(file.path)).map(
901
- (file) => file.path,
902
- );
903
-
904
- /* THE ONE WAY AN EXTENSION NAMES ITS SCRATCH HOME, `.intentic/runtime/extensions/<id>`, workspace-relative
905
- * and forward-slash so the browser bundle can hold it too; callers join it onto whatever root is in force.
906
- *
907
- * It exists for the reason statePath does one table over: before it, every gateway spelled the layout itself
908
- * and one extension (deployments) simply didn't, minting `komodo.json` at the `.intentic` root where nothing
909
- * classified it. An extension that composes through this helper cannot land outside its own directory, so the
910
- * runtime/ entry's `derived` covers whatever it writes tomorrow. Extension ids are validated slugs already;
911
- * the replace is defence in depth against a path ever being built from something else. */
912
- export const extensionRuntimeDir = (extension: string): string =>
913
- `${STATE_GROUP_DIR.local}/runtime/extensions/${extension.replaceAll(/[^a-zA-Z0-9._-]/g, "_")}`;
914
-
915
- /* The manifests whose problems the unreadable-manifest notice SHOWS, the handful a person hand-edits, and the
916
- * one fact that decides it is already in the table above.
917
- *
918
- * Every store reads through the same `jsonFile`, so every store reports what it could not make sense of, and for
919
- * a long time the notice showed all of them. That is wrong twice over. Its advice, fix the file and this clears
920
- * on its own, is addressed to somebody holding an editor, which is true of `settings.json` and false of a
921
- * daemon-written LEDGER nobody opens: a run history that stopped matching a schema the build tightened is not a
922
- * mistake the owner made, and the card asked them to repair sixty kilobytes of machine JSON by hand. Worse, a
923
- * file that reports into the notice without feeding the notice's QUERY leaves a complaint no write can refresh,
924
- * so it sits on screen until the daemon restarts, which is exactly how the workflow ledger's entry became
925
- * permanent furniture.
926
- *
927
- * Both follow from one rule, which is why this derives rather than lists: a file's problems are shown IFF a write
928
- * to that file refreshes the notice. Declaring `manifests` in `invalidates` is the entire opt-in, so the edit
929
- * that puts a file on the card is the same edit that keeps it current, and neither can be done without the
930
- * other. A ledger that breaks still falls back and still sets its unreadable bytes aside on the next write
931
- * (store/json-file.ts), it just stops asking the owner to fix it. */
932
- export const REPORTED_MANIFEST_PATHS: readonly string[] = WORKSPACE_STATE_FILES.filter((file) => file.invalidates.includes("manifests")).map(
933
- (file) => file.path,
934
- );
935
-
936
- // Accepts either separator, like isLockedWorkspacePath below: the daemon holds these as platform paths and makes
937
- // them relative at the last moment, and normalizing at each call site is the one that eventually gets forgotten.
938
- export const isReportedManifest = (relPath: string): boolean => REPORTED_MANIFEST_PATHS.includes(relPath.replaceAll("\\", "/"));
939
-
940
- /* THE DAEMON'S OWN CONTROL PLANE, the entries directly under the workspace root's `.intentic/` that the file
941
- * API refuses to read, write, move or delete for anyone, the owner included (workspace/workspace-files.ts holds
942
- * the enforcement and the full reasoning for each name).
943
- *
944
- * The list lives HERE, in the package both sides import, because the browser has to draw the same rule the
945
- * daemon enforces. It didn't, and the gap was a small piece of theatre: the explorer listed `capabilities.json`
946
- * like any other file, opening it flashed a tab, the read came back with nothing there, and the tab closed
947
- * itself, a refusal acted out as a glitch. A file the app will not open should say so before it is clicked,
948
- * which takes a rule the explorer can consult, not a status code it can only react to.
949
- *
950
- * Naming these to the browser gives nothing away that the tree did not already publish, it listed them, sizes
951
- * and all. What stays behind the guard is the only thing that ever mattered: the bytes. */
952
- /* GROUP-RELATIVE NOW, and the one rule the regrouping did NOT simplify, worth saying because every other rule
953
- * over this tree collapsed to a prefix and this one could not. What the file API refuses to open cuts ACROSS the
954
- * groups: the capability manifest is `config`, the transcripts are `records`, the browser profiles are `local`,
955
- * and all of `identity` and `secrets` is in. That is not an accident of the grouping, it is a different question
956
- *, "would showing the bytes hand someone something" rather than "what kind of thing is this", so it keeps an
957
- * explicit list, just one that now names the folder each entry lives in. */
958
- export const LOCKED_STATE_ENTRIES: ReadonlySet<string> = new Set([
959
- "identity/owner.json",
960
- "identity/members.json",
961
- "identity/control-tokens.json",
962
- "config/capabilities.json",
963
- "secrets/ci.json",
964
- "secrets/auth",
965
- "records/sessions",
966
- "local/browser",
967
- /* The provider CLI's own home, which this table does not declare and so has no group to move into, it is
968
- * written by the agent's runtime rather than by any daemon store. It stays at the state dir's root, and the
969
- * two-segment match below still reaches it because a bare name joins to itself. Locked for the reason the
970
- * credential entries are: it holds a live session for whatever the agent is signed into. */
971
- "claude.json",
972
- ]);
973
-
974
- /* WHERE THE CLI'S PLAN FILES LAND, workspace-relative — and the one thing inside a locked entry that is not
975
- * the sandbox's own state, which is why it is declared here rather than beside the card that draws it.
976
- *
977
- * `~/.claude/plans` is a symlink onto this directory (sessions/session-store.ts links the SDK's conversation
978
- * state onto the workspace volume), so a plan file has a HARNESS-OWNED address: no guessing whether prose is a
979
- * plan, no threshold on length, the path says so.
980
- *
981
- * What lands there is a DOCUMENT ADDRESSED TO THE READER. `records/sessions` is locked because it holds the
982
- * provider's own conversation state; a plan is the opposite of that — the chat renders its full text into the
983
- * card asking the reader to approve it, so opening the file publishes nothing the transcript had not. Locked
984
- * anyway, the one link the card offers into the workspace landed on a padlock reading "it holds something only
985
- * the sandbox itself uses", about a document the sandbox had just asked the reader to approve. */
986
- export const PLAN_DOCUMENTS_DIR = `${STATE_DIR}/records/sessions/claude/plans`;
987
-
988
- /* WHICH locked entry a workspace-root-relative path belongs to, or undefined for a path that is not in the
989
- * control plane at all. Scoped deliberately tight, matching the guard: only the ROOT `.intentic` counts (a
990
- * repo's own nested one is ordinary content) and only these entries within it, subtrees included, so a new
991
- * provider dropped under `auth/` is covered without a second edit.
992
- *
993
- * The ROOT's own `.git` joins them. It is the pointer to the shadow history repo kept off the workspace so the
994
- * agent cannot rewrite its own past; a NESTED repo's `.git` is ordinary content and stays browsable.
995
- *
996
- * The ENTRY rather than a boolean, because the screen that reports a refusal has to say what the file holds and
997
- * where the thing inside it is actually managed, and it can only do that from the name of the entry the path
998
- * matched — never from the leaf, which is a Chromium cookie jar or a mint-fresh session id. Keeping that lookup
999
- * keyed on this function's answer is what stops the browser's sentences from drifting off the daemon's list, as
1000
- * they did through the regrouping: every one of them was still keyed on `sessions` and `auth` while the rule
1001
- * had moved to `records/sessions` and `secrets/auth`, so every locked file in the product fell through to the
1002
- * generic sentence and lost its way out.
1003
- *
1004
- * Accepts either slash so a caller holding a platform path doesn't have to normalize first. */
1005
- export const lockedWorkspaceEntry = (relPath: string): string | undefined => {
1006
- const segments = relPath.split(/[\\/]/).filter((segment) => segment !== "" && segment !== ".");
1007
- if (segments[0] === ".git") {
1008
- return ".git";
1009
- }
1010
- if (segments[0] !== STATE_DIR) {
1011
- return undefined;
1012
- }
1013
- const rel = segments.join("/");
1014
- if (rel === PLAN_DOCUMENTS_DIR || rel.startsWith(`${PLAN_DOCUMENTS_DIR}/`)) {
1015
- return undefined;
1016
- }
1017
- // Two segments, which covers both spellings in the set above: a grouped entry (`secrets/auth`) matches as
1018
- // written, and a bare root entry (`claude.json`) joins to itself because there is no second segment to add.
1019
- const entry = segments.slice(1, 3).join("/");
1020
- return LOCKED_STATE_ENTRIES.has(entry) ? entry : undefined;
1021
- };
1022
-
1023
- // Whether a path lands in that control plane, and so is refused by the file API and shown locked rather than
1024
- // opened. The question every guard asks; the entry above is for the one screen that has to name it.
1025
- export const isLockedWorkspacePath = (relPath: string): boolean => lockedWorkspaceEntry(relPath) !== undefined;
1026
-
1027
- /* THE LOCKED ENTRIES THE ROOT REPO TRACKS, refused by the file API, and diffable anyway.
1028
- *
1029
- * `capabilities.json` is the only one today and the whole reason this exists. Both of its rules are right on
1030
- * their own: it is `versioned`, because connecting this sandbox to a deployment orchestrator is the largest
1031
- * change anyone makes to what it can DO and that belongs in review; and it is locked, because a member who
1032
- * could PUT one through the generic file API would be granting themselves a capability the owner never
1033
- * approved. The lock was always about that WRITE, its credentials live in the vault, not in the file.
1034
- *
1035
- * Together, though, the second silently cancelled the first. The Changes panel listed the file (git tracks it,
1036
- * so `git status` reports it), and clicking the row asked a diff route that refuses every control-plane path,
1037
- * a 404 on the one surface `versioned` exists to produce. The bytes were already in `git log`, in every clone
1038
- * of the root repo and in the workspace search; only the review was missing.
1039
- *
1040
- * So the review surfaces ask THIS instead of the flat lock, and it derives from the same flag rather than
1041
- * naming the file, so marking another locked entry `versioned` cannot reproduce the contradiction. Every other
1042
- * surface, read, write, move, delete, publish, still asks `isLockedWorkspacePath` and still refuses.
1043
- *
1044
- * Accepts either slash, like the rule above it. */
1045
- export const isReviewableLockedPath = (relPath: string): boolean => {
1046
- const rel = relPath.replaceAll("\\", "/").replace(/^\.\//, "");
1047
- return isLockedWorkspacePath(rel) && VERSIONED_STATE_PATHS.some((path) => (path.endsWith("/") ? rel.startsWith(path) : rel === path));
1048
- };
1049
-
1050
- /* Every path this table declares, as a type. `as const` above is what makes it one, and it is what finally makes
1051
- * the first sentence of this file's header TRUE rather than aspirational.
1052
- *
1053
- * "The daemon builds its store paths from `path`" was the design; the code did not. `composition.ts` and twenty
1054
- * files beside it spelled the same layout a SECOND way, `join(root, ".intentic", "settings.json")`, with
1055
- * nothing tying the two spellings together. Rename a store's file and this table keeps declaring the old name:
1056
- * no error, no failing test, just a view that quietly stops refreshing, which is the exact failure the table was
1057
- * written to end and the exact way approvals went missing.
1058
- *
1059
- * So the daemon joins through `statePath` (workspace/state-paths.ts), which takes one of THESE and nothing else.
1060
- * A rename is now a compile error at every site that names the file, in both packages, or it is not a rename. */
1061
- export type WorkspaceStatePath = (typeof STATE_FILES)[number]["path"];
1062
-
1063
- /* The query keys a batch of changed paths makes stale, deduped and stable. The browser's `/events` handler calls
1064
- * this; keeping it here rather than in the web means the rule is unit-testable without a query client, and the
1065
- * daemon can assert against the same table.
1066
- *
1067
- * `contributed` is what the ACTIVATED extensions declared in `contributes.files`, passed in rather than
1068
- * imported, because which extensions are live is a browser fact this package has no way to know. It is a
1069
- * required argument for the same reason: an added second source that callers may forget is a source that
1070
- * silently does nothing, which is the failure this whole file exists to remove. Extension entries are unioned
1071
- * flat with the core ones, not layered over them: both lists describe the same fact about the same file, and a
1072
- * path can legitimately match one entry in each, a core prefix that invalidates nothing must not veto a
1073
- * narrower extension entry beneath it, or everything under one of the daemon's machine-state prefixes would be
1074
- * unreachable to extensions by construction. */
1075
- export const staleQueryKeys = (paths: readonly string[], contributed: readonly FileContribution[]): readonly string[] => [
1076
- ...new Set(
1077
- [...WORKSPACE_STATE_FILES, ...contributed]
1078
- .filter((file) => file.invalidates.length > 0 && paths.some((path) => path.startsWith(file.path)))
1079
- .flatMap((file) => file.invalidates),
1080
- ),
1081
- ];
1082
-
1083
- /* Every query key any watched file feeds, what a NEW /events connection invalidates wholesale (core's table
1084
- * plus the running extensions'). The file push is these keys' ONLY live feed, and a `workspaceChanged` frame
1085
- * produced while the stream was down is a frame nobody will ever resend, so each key's view would sit stale
1086
- * until the file's NEXT write, indefinitely for anything that settled while the browser was away. Re-asking on
1087
- * connect bounds the damage at one cheap read per key, which is what lets those views go entirely unpolled. */
1088
- export const fileBoundQueryKeys = (contributed: readonly FileContribution[]): readonly string[] => [
1089
- ...new Set([...WORKSPACE_STATE_FILES, ...contributed].flatMap((file) => file.invalidates)),
1090
- ];