@calliopelabs/cli 3.5.4 → 3.7.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 (311) hide show
  1. package/README.md +8 -0
  2. package/dist/acp/controls.d.ts +10 -0
  3. package/dist/acp/controls.d.ts.map +1 -0
  4. package/dist/acp/controls.js +81 -0
  5. package/dist/acp/controls.js.map +1 -0
  6. package/dist/acp.d.ts +21 -7
  7. package/dist/acp.d.ts.map +1 -1
  8. package/dist/acp.js +139 -23
  9. package/dist/acp.js.map +1 -1
  10. package/dist/bin.d.ts.map +1 -1
  11. package/dist/bin.js +28 -8
  12. package/dist/bin.js.map +1 -1
  13. package/dist/build-identity.d.ts +27 -0
  14. package/dist/build-identity.d.ts.map +1 -0
  15. package/dist/build-identity.js +32 -0
  16. package/dist/build-identity.js.map +1 -0
  17. package/dist/build-metadata.json +1 -0
  18. package/dist/execution/authority.d.ts +4 -1
  19. package/dist/execution/authority.d.ts.map +1 -1
  20. package/dist/execution/authority.js +23 -7
  21. package/dist/execution/authority.js.map +1 -1
  22. package/dist/execution/child-grants.d.ts +2 -0
  23. package/dist/execution/child-grants.d.ts.map +1 -1
  24. package/dist/execution/child-grants.js +19 -4
  25. package/dist/execution/child-grants.js.map +1 -1
  26. package/dist/execution/delegated.d.ts +14 -0
  27. package/dist/execution/delegated.d.ts.map +1 -0
  28. package/dist/execution/delegated.js +66 -0
  29. package/dist/execution/delegated.js.map +1 -0
  30. package/dist/execution/files.js +6 -6
  31. package/dist/execution/files.js.map +1 -1
  32. package/dist/execution/guard.d.ts +5 -0
  33. package/dist/execution/guard.d.ts.map +1 -1
  34. package/dist/execution/guard.js +31 -16
  35. package/dist/execution/guard.js.map +1 -1
  36. package/dist/execution/index.d.ts +4 -0
  37. package/dist/execution/index.d.ts.map +1 -1
  38. package/dist/execution/index.js +4 -0
  39. package/dist/execution/index.js.map +1 -1
  40. package/dist/execution/ledger-cli.d.ts +2 -1
  41. package/dist/execution/ledger-cli.d.ts.map +1 -1
  42. package/dist/execution/ledger-cli.js +51 -14
  43. package/dist/execution/ledger-cli.js.map +1 -1
  44. package/dist/execution/ledger-protocol.d.ts +6 -2
  45. package/dist/execution/ledger-protocol.d.ts.map +1 -1
  46. package/dist/execution/ledger-protocol.js +110 -24
  47. package/dist/execution/ledger-protocol.js.map +1 -1
  48. package/dist/execution/ledger-server.d.ts +13 -0
  49. package/dist/execution/ledger-server.d.ts.map +1 -1
  50. package/dist/execution/ledger-server.js +57 -13
  51. package/dist/execution/ledger-server.js.map +1 -1
  52. package/dist/execution/ledger-tunnel.d.ts +50 -0
  53. package/dist/execution/ledger-tunnel.d.ts.map +1 -0
  54. package/dist/execution/ledger-tunnel.js +307 -0
  55. package/dist/execution/ledger-tunnel.js.map +1 -0
  56. package/dist/execution/ledger.d.ts +4 -0
  57. package/dist/execution/ledger.d.ts.map +1 -1
  58. package/dist/execution/ledger.js +30 -4
  59. package/dist/execution/ledger.js.map +1 -1
  60. package/dist/execution/parent-accounting.d.ts +41 -0
  61. package/dist/execution/parent-accounting.d.ts.map +1 -0
  62. package/dist/execution/parent-accounting.js +52 -0
  63. package/dist/execution/parent-accounting.js.map +1 -0
  64. package/dist/execution/parent-budget.d.ts +25 -0
  65. package/dist/execution/parent-budget.d.ts.map +1 -0
  66. package/dist/execution/parent-budget.js +102 -0
  67. package/dist/execution/parent-budget.js.map +1 -0
  68. package/dist/execution/project-spend.d.ts.map +1 -1
  69. package/dist/execution/project-spend.js +35 -5
  70. package/dist/execution/project-spend.js.map +1 -1
  71. package/dist/execution/remote-checkpoint.d.ts +15 -0
  72. package/dist/execution/remote-checkpoint.d.ts.map +1 -0
  73. package/dist/execution/remote-checkpoint.js +165 -0
  74. package/dist/execution/remote-checkpoint.js.map +1 -0
  75. package/dist/execution/remote-ledger.d.ts +12 -2
  76. package/dist/execution/remote-ledger.d.ts.map +1 -1
  77. package/dist/execution/remote-ledger.js +53 -21
  78. package/dist/execution/remote-ledger.js.map +1 -1
  79. package/dist/execution/types.d.ts +23 -5
  80. package/dist/execution/types.d.ts.map +1 -1
  81. package/dist/execution/types.js.map +1 -1
  82. package/dist/goals/supervised.js +2 -2
  83. package/dist/goals/supervised.js.map +1 -1
  84. package/dist/headless.d.ts +2 -6
  85. package/dist/headless.d.ts.map +1 -1
  86. package/dist/headless.js +17 -21
  87. package/dist/headless.js.map +1 -1
  88. package/dist/improvement/actions.d.ts +3 -4
  89. package/dist/improvement/actions.d.ts.map +1 -1
  90. package/dist/improvement/actions.js +10 -7
  91. package/dist/improvement/actions.js.map +1 -1
  92. package/dist/improvement/capabilities.d.ts +54 -0
  93. package/dist/improvement/capabilities.d.ts.map +1 -0
  94. package/dist/improvement/capabilities.js +44 -0
  95. package/dist/improvement/capabilities.js.map +1 -0
  96. package/dist/improvement/cli.d.ts +1 -1
  97. package/dist/improvement/cli.d.ts.map +1 -1
  98. package/dist/improvement/cli.js +29 -3
  99. package/dist/improvement/cli.js.map +1 -1
  100. package/dist/improvement/host-capabilities.d.ts +119 -0
  101. package/dist/improvement/host-capabilities.d.ts.map +1 -0
  102. package/dist/improvement/host-capabilities.js +18 -0
  103. package/dist/improvement/host-capabilities.js.map +1 -0
  104. package/dist/improvement/index.d.ts +6 -0
  105. package/dist/improvement/index.d.ts.map +1 -1
  106. package/dist/improvement/index.js +6 -0
  107. package/dist/improvement/index.js.map +1 -1
  108. package/dist/improvement/proposal-hash.d.ts +3 -0
  109. package/dist/improvement/proposal-hash.d.ts.map +1 -0
  110. package/dist/improvement/proposal-hash.js +5 -0
  111. package/dist/improvement/proposal-hash.js.map +1 -0
  112. package/dist/improvement/review-contract.d.ts +32 -0
  113. package/dist/improvement/review-contract.d.ts.map +1 -0
  114. package/dist/improvement/review-contract.js +62 -0
  115. package/dist/improvement/review-contract.js.map +1 -0
  116. package/dist/improvement/review-requests.d.ts +72 -0
  117. package/dist/improvement/review-requests.d.ts.map +1 -0
  118. package/dist/improvement/review-requests.js +63 -0
  119. package/dist/improvement/review-requests.js.map +1 -0
  120. package/dist/improvement/source-changes.d.ts +78 -0
  121. package/dist/improvement/source-changes.d.ts.map +1 -0
  122. package/dist/improvement/source-changes.js +91 -0
  123. package/dist/improvement/source-changes.js.map +1 -0
  124. package/dist/improvement/task-outcomes.d.ts +82 -0
  125. package/dist/improvement/task-outcomes.d.ts.map +1 -0
  126. package/dist/improvement/task-outcomes.js +72 -0
  127. package/dist/improvement/task-outcomes.js.map +1 -0
  128. package/dist/index.d.ts +10 -0
  129. package/dist/index.d.ts.map +1 -1
  130. package/dist/index.js +6 -0
  131. package/dist/index.js.map +1 -1
  132. package/dist/isolation/contracts.d.ts +13 -0
  133. package/dist/isolation/contracts.d.ts.map +1 -1
  134. package/dist/isolation/contracts.js +9 -1
  135. package/dist/isolation/contracts.js.map +1 -1
  136. package/dist/isolation/coordinator.d.ts.map +1 -1
  137. package/dist/isolation/coordinator.js +4 -0
  138. package/dist/isolation/coordinator.js.map +1 -1
  139. package/dist/isolation/process.d.ts.map +1 -1
  140. package/dist/isolation/process.js +3 -1
  141. package/dist/isolation/process.js.map +1 -1
  142. package/dist/isolation/worktree.d.ts +9 -1
  143. package/dist/isolation/worktree.d.ts.map +1 -1
  144. package/dist/isolation/worktree.js +8 -3
  145. package/dist/isolation/worktree.js.map +1 -1
  146. package/dist/memory.d.ts +5 -3
  147. package/dist/memory.d.ts.map +1 -1
  148. package/dist/memory.js +8 -6
  149. package/dist/memory.js.map +1 -1
  150. package/dist/migration/assessment-contract.d.ts +60 -0
  151. package/dist/migration/assessment-contract.d.ts.map +1 -0
  152. package/dist/migration/assessment-contract.js +132 -0
  153. package/dist/migration/assessment-contract.js.map +1 -0
  154. package/dist/migration/assessment-schema.d.ts +19 -0
  155. package/dist/migration/assessment-schema.d.ts.map +1 -0
  156. package/dist/migration/assessment-schema.js +43 -0
  157. package/dist/migration/assessment-schema.js.map +1 -0
  158. package/dist/migration/assessment.d.ts +159 -0
  159. package/dist/migration/assessment.d.ts.map +1 -0
  160. package/dist/migration/assessment.js +219 -0
  161. package/dist/migration/assessment.js.map +1 -0
  162. package/dist/migration/cli.d.ts +6 -0
  163. package/dist/migration/cli.d.ts.map +1 -0
  164. package/dist/migration/cli.js +101 -0
  165. package/dist/migration/cli.js.map +1 -0
  166. package/dist/migration/evidence.d.ts +27 -0
  167. package/dist/migration/evidence.d.ts.map +1 -0
  168. package/dist/migration/evidence.js +124 -0
  169. package/dist/migration/evidence.js.map +1 -0
  170. package/dist/migration/example.d.ts +33 -0
  171. package/dist/migration/example.d.ts.map +1 -0
  172. package/dist/migration/example.js +28 -0
  173. package/dist/migration/example.js.map +1 -0
  174. package/dist/migration/index.d.ts +21 -0
  175. package/dist/migration/index.d.ts.map +1 -0
  176. package/dist/migration/index.js +15 -0
  177. package/dist/migration/index.js.map +1 -0
  178. package/dist/migration/inventory.d.ts +70 -0
  179. package/dist/migration/inventory.d.ts.map +1 -0
  180. package/dist/migration/inventory.js +233 -0
  181. package/dist/migration/inventory.js.map +1 -0
  182. package/dist/migration/schema.d.ts +61 -0
  183. package/dist/migration/schema.d.ts.map +1 -0
  184. package/dist/migration/schema.js +76 -0
  185. package/dist/migration/schema.js.map +1 -0
  186. package/dist/migration/verification.d.ts +146 -0
  187. package/dist/migration/verification.d.ts.map +1 -0
  188. package/dist/migration/verification.js +260 -0
  189. package/dist/migration/verification.js.map +1 -0
  190. package/dist/orchestration/actions.d.ts +2 -0
  191. package/dist/orchestration/actions.d.ts.map +1 -1
  192. package/dist/orchestration/actions.js.map +1 -1
  193. package/dist/orchestration/artifact-host.d.ts +46 -0
  194. package/dist/orchestration/artifact-host.d.ts.map +1 -0
  195. package/dist/orchestration/artifact-host.js +64 -0
  196. package/dist/orchestration/artifact-host.js.map +1 -0
  197. package/dist/orchestration/coordinator-actions.d.ts +1 -1
  198. package/dist/orchestration/coordinator-actions.d.ts.map +1 -1
  199. package/dist/orchestration/coordinator-actions.js +5 -3
  200. package/dist/orchestration/coordinator-actions.js.map +1 -1
  201. package/dist/orchestration/coordinator-types.d.ts +23 -2
  202. package/dist/orchestration/coordinator-types.d.ts.map +1 -1
  203. package/dist/orchestration/coordinator.d.ts +5 -0
  204. package/dist/orchestration/coordinator.d.ts.map +1 -1
  205. package/dist/orchestration/coordinator.js +30 -13
  206. package/dist/orchestration/coordinator.js.map +1 -1
  207. package/dist/orchestration/execution-cli.d.ts +1 -1
  208. package/dist/orchestration/execution-cli.d.ts.map +1 -1
  209. package/dist/orchestration/execution-cli.js +29 -6
  210. package/dist/orchestration/execution-cli.js.map +1 -1
  211. package/dist/orchestration/execution-journal.d.ts.map +1 -1
  212. package/dist/orchestration/execution-journal.js +79 -6
  213. package/dist/orchestration/execution-journal.js.map +1 -1
  214. package/dist/orchestration/execution-store.d.ts +5 -1
  215. package/dist/orchestration/execution-store.d.ts.map +1 -1
  216. package/dist/orchestration/execution-store.js +66 -5
  217. package/dist/orchestration/execution-store.js.map +1 -1
  218. package/dist/orchestration/execution.d.ts.map +1 -1
  219. package/dist/orchestration/execution.js +37 -10
  220. package/dist/orchestration/execution.js.map +1 -1
  221. package/dist/orchestration/index.d.ts +6 -0
  222. package/dist/orchestration/index.d.ts.map +1 -1
  223. package/dist/orchestration/index.js +6 -0
  224. package/dist/orchestration/index.js.map +1 -1
  225. package/dist/orchestration/interruption.d.ts +10 -0
  226. package/dist/orchestration/interruption.d.ts.map +1 -0
  227. package/dist/orchestration/interruption.js +38 -0
  228. package/dist/orchestration/interruption.js.map +1 -0
  229. package/dist/orchestration/question-contract.d.ts +19 -0
  230. package/dist/orchestration/question-contract.d.ts.map +1 -0
  231. package/dist/orchestration/question-contract.js +21 -0
  232. package/dist/orchestration/question-contract.js.map +1 -0
  233. package/dist/orchestration/questions.d.ts +9 -0
  234. package/dist/orchestration/questions.d.ts.map +1 -0
  235. package/dist/orchestration/questions.js +75 -0
  236. package/dist/orchestration/questions.js.map +1 -0
  237. package/dist/orchestration/reviewed-ledger.d.ts +23 -0
  238. package/dist/orchestration/reviewed-ledger.d.ts.map +1 -0
  239. package/dist/orchestration/reviewed-ledger.js +57 -0
  240. package/dist/orchestration/reviewed-ledger.js.map +1 -0
  241. package/dist/orchestration/routing.d.ts +3 -0
  242. package/dist/orchestration/routing.d.ts.map +1 -1
  243. package/dist/orchestration/routing.js +5 -1
  244. package/dist/orchestration/routing.js.map +1 -1
  245. package/dist/orchestration/source-candidates.d.ts +64 -0
  246. package/dist/orchestration/source-candidates.d.ts.map +1 -0
  247. package/dist/orchestration/source-candidates.js +95 -0
  248. package/dist/orchestration/source-candidates.js.map +1 -0
  249. package/dist/orchestration/validation.js +1 -1
  250. package/dist/orchestration/validation.js.map +1 -1
  251. package/dist/runlog.js +2 -2
  252. package/dist/runlog.js.map +1 -1
  253. package/dist/runtime/permissions.d.ts.map +1 -1
  254. package/dist/runtime/permissions.js +3 -2
  255. package/dist/runtime/permissions.js.map +1 -1
  256. package/dist/runtime/turn.d.ts +2 -0
  257. package/dist/runtime/turn.d.ts.map +1 -1
  258. package/dist/runtime/turn.js +21 -7
  259. package/dist/runtime/turn.js.map +1 -1
  260. package/dist/session-management/actions.js +1 -1
  261. package/dist/session-management/actions.js.map +1 -1
  262. package/dist/sessions/execution-binding.d.ts +8 -0
  263. package/dist/sessions/execution-binding.d.ts.map +1 -0
  264. package/dist/sessions/execution-binding.js +9 -0
  265. package/dist/sessions/execution-binding.js.map +1 -0
  266. package/dist/sessions/index.d.ts +1 -0
  267. package/dist/sessions/index.d.ts.map +1 -1
  268. package/dist/sessions/index.js +1 -0
  269. package/dist/sessions/index.js.map +1 -1
  270. package/dist/source-changes/writer.d.ts +77 -0
  271. package/dist/source-changes/writer.d.ts.map +1 -0
  272. package/dist/source-changes/writer.js +189 -0
  273. package/dist/source-changes/writer.js.map +1 -0
  274. package/dist/spawning/actions.d.ts +10 -1
  275. package/dist/spawning/actions.d.ts.map +1 -1
  276. package/dist/spawning/actions.js +26 -7
  277. package/dist/spawning/actions.js.map +1 -1
  278. package/dist/spawning/cli.js +1 -1
  279. package/dist/spawning/cli.js.map +1 -1
  280. package/dist/spawning/execution.d.ts.map +1 -1
  281. package/dist/spawning/execution.js +2 -0
  282. package/dist/spawning/execution.js.map +1 -1
  283. package/dist/spawning/types.d.ts +19 -6
  284. package/dist/spawning/types.d.ts.map +1 -1
  285. package/dist/spawning/validation.d.ts +16 -0
  286. package/dist/spawning/validation.d.ts.map +1 -1
  287. package/dist/spawning/validation.js +44 -8
  288. package/dist/spawning/validation.js.map +1 -1
  289. package/dist/storage.d.ts +5 -0
  290. package/dist/storage.d.ts.map +1 -1
  291. package/dist/storage.js +10 -1
  292. package/dist/storage.js.map +1 -1
  293. package/dist/supervision/contracts.js +4 -1
  294. package/dist/supervision/contracts.js.map +1 -1
  295. package/dist/tools.d.ts +1 -0
  296. package/dist/tools.d.ts.map +1 -1
  297. package/dist/tools.js +5 -0
  298. package/dist/tools.js.map +1 -1
  299. package/docs/README.md +66 -0
  300. package/docs/acp.md +228 -0
  301. package/docs/delegation-ledger.md +331 -0
  302. package/docs/improvement-cycles.md +304 -0
  303. package/docs/migration-assessment.md +113 -0
  304. package/docs/migration-example-plan.json +88 -0
  305. package/docs/migration-example-report.json +511 -0
  306. package/docs/migration-inventory.md +63 -0
  307. package/docs/migration-playbook.md +152 -0
  308. package/docs/migration-verification.md +177 -0
  309. package/docs/releases/3.6.0.md +43 -0
  310. package/docs/releases/3.7.0.md +53 -0
  311. package/package.json +11 -3
package/docs/acp.md ADDED
@@ -0,0 +1,228 @@
1
+ # Editors: Agent Client Protocol (ACP)
2
+
3
+ Calliope can run as an [Agent Client Protocol](https://agentclientprotocol.com)
4
+ agent, so ACP-speaking editors — [Zed](https://zed.dev), JetBrains IDEs, Neovim,
5
+ and others — can drive it as a coding agent without any Calliope-specific plugin.
6
+ One command, `calliope acp`, speaks JSON-RPC 2.0 over stdio.
7
+
8
+ ```bash
9
+ calliope acp
10
+ ```
11
+
12
+ The subcommand is not meant to be run by hand: the editor launches it, writes
13
+ JSON-RPC to its stdin, and reads notifications from its stdout. **stdout carries
14
+ the protocol; all logs go to stderr**, so nothing corrupts the stream.
15
+
16
+ It reuses the same agent core as everything else in Calliope — the provider chat
17
+ loop, the tool runtime, the pre-tool policy hook, and the audit run log — so an
18
+ ACP session behaves like a headless or interactive session, just driven by your
19
+ editor.
20
+
21
+ The maintained SDK validates protocol messages with the pinned Zod runtime.
22
+ The SDK package version is independent of the negotiated ACP version; this
23
+ integration continues to use stable ACP v1, not the experimental v2 entrypoint.
24
+ Incoming messages are bounded before schema validation: 64 nested levels, 16,384
25
+ values, 4,096 members per collection and 32 MiB of string data. The NDJSON
26
+ transport also enforces its 32 MiB message limit. Over-limit requests receive an invalid-parameters response without creating a
27
+ session or starting inference; oversized notifications are discarded and
28
+ oversized replies fail the waiting request.
29
+
30
+ ## What works (baseline conformance)
31
+
32
+ The [baseline ACP agent surface](https://agentclientprotocol.com/protocol/overview#agent)
33
+ is implemented and tested against the official TypeScript SDK
34
+ (`@agentclientprotocol/sdk`, stable ACP v1 entrypoint):
35
+
36
+ | Method / flow | Status | Notes |
37
+ |---|---|---|
38
+ | `initialize` | ✅ | Negotiates protocol v1; advertises agent capabilities |
39
+ | `authenticate` | ✅ | No-op — Calliope authenticates via locally-configured provider keys |
40
+ | `session/new` | ✅ | One Calliope session per ACP session; the session id round-trips |
41
+ | `session/load` | ✅ | Restores a saved session in its project and replays its history (see *Loading a session*) |
42
+ | `session/set_mode` | ✅ | Session-scoped Work and Plan modes |
43
+ | `session/set_config_option` | ✅ | Selects a discovered model for this session |
44
+ | `session/prompt` | ✅ | Drives the agent loop (chat + tools) to a stop reason |
45
+ | `session/cancel` | ✅ | Aborts provider I/O and pending permission waits; returns `stopReason: cancelled` |
46
+ | `session/update` (streaming) | ✅ | `agent_message_chunk`, `tool_call`, `tool_call_update`; `user_message_chunk` in a replay |
47
+ | `session/request_permission` | ✅ | Asked for mutating/destructive tools (see below) |
48
+ | `fs/read_text_file`, `fs/write_text_file` | ✅ | Preferred for file tools when the client advertises `fs` |
49
+
50
+ ### Capability matrix
51
+
52
+ **Advertised by Calliope (agent):**
53
+
54
+ | Capability | Value |
55
+ |---|---|
56
+ | `promptCapabilities.image` / `audio` / `embeddedContext` | `false` — text and resource links only |
57
+ | `loadSession` | `true`; see *Loading a session* |
58
+ | `authMethods` | `[]` — no authentication required |
59
+
60
+ **Consumed from the client (editor):**
61
+
62
+ | Client capability | Effect |
63
+ |---|---|
64
+ | `fs.readTextFile` | `read_file` / `edit_file` read the editor's buffer instead of disk |
65
+ | `fs.writeTextFile` | `write_file` / `edit_file` write through the editor instead of disk |
66
+ | `requestPermission` | Used to gate mutating tools; falls back to *deny* if unavailable |
67
+ | `terminal` | Not used yet — Calliope runs shell tools itself |
68
+
69
+ ### Permissions
70
+
71
+ Read-only tools (`read_file`, `list_files`, `glob`, `grep`, `web_search`,
72
+ `think`) run without asking. Tools that mutate state or that Calliope's risk model
73
+ flags for confirmation (`write_file`, `edit_file`, `shell`, `git`, `execute_code`,
74
+ and any high/critical-risk command) trigger a `session/request_permission` call so
75
+ your editor can prompt you. If the client can't handle a permission request, the
76
+ non-interactive default is to **deny** the mutating tool (read-only tools still
77
+ run).
78
+
79
+ Scope, **pre-tool hooks** and the external **policy hook** (the
80
+ [Zentinelle](./governance.md) integration point) run before the prompt and again
81
+ after approval. A denial prevents execution and is reported to the model.
82
+
83
+ `allow` approves once. For eligible file operations, `allow_always` means the
84
+ exact arguments and canonical path in this ACP session for at most 24 hours;
85
+ changed arguments or policy configuration need a new approval. Shell, code and
86
+ plugin operations offer only once/reject. Unknown option IDs are rejected.
87
+ Session grants disappear on process restart; existing project grants may apply
88
+ but ACP does not create project grants. See [permissions](./permissions.md) for
89
+ scope, revocation and audit semantics.
90
+
91
+ ### Loading a session
92
+
93
+ `session/load` restores a session this agent saved, including after the agent or
94
+ its host restarts. Every turn already checkpoints a verified
95
+ [recovery snapshot](./session-recovery.md), and `session/new` commits the first
96
+ one, so a session that was never prompted loads too.
97
+
98
+ - Pass the ID from `session/new` and the same `cwd`. A session loads only in its
99
+ recorded project; an unknown ID or a missing or damaged snapshot is refused.
100
+ - Before responding, Calliope replays the conversation as `session/update`
101
+ notifications: `user_message_chunk`, `agent_message_chunk`, `tool_call`, then a
102
+ `tool_call_update` carrying the recorded result. The system prompt is not
103
+ replayed.
104
+ - A tool call without a recorded result is closed as an unknown outcome and
105
+ replays as `failed`, as do recorded tool errors. No tool or inference is
106
+ replayed; an `agent_thought_chunk` says so when work was interrupted or
107
+ retention omitted older messages.
108
+ - A load is refused while a prompt runs in that session. Provider and model
109
+ preferences resolve for `cwd` as they do for `session/new`, with any explicit
110
+ saved ACP model selection applied to that session. Session approvals do not
111
+ survive a restart.
112
+
113
+ ### Session modes and models
114
+
115
+ New and loaded sessions return `modes` and `configOptions`. `session/set_mode`
116
+ is advertised through `agentCapabilities._meta.calliopeSessionControls.version: 1` and
117
+ selects `work` (normal permissions and confirmations) or `plan` (the core's
118
+ read-only planning tools). Plan mode refuses workspace mutation, shell/code
119
+ execution and other non-planning tools before effects, including editor-buffer
120
+ writes. Planning may still write native conversation/audit state. Returning to
121
+ Work does not grant permission to bypass project policy or a parent allowance.
122
+
123
+ Model selection uses stable ACP v1 `session/set_config_option`, with
124
+ `configId: "model"`; the older `session/set_model` method is not used. Select an
125
+ advertised value, or `default` to use the configured preference. Options come
126
+ from live model discovery for the session's resolved provider. Discovery is
127
+ bounded to five seconds and may use its current cache; unavailable discovery
128
+ does not invent selectable models. It may query provider catalog metadata when
129
+ creating/loading a session or changing its model, but does not run inference.
130
+
131
+ Mode and explicit model selections are stored with the native session and
132
+ survive `session/load`. Changes affect no other session or global/project
133
+ configuration. Busy sessions refuse changes; stale or damaged control state
134
+ requires reload or restoration. Delegated sessions retain parent model control
135
+ and refuse independent model selection. Mode changes recheck their live parent
136
+ authority, and every subsequent tool/model request retains native admission.
137
+
138
+ ### Client-side filesystem
139
+
140
+ When your editor advertises the `fs` capability, Calliope routes `read_file`,
141
+ `write_file`, and `edit_file` through the editor's `fs/read_text_file` and
142
+ `fs/write_text_file` rather than touching local disk. This is the marquee ACP
143
+ behavior: edits apply to the buffer you are actually looking at — including
144
+ **unsaved changes** — instead of the last-saved bytes on disk. Without the `fs`
145
+ capability, file tools use local disk as usual.
146
+
147
+ ### Audit
148
+
149
+ Every ACP session writes the same tamper-evident audit run log as any other
150
+ Calliope session, tagged `mode: acp` in its `run_start` event. Inspect one with
151
+ `calliope replay <sessionId>` (see [governance](./governance.md)).
152
+
153
+ ## Configuring your editor
154
+
155
+ The provider and model come from your Calliope config (`defaultProvider` /
156
+ `defaultModel`) or the usual `*_API_KEY` environment variables — configure those
157
+ first (`calliope --setup`), exactly as for interactive use.
158
+
159
+ ### Zed
160
+
161
+ Add an agent server to your Zed `settings.json`. Point it at the `calliope`
162
+ binary (or `node /absolute/path/to/dist/bin.js`) with the `acp` argument:
163
+
164
+ ```json
165
+ {
166
+ "agent_servers": {
167
+ "Calliope": {
168
+ "command": "calliope",
169
+ "args": ["acp"],
170
+ "env": {
171
+ "ANTHROPIC_API_KEY": "sk-ant-..."
172
+ }
173
+ }
174
+ }
175
+ }
176
+ ```
177
+
178
+ Then pick **Calliope** from the agent panel's agent menu. See Zed's
179
+ [External Agents](https://zed.dev/docs/ai/external-agents) docs.
180
+
181
+ ### JetBrains
182
+
183
+ JetBrains IDEs speak ACP through the AI Assistant / external-agent integration.
184
+ Register an external ACP agent with the command `calliope` and argument `acp`
185
+ (and the provider key in the environment), then select Calliope as the agent.
186
+ The exact settings path varies by IDE version; consult your IDE's ACP/external
187
+ agent documentation.
188
+
189
+ ### Any ACP client
190
+
191
+ Any client that can launch a stdio ACP agent works the same way: run the command
192
+ `calliope acp` with a configured provider key in the environment.
193
+
194
+ ## Not yet done
195
+
196
+ - **Registry listing.** Submitting Calliope to the public ACP agent registry is
197
+ deferred to a later release.
198
+ - **MCP servers over ACP.** `session/new` and `session/load` accept an
199
+ `mcpServers` list; Calliope ignores it for now and uses its own MCP configuration.
200
+ - **Terminals, images, and audio** in prompts/tool calls.
201
+
202
+ ## Verification status
203
+
204
+ Code-level conformance is tested against the official ACP TypeScript SDK: the
205
+ handshake, session lifecycle, streaming updates, the permission round-trip (grant
206
+ and deny), mid-prompt cancellation, and client-side filesystem delegation are all
207
+ covered by in-process tests that drive the SDK's client against the agent
208
+ (`tests/acp.test.ts`, `tests/acp-fs-delegate.test.ts`). `tests/acp-stdio.test.ts`
209
+ runs the built CLI over stdio, kills it after a turn and loads the session in a
210
+ new process. A live editor smoke test
211
+ in Zed and JetBrains is pending and tracked on the release checklist.
212
+
213
+ ## Cancellation and instructions
214
+
215
+ Each session owns one active prompt. Concurrent prompts in the same session are
216
+ rejected; a completed cancellation permits a new prompt. Late permission replies
217
+ cannot authorize tools from a cancelled turn. Cancellation preserves assistant /
218
+ tool-result pairing for the next request. It cannot undo completed writes or
219
+ retract remote operations; see [cancellation limits](./features.md#cancellation).
220
+
221
+ Trusted [repository instructions](./instructions.md) load from the session's
222
+ `cwd` when the session is created.
223
+
224
+ ACP forwards append-only assistant chunks. A partial stream failure returns the
225
+ existing JSON-RPC error without automatically repeating those chunks; an explicit
226
+ later prompt continues from committed conversation state. Bounded tool output
227
+ is available locally through `calliope session outputs SESSION_ID --json`. See
228
+ [streaming and output storage](streaming.md); no ACP message schema is changed.
@@ -0,0 +1,331 @@
1
+ # Delegation ledger (`delegation-ledger/v1`)
2
+
3
+ One parent execution allowance, shared with children that run in other processes or on other
4
+ hosts (#415). The authority is the existing reservation ledger (`src/execution/ledger.ts`):
5
+ requests are charged before dispatch, every ancestor is charged, child accounts come from
6
+ `child_grant` events, original deadlines hold, and unknown outcomes never restore capacity. This
7
+ protocol serves that ledger; it adds no second set of budget rules.
8
+
9
+ ## Placement
10
+
11
+ The user chooses where a run's ledger lives:
12
+
13
+ - **local**: the parent CLI serves its own ledger from the user's machine or container.
14
+ - **astrolift**: Astrolift runs the same `calliope ledger serve` as a durable managed service, so
15
+ children in pods, restarts and disconnects never lose reservations.
16
+
17
+ Children only receive a URL and a scoped token.
18
+
19
+ ## Serve
20
+
21
+ ```sh
22
+ calliope ledger serve --budget RUNS/<run>/budget --project /path/to/project \
23
+ --token-file /private/parent.token [--host 127.0.0.1] [--port 0]
24
+ ```
25
+
26
+ It prints `{"protocol":"delegation-ledger/v1","url":...,"runId":...}` once listening. The parent
27
+ token goes to `--token-file` (created new, mode 0600) and is never printed. Server state (signing
28
+ key, grant epochs) lives in a private sibling directory, never inside the budget directory.
29
+
30
+ ## Serve a reviewed native run
31
+
32
+ ```sh
33
+ calliope ledger serve-reviewed --run RUN_ID --agent AGENT_ID \
34
+ --max-output-tokens 1024 --project /path/to/project \
35
+ --token-file /private/owner.token
36
+ ```
37
+
38
+ This mode calls `prepareReviewedLedger`, reuses the run's native permission gates,
39
+ original budget, parent funding and deadline, and serves only the selected agent's
40
+ subtree. The token file must be outside the project in a private canonical directory;
41
+ it is created exclusively and never printed. Output includes the owner, original
42
+ deadline and versioned reviewed-host capability. SIGINT/SIGTERM close the listener.
43
+ Failed credential delivery also closes it without replacing an existing file.
44
+ Library hosts can call `prepareReviewedLedger(cwd, runId, agentId, maxOutputTokens,
45
+ options)` for the unbound server and private credential. They control where it listens.
46
+
47
+ Version 2 credentials bind the owner scope and exact native run review. Older
48
+ servers reject that token version; current raw-ledger endpoints reject its reviewed
49
+ authority binding. Child credentials retain that binding. A sibling owner endpoint
50
+ cannot accept the token, and reservations, settlements and revocations enforce the
51
+ selected subtree. Each new request also checks the target account's native admission,
52
+ stop/escalation state, explicit reviewed provider/model choices and the host's
53
+ output cap. The provider/model check uses the current admitted graph and runs
54
+ again under the ledger writer lock before a new reservation commits. Existing requests can still settle
55
+ after owner cancellation; grant revocation and token expiry retain their existing
56
+ semantics.
57
+
58
+ The HTTP grant operation only returns credentials for an **exact, already admitted**
59
+ native child grant. It cannot create a proposal, approve children, bypass native
60
+ depth/count limits or promote an interrupted ledger grant into the execution graph.
61
+ Use the existing native proposal review/admission flow first. Reissuing a credential
62
+ preserves its account, deadline and all recorded spending; revoked grants stay revoked.
63
+
64
+ All owners of a run share its private signing key and revocation history. A native
65
+ writer lock serializes revocations from separate processes; only confirmed dead locks
66
+ are reclaimed. Malformed, missing, public or linked revocation/key files are refused.
67
+ New keys initialize an empty revocation history once. A retained legacy key without
68
+ that history requires verified restoration or an explicit owner-managed credential
69
+ rotation; opening it never silently treats missing revocations as an empty history.
70
+
71
+ This is reviewed ledger hosting, not automatic Cykick/Astrolift enrollment. Remote
72
+ workspace identity, dispatcher credential delivery, task-attempt ownership, transport
73
+ reachability and any narrower Cykick file-mutation policy still need their native
74
+ bindings. A loopback listener does not make a desktop reachable from a remote pod.
75
+
76
+ ## Run a delegated child
77
+
78
+ A host (Cy, an Astrolift task) grants the child, writes its scoped token to a private file and
79
+ starts a headless run or native ACP process:
80
+
81
+ ```sh
82
+ calliope --headless --json --ledger-url URL --ledger-token-file /private/child.token \
83
+ --ledger-agent CHILD_ACCOUNT "objective"
84
+
85
+ calliope acp --ledger-url URL --ledger-token-file /private/child.token \
86
+ --ledger-agent CHILD_ACCOUNT
87
+ ```
88
+
89
+ The turn runs under `ExecutionGuard` with the parent's ledger: the child's tools, paths, deadline
90
+ and budget come from its grant, and every provider request is reserved and settled with the
91
+ parent. A revoked or unknown grant, or an unreachable parent, stops the child before any turn.
92
+ The three flags go together, using separate flag/value arguments. Partial, repeated,
93
+ unknown or equals-form ledger flags fail before execution; they never select an
94
+ undelegated fallback.
95
+
96
+ ## Operations
97
+
98
+ `POST /v1/<op>` with `Authorization: Bearer <token>` and a JSON body.
99
+
100
+ | Op | Who | Effect |
101
+ | --- | --- | --- |
102
+ | `hello` | any | protocol and operations |
103
+ | `journal` | any | the full hash-chained history (`manifest`, `events`) |
104
+ | `execution` | account owner | verify `{agentId, project: {root, key}}` against the retained owner grant and return its native workspace binding |
105
+ | `reserve` | owner of `reservation.agentId` | charge before dispatch; same id replays the original admission |
106
+ | `settle` | owner of the reserved request | record usage or an outcome; same settlement replays |
107
+ | `grant` | parent, or a child for its own accounts | allocate child accounts; returns the child's scoped token |
108
+ | `revoke` | parent | permanently fence a grant and every descendant |
109
+
110
+ A token may act for its accounts and their descendants only. A child cannot charge a sibling or
111
+ the root, cannot mint a root allowance, and a revoked grant cannot be reissued. Errors carry the
112
+ ledger's codes (`budget`, `deadline`, `authority`, `conflict`, `limit`, `locked`, `unavailable`).
113
+
114
+ Admission rechecks token expiry and grant revocation while holding the ledger's
115
+ writer lock, immediately before committing a reservation or nested grant. A
116
+ request queued before revocation cannot acquire authority when the lock opens.
117
+
118
+ An embedded owner can also supply `createLedgerServer({ledger, cwd, state,
119
+ assertAuthority: execution.assertAuthority})`, using the handle returned by
120
+ `prepareAgentExecution`. The server rechecks this trusted callback before new
121
+ admission and under the writer lock, including grant reissue. Cancelling the
122
+ native reviewed run then fences remote reservations and grants even before a
123
+ coordinator journal exists. Once the journal exists, completing the run or stopping
124
+ the handle's selected agent (or an ancestor) through an explicit stop control also
125
+ fences new work. Reopening the handle does not bypass those controls; an independently active sibling remains
126
+ eligible under its own handle. These checks reuse native execution history.
127
+ The callback is host code, never a request argument.
128
+ The standalone `ledger serve --budget ...` command serves an explicitly selected
129
+ raw ledger; it does not infer a reviewed-run binding.
130
+
131
+ Owner cancellation, agent stops and run completion still permit authenticated
132
+ journal inspection, replay of an already admitted reservation, and settlement
133
+ of existing requests. These reconcile
134
+ prior work; they do not authorize another provider call. Unknown/cancelled usage
135
+ retains its reserved charge. Token expiry and grant revocation continue to apply
136
+ to every operation, so a revoked child needs its owner to reconcile its requests.
137
+
138
+ ## Client behaviour
139
+
140
+ `RemoteReservationLedger` gives `ExecutionGuard` the same read/reserve/settle surface as the local
141
+ ledger. It replays and verifies the hash chain itself and refuses any history that is not an
142
+ append-only extension of what it has seen, so a server reset or rollback cannot return spent
143
+ capacity. Writes retry with the same id; if every attempt is lost it inspects the journal, and
144
+ only an outcome the parent recorded counts. Otherwise the result is `unavailable` and nothing is
145
+ authorized (a reservation that was admitted stays charged).
146
+
147
+ The verified history is checkpointed atomically beneath the client's private
148
+ `root` as `verified-parent/history.json`. Reuse that root after reconnect or
149
+ restart. A missing, damaged, public or linked history file is an error; it is
150
+ never replaced with an empty allowance. Concurrent clients retain the longest
151
+ verified history, so an older response cannot overwrite a newer checkpoint.
152
+ The checkpoint contains no bearer token and never admits a provider request by
153
+ itself. Only the parent service can reserve or settle usage.
154
+
155
+ Headless and ACP children keep this state under `~/.calliope-cli/delegation-ledgers`,
156
+ keyed by the canonical project, configured token-file location and account. Rotating
157
+ the token or its projected-secret symlink at that location preserves verified history; restarting against a
158
+ rolled-back parent stops before the turn starts. Keep this directory on the
159
+ child's persistent private volume when running in a container. A new configured
160
+ token path is a separate connection, not recovery of the old one. These client
161
+ checkpoints do not by themselves wire Astrolift task admission or cancellation
162
+ to the ledger service.
163
+
164
+ The shared project budget also retains its reservation while admission is unknown.
165
+ An error releases project capacity only after a confirmed rejection before any
166
+ lost response. Even a fresh journal can lag an in-flight admission. Neither a
167
+ disconnect nor restarting the child restores the reserved project capacity.
168
+ Reservation errors optionally report `admission: refused` when the server has
169
+ verified non-admission after the local operation ends, or `unknown` otherwise.
170
+ Clients retain capacity when talking to older v1 servers that omit this evidence.
171
+
172
+ ## Owner-bound remote workspaces
173
+
174
+ A copied checkout has a different path and filesystem identity. It cannot use a
175
+ parent grant just because its files look the same. The ledger owner may issue a
176
+ version 2 child grant with `project: {root, key}`, captured using the CLI's
177
+ `projectIdentity()` on the intended child host. The existing proposal hash,
178
+ review revision and native run manifest references remain part of that immutable
179
+ grant. The trusted host must establish the identity and authorize the binding;
180
+ model output or an unauthenticated workspace claim is not sufficient.
181
+
182
+ Only a parent token may issue these workspace grants. Child-issued version 1
183
+ grants inherit the nearest owner-bound workspace, and cannot change it. Workspace
184
+ grants use reservation event version 5 and projection version 4; existing grant
185
+ events, manifests and hashes are unchanged. A restarted client replays the same
186
+ grant through its retained verified checkpoint.
187
+
188
+ Headless and ACP invocations negotiate `execution` before starting their turn. The server
189
+ checks the token's account scope, live owner authority and exact project identity.
190
+ The client independently checks the response against the native journal and its
191
+ actual local directory. Missing protocol support, another account, a substituted
192
+ binding or a replaced directory stops execution. Library callers opt in with
193
+ `RemoteReservationLedger.connect({..., execution: {cwd, agentId}})`.
194
+
195
+ File and brain-path checks use the bound child root and key, with the original
196
+ relative tool/path grants. Filesystem separators are normalized for grant checks;
197
+ parent traversal and symlink aliases remain denied. The immutable source budget
198
+ manifest, account ancestry, reservations and deadline remain on the parent ledger.
199
+ The checkpoint stays outside the child's project, and local project spending
200
+ limits still apply. Binding a folder does not copy files, mount a volume, import
201
+ brain content, install credentials or create another allowance.
202
+
203
+ The protocol now supports explicit workspace identity binding. Astrolift must
204
+ still establish that identity from its native runtime authority, enroll the task
205
+ under its owner, and connect lifecycle cancellation and funding. The raw ledger
206
+ service and a parent task UUID do not establish those bindings automatically.
207
+
208
+ `tests/delegation-ledger.test.ts` is the local-host conformance suite: concurrent and nested
209
+ children exhausting one allowance, duplicate dispatch and lost acknowledgements, an unreachable
210
+ parent, restart and rollback, revocation of a child and its descendants, foreign runs, siblings
211
+ and forged tokens, and `ExecutionGuard` admission through the parent.
212
+
213
+ ### Runner capability negotiation
214
+
215
+ `calliope --version --json` is an offline, credential-free probe.
216
+ `headless: {protocol: 1, delegation: 1, workspaceBinding: 1}` advertises
217
+ NDJSON terminal events, native parent-ledger admission and owner-bound workspace
218
+ validation. Embedders must verify these fields before supplying delegated tasks;
219
+ a matching package version alone does not establish those capabilities. This
220
+ probe does not grant authority: each invocation still negotiates with the live
221
+ parent and validates its token, journal and workspace before inference.
222
+
223
+
224
+ ### Native ACP session continuity
225
+
226
+ ACP connects to the parent's ledger before opening its protocol transport. The
227
+ process has one trusted execution context; `session/new` and `session/load` cannot
228
+ replace it through client parameters. `initialize` advertises
229
+ `agentCapabilities._meta.calliopeDelegation` with `version: 1`,
230
+ `workspaceBinding: 1` and `sessionBinding: 1`. A host must negotiate this metadata
231
+ before relying on delegated ACP behavior.
232
+
233
+ New delegated sessions retain a versioned restriction containing the original
234
+ manifest hash and account ID in private session metadata. Saving a conversation
235
+ or creating a manual/safety branch preserves it. This marker does not mint a
236
+ grant, reserve tokens or confer authority. Loading requires the same live ledger
237
+ and account, an exact workspace match and an unexpired original deadline. A
238
+ plain ACP process cannot load a bound session, and a delegated process cannot
239
+ attach its allowance to old unbound history. The shared turn engine also checks
240
+ the restriction before inference through other clients.
241
+
242
+ Follow-up prompts use the original account's reservations, costs and clock.
243
+ Native one-time approvals, tool results, cancellation and protocol replay remain
244
+ in use. Automatic project memory/context is filtered through the granted read
245
+ scope before inclusion in the system prompt; project trust alone does not widen
246
+ that scope. Operator-owned global preferences remain trusted configuration.
247
+
248
+ This is a CLI capability, not completed Astrolift enrollment. The runtime adapter
249
+ must still pass the trusted tuple, retain its task binding across restarts, verify
250
+ the capability and connect owner lifecycle/funding. Retained metadata is a
251
+ restriction within the private store, not protection against an administrator
252
+ rewriting that store or explicitly transferring conversation content elsewhere.
253
+
254
+ ### Private reverse transport for hosted tasks
255
+
256
+ The execution API exports `LEDGER_TUNNEL_CAPABILITY`, `attachLedgerTunnel` (owner)
257
+ and `listenLedgerTunnel` (task). The owner injects an authenticated, non-replayed
258
+ duplex exec connection; ordinary HTTP framing and backpressure carry only native
259
+ ledger requests. The owner opens no public listener. The task binds its original
260
+ loopback port, and never picks another port after a conflict. This does not yet
261
+ supply an Astrolift websocket endpoint or its task-placement authorization.
262
+
263
+ Both ends pin the original child credential's SHA-256, reviewed audience, run,
264
+ grant and expiration. Parent/replacement credentials are refused before task
265
+ traffic enters the exec stream. Claims are restrictions, not authentication:
266
+ the existing native server still verifies the signature, current grant, workspace
267
+ and account controls. The owner URL must be its trusted reviewed loopback host;
268
+ requests cannot choose another URL, follow redirects or invoke revocation.
269
+
270
+ Requests retain the native 256 KiB limit. Responses stream with a 32 MiB bound
271
+ for the bounded journal and envelope. There is one task request in flight;
272
+ heartbeats, request deadlines, stream closure and the original credential expiry
273
+ close both ends on loss of the owner. Bridge failures never assert non-admission.
274
+ The remote ledger retains unknown charges and retries the original request ID.
275
+
276
+ Reconnect attaches a new authorized stream to the original task port and native
277
+ stores, using the same credential and child checkpoint. It must not mint another
278
+ grant or replace a task binding. The trusted host must revalidate task identity,
279
+ placement and caller access through `assertConnection`, and abort the connection
280
+ when that lease ends. Do not use terminal replay, chat events or logs for these
281
+ streams: request headers contain the child bearer credential. The API performs
282
+ no task enrollment, credential persistence, scheduling or independent accounting.
283
+
284
+ ### Live execution authority
285
+
286
+ A retained journal proves accounting history, not current permission to execute.
287
+ Delegated clients revalidate the exact account and workspace through `execution`
288
+ before model requests and tool effects, and again before committing staged file
289
+ bytes. Revoked grants, stopped owners and an unreachable authority refuse further
290
+ work even when cached history is readable. Reconciliation reads do not restore
291
+ execution permission or release unresolved reservations.
292
+
293
+
294
+ ### Runnable host conformance example
295
+
296
+ Run `npm run test:reviewed-host` from the source checkout. The example at
297
+ `scripts/qualification/reviewed-host.mjs` creates a reviewed native run, serves
298
+ its parent ledger over HTTP and launches two concurrent built headless CLI
299
+ processes with separate account-scoped credentials against a deterministic local
300
+ inference endpoint. Each account ledger is also served by its own CLI process,
301
+ which is stopped and recreated during the restart check. Both children settle
302
+ into one parent allowance. Retained unknown requests then exhaust that allowance;
303
+ a host restart preserves them, and real CLI invocations refuse exhausted,
304
+ foreign-workspace, sibling-account and cancelled authority without another
305
+ inference request.
306
+ It uses private disposable configuration and makes no paid provider requests.
307
+
308
+ To qualify a standalone artifact built from the same source:
309
+
310
+ ```sh
311
+ npm run build
312
+ bun packaging/build-binary.mjs --native
313
+ CALLIOPE_REVIEWED_HOST_BINARY="$PWD/packaging/dist/calliope-native" \
314
+ node scripts/qualification/reviewed-host.mjs
315
+ ```
316
+
317
+ To qualify an extracted npm tarball with its production dependencies installed,
318
+ set `CALLIOPE_REVIEWED_HOST_PACKAGE` to that package directory instead. Both the
319
+ host library and all child processes then use the extracted package. The package
320
+ and standalone-binary options are mutually exclusive.
321
+
322
+ The executable reports its tested artifact type and invariant results as JSON.
323
+ This is a local HTTP host example, not a deployed Astrolift acceptance test.
324
+ Use `delegation-ledger/v1`, reviewed host capability version 1 and the headless
325
+ capability tuple above; a matching package version alone is insufficient.
326
+ The current CLI entry point requests a 4096-token output limit, so the reviewed
327
+ host and discovered model must both permit that bound. Lower output caps are
328
+ available to library callers through `DelegatedExecutionOptions.maxOutputTokens`.
329
+ The existing ledger, workspace and session suites cover nested grants, lost
330
+ acknowledgments, rollback and approval/session replay; those are separate from
331
+ this example's process-level assertions.