@xingular/harness 1.1.1 → 1.3.1-unstable.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 (264) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +36 -28
  3. package/dist/cli.js +10837 -6159
  4. package/dist/sdk/accounts/accounts.d.ts +27 -3
  5. package/dist/sdk/accounts/accounts.js +78 -24
  6. package/dist/sdk/accounts/secrets.d.ts +12 -0
  7. package/dist/sdk/accounts/secrets.js +114 -7
  8. package/dist/sdk/accounts/store.d.ts +26 -1
  9. package/dist/sdk/accounts/store.js +1 -1
  10. package/dist/sdk/agents/builtin.js +18 -4
  11. package/dist/sdk/agents/planResearch.d.ts +27 -0
  12. package/dist/sdk/agents/planResearch.js +82 -0
  13. package/dist/sdk/agents/profiles.d.ts +5 -1
  14. package/dist/sdk/agents/profiles.js +21 -5
  15. package/dist/sdk/annotations/pageScript.js +349 -48
  16. package/dist/sdk/annotations/part.js +34 -23
  17. package/dist/sdk/annotations/store.d.ts +7 -0
  18. package/dist/sdk/annotations/store.js +13 -5
  19. package/dist/sdk/browser/backend.d.ts +16 -0
  20. package/dist/sdk/browser/backend.js +17 -0
  21. package/dist/sdk/browser/contracts.d.ts +19 -0
  22. package/dist/sdk/browser/contracts.js +116 -0
  23. package/dist/sdk/browser/tools.d.ts +1 -4
  24. package/dist/sdk/browser/tools.js +14 -91
  25. package/dist/sdk/capabilities/runSnapshot.js +10 -4
  26. package/dist/sdk/cli.js +5 -4
  27. package/dist/sdk/commands/list.d.ts +3 -0
  28. package/dist/sdk/commands/list.js +75 -0
  29. package/dist/sdk/commands/registry.d.ts +258 -0
  30. package/dist/sdk/commands/registry.js +48 -0
  31. package/dist/sdk/commands/routes.d.ts +16 -0
  32. package/dist/sdk/commands/routes.js +33 -0
  33. package/dist/sdk/core/commandBudget.d.ts +23 -0
  34. package/dist/sdk/core/commandBudget.js +57 -0
  35. package/dist/sdk/core/index.js +17 -1
  36. package/dist/sdk/core/interactiveProfile.d.ts +46 -0
  37. package/dist/sdk/core/interactiveProfile.js +143 -0
  38. package/dist/sdk/core/shell.d.ts +20 -0
  39. package/dist/sdk/core/shell.js +73 -0
  40. package/dist/sdk/core/workspace.d.ts +13 -0
  41. package/dist/sdk/core/workspace.js +88 -0
  42. package/dist/sdk/core/workspaceBashTool.d.ts +20 -0
  43. package/dist/sdk/core/workspaceBashTool.js +50 -0
  44. package/dist/sdk/core/workspaceSandbox.d.ts +41 -0
  45. package/dist/sdk/core/workspaceSandbox.js +360 -0
  46. package/dist/sdk/core/workspaceWriteOperations.d.ts +33 -0
  47. package/dist/sdk/core/workspaceWriteOperations.js +224 -0
  48. package/dist/sdk/doctor/checks.js +71 -12
  49. package/dist/sdk/doctor/types.d.ts +2 -2
  50. package/dist/sdk/harness.d.ts +7 -0
  51. package/dist/sdk/harness.js +42 -2
  52. package/dist/sdk/hub/hub.js +5 -3
  53. package/dist/sdk/index.d.ts +8 -3
  54. package/dist/sdk/index.js +4 -1
  55. package/dist/sdk/pi/runtime.d.ts +2 -1
  56. package/dist/sdk/pi/runtime.js +2 -2
  57. package/dist/sdk/plugins/builtin.js +32 -15
  58. package/dist/sdk/plugins/builtinRegistry.d.ts +10 -3
  59. package/dist/sdk/plugins/builtinRegistry.js +30 -8
  60. package/dist/sdk/plugins/catalogue.js +2 -1
  61. package/dist/sdk/plugins/commandPrefix.d.ts +8 -0
  62. package/dist/sdk/plugins/commandPrefix.js +21 -0
  63. package/dist/sdk/plugins/firstParty.d.ts +1 -1
  64. package/dist/sdk/plugins/firstParty.js +8 -2
  65. package/dist/sdk/plugins/install.d.ts +6 -2
  66. package/dist/sdk/plugins/install.js +29 -5
  67. package/dist/sdk/plugins/inventory.js +6 -5
  68. package/dist/sdk/plugins/manifest.d.ts +2 -0
  69. package/dist/sdk/plugins/manifest.js +2 -1
  70. package/dist/sdk/plugins/surfaces.d.ts +5 -0
  71. package/dist/sdk/plugins/surfaces.js +11 -0
  72. package/dist/sdk/plugins/types.d.ts +15 -0
  73. package/dist/sdk/prompt/compile.d.ts +14 -0
  74. package/dist/sdk/prompt/compile.js +65 -31
  75. package/dist/sdk/prompt/standard.d.ts +17 -0
  76. package/dist/sdk/prompt/standard.js +21 -0
  77. package/dist/sdk/server/methods.js +22 -2
  78. package/dist/sdk/server/remote.js +36 -11
  79. package/dist/sdk/sessions/compactionCheckpoint.d.ts +11 -0
  80. package/dist/sdk/sessions/compactionCheckpoint.js +79 -0
  81. package/dist/sdk/sessions/continuation.d.ts +7 -2
  82. package/dist/sdk/sessions/continuation.js +11 -6
  83. package/dist/sdk/sessions/contracts.d.ts +190 -4
  84. package/dist/sdk/sessions/contracts.js +71 -8
  85. package/dist/sdk/sessions/control.d.ts +72 -0
  86. package/dist/sdk/sessions/control.js +158 -0
  87. package/dist/sdk/sessions/initialBash.d.ts +7 -0
  88. package/dist/sdk/sessions/initialBash.js +7 -0
  89. package/dist/sdk/sessions/planMode.d.ts +14 -3
  90. package/dist/sdk/sessions/planMode.js +74 -17
  91. package/dist/sdk/sessions/registry.d.ts +1 -1
  92. package/dist/sdk/sessions/registry.js +2 -2
  93. package/dist/sdk/sessions/runStore.d.ts +14 -0
  94. package/dist/sdk/sessions/runStore.js +38 -1
  95. package/dist/sdk/sessions/runner.d.ts +40 -2
  96. package/dist/sdk/sessions/runner.js +161 -13
  97. package/dist/sdk/sessions/sessions.d.ts +23 -3
  98. package/dist/sdk/sessions/sessions.js +225 -22
  99. package/dist/sdk/sessions/subagentService.d.ts +24 -0
  100. package/dist/sdk/sessions/subagentService.js +225 -26
  101. package/dist/sdk/sessions/subagents.d.ts +10 -1
  102. package/dist/sdk/sessions/subagents.js +4 -0
  103. package/dist/sdk/sessions/workSlice.d.ts +106 -0
  104. package/dist/sdk/sessions/workSlice.js +329 -0
  105. package/dist/sdk/sessions/workspaceBoundary.d.ts +15 -0
  106. package/dist/sdk/sessions/workspaceBoundary.js +46 -0
  107. package/dist/sdk/terminal/browserControl.js +2 -1
  108. package/dist/sdk/terminal/controller.d.ts +31 -3
  109. package/dist/sdk/terminal/controller.js +81 -29
  110. package/dist/sdk/terminal/opentui/ansi.d.ts +25 -0
  111. package/dist/sdk/terminal/opentui/ansi.js +192 -0
  112. package/dist/sdk/terminal/opentui/model.d.ts +163 -0
  113. package/dist/sdk/terminal/opentui/model.js +482 -0
  114. package/dist/sdk/terminal/opentui/subagentsWidget.d.ts +3 -3
  115. package/dist/sdk/terminal/opentui/subagentsWidget.js +7 -5
  116. package/dist/sdk/terminal/opentui/theme.d.ts +43 -0
  117. package/dist/sdk/terminal/opentui/theme.js +88 -0
  118. package/dist/sdk/terminal/piExtension.d.ts +6 -1
  119. package/dist/sdk/terminal/piExtension.js +177 -63
  120. package/dist/sdk/terminal/standalone.d.ts +7 -0
  121. package/dist/sdk/terminal/standalone.js +72 -13
  122. package/dist/sdk/terminal/subagentMonitor.d.ts +28 -6
  123. package/dist/sdk/terminal/subagentMonitor.js +61 -9
  124. package/dist/sdk/terminal/terminals.d.ts +26 -2
  125. package/dist/sdk/terminal/terminals.js +325 -43
  126. package/dist/sdk/terminal/trajectory.d.ts +6 -1
  127. package/dist/sdk/terminal/trajectory.js +8 -0
  128. package/dist/sdk/terminal/tui/annotateCommand.d.ts +1 -1
  129. package/dist/sdk/terminal/tui/annotateCommand.js +3 -3
  130. package/dist/sdk/terminal/tui/chrome.d.ts +4 -0
  131. package/dist/sdk/terminal/tui/chrome.js +13 -0
  132. package/dist/sdk/terminal/tui/commandPages.d.ts +3 -1
  133. package/dist/sdk/terminal/tui/commandPages.js +17 -4
  134. package/dist/sdk/terminal/tui/commands.d.ts +6 -0
  135. package/dist/sdk/terminal/tui/commands.js +213 -124
  136. package/dist/sdk/terminal/tui/list.d.ts +14 -1
  137. package/dist/sdk/terminal/tui/list.js +96 -14
  138. package/dist/sdk/terminal/tui/pageOverlay.js +21 -5
  139. package/dist/sdk/terminal/tui/pages/annotatePage.d.ts +1 -1
  140. package/dist/sdk/terminal/tui/pages/browserPage.js +5 -4
  141. package/dist/sdk/terminal/tui/pages/hubPage.d.ts +14 -1
  142. package/dist/sdk/terminal/tui/pages/hubPage.js +192 -28
  143. package/dist/sdk/terminal/tui/pages/notesPage.d.ts +5 -5
  144. package/dist/sdk/terminal/tui/pages/notesPage.js +18 -18
  145. package/dist/sdk/terminal/tui/pages/pluginsPage.d.ts +8 -6
  146. package/dist/sdk/terminal/tui/pages/pluginsPage.js +206 -28
  147. package/dist/sdk/terminal/tui/pages/subagentsPage.d.ts +1 -0
  148. package/dist/sdk/terminal/tui/pages/subagentsPage.js +104 -19
  149. package/dist/sdk/terminal/tui/pages/usagePage.d.ts +43 -0
  150. package/dist/sdk/terminal/tui/pages/usagePage.js +370 -0
  151. package/dist/sdk/terminal/tui/piAdapter.d.ts +1 -2
  152. package/dist/sdk/terminal/tui/piAdapter.js +3 -5
  153. package/dist/sdk/terminal/tui/pluginCommands.d.ts +2 -0
  154. package/dist/sdk/terminal/tui/pluginCommands.js +13 -9
  155. package/dist/sdk/terminal/tui/runtime.js +23 -3
  156. package/dist/sdk/terminal/tui/sessionPicker.d.ts +40 -0
  157. package/dist/sdk/terminal/tui/sessionPicker.js +141 -0
  158. package/dist/sdk/tools/checkpoint.d.ts +27 -0
  159. package/dist/sdk/tools/checkpoint.js +154 -0
  160. package/dist/sdk/tools/getCapabilities.d.ts +31 -0
  161. package/dist/sdk/tools/getCapabilities.js +34 -0
  162. package/dist/sdk/tools/sessionName.d.ts +2 -0
  163. package/dist/sdk/tools/sessionName.js +5 -3
  164. package/dist/sdk/tools/spawnSubagent.js +11 -8
  165. package/dist/sdk/tools/todo.d.ts +15 -0
  166. package/dist/sdk/tools/todo.js +64 -0
  167. package/dist/sdk/usage/analytics.d.ts +20 -0
  168. package/dist/sdk/usage/analytics.js +151 -0
  169. package/dist/sdk/usage/ledger.d.ts +38 -0
  170. package/dist/sdk/usage/ledger.js +142 -0
  171. package/dist/sdk/usage/limits/adapters.d.ts +11 -0
  172. package/dist/sdk/usage/limits/adapters.js +349 -0
  173. package/dist/sdk/usage/limits/capture.d.ts +8 -0
  174. package/dist/sdk/usage/limits/capture.js +47 -0
  175. package/dist/sdk/usage/limits/http.d.ts +12 -0
  176. package/dist/sdk/usage/limits/http.js +51 -0
  177. package/dist/sdk/usage/limits/normalize.d.ts +15 -0
  178. package/dist/sdk/usage/limits/normalize.js +211 -0
  179. package/dist/sdk/usage/limits/service.d.ts +30 -0
  180. package/dist/sdk/usage/limits/service.js +176 -0
  181. package/dist/sdk/usage/limits/types.d.ts +65 -0
  182. package/dist/sdk/usage/limits/types.js +1 -0
  183. package/dist/sdk/usage/serverMethods.d.ts +3 -0
  184. package/dist/sdk/usage/serverMethods.js +22 -0
  185. package/dist/sdk/usage/service.d.ts +32 -0
  186. package/dist/sdk/usage/service.js +66 -0
  187. package/dist/sdk/usage/settings.d.ts +7 -0
  188. package/dist/sdk/usage/settings.js +28 -0
  189. package/dist/sdk/usage/types.d.ts +60 -0
  190. package/dist/sdk/usage/types.js +4 -0
  191. package/dist/terminal-opentui.js +9204 -4812
  192. package/dist/terminal-pi.js +1848 -272
  193. package/docs/architecture/00-overview.md +1 -1
  194. package/docs/architecture/01-extension-points.md +1 -1
  195. package/docs/architecture/02-sessions-and-runs.md +169 -36
  196. package/docs/architecture/04-prompt.md +55 -15
  197. package/docs/architecture/06-plugins-and-capabilities.md +36 -15
  198. package/docs/architecture/07-tools-and-gate.md +131 -25
  199. package/docs/architecture/08-memory-and-history.md +4 -2
  200. package/docs/architecture/09-accounts-and-connectors.md +39 -3
  201. package/docs/architecture/10-server-protocol.md +71 -9
  202. package/docs/architecture/11-terminal.md +148 -60
  203. package/docs/architecture/12-storage.md +30 -2
  204. package/docs/architecture/13-world-tools.md +22 -1
  205. package/docs/architecture/14-surfaces-and-parity.md +58 -8
  206. package/docs/architecture/README.md +20 -17
  207. package/docs/architecture/proposals/PROP-0006-run-checklist.md +2 -0
  208. package/docs/architecture/proposals/PROP-0017-page-annotations.md +6 -2
  209. package/docs/architecture/proposals/PROP-0018-annotation-queue-and-app-targets.md +1 -1
  210. package/docs/architecture/proposals/PROP-0031-plugin-command-owner-namespaces.md +54 -0
  211. package/docs/architecture/proposals/PROP-0032-planning-quality.md +196 -0
  212. package/docs/architecture/proposals/PROP-0033-compaction-plan-checkpoints.md +75 -0
  213. package/docs/architecture/proposals/PROP-0034-conversation-fast-mode.md +120 -0
  214. package/docs/architecture/proposals/PROP-0035-retain-subagent-status.md +47 -0
  215. package/docs/architecture/proposals/PROP-0036-first-class-harness-commands.md +59 -0
  216. package/docs/architecture/proposals/PROP-0037-workspace-write-boundary.md +63 -0
  217. package/docs/architecture/proposals/PROP-0038-annotate-open-shadow-roots.md +73 -0
  218. package/docs/architecture/proposals/PROP-0039-workspace-boundary-hardening.md +139 -0
  219. package/docs/architecture/proposals/PROP-0040-one-launch-path.md +87 -0
  220. package/docs/architecture/proposals/PROP-0041-bounded-work-slices.md +258 -0
  221. package/docs/architecture/proposals/PROP-0042-usage-and-provider-limits.md +127 -0
  222. package/docs/architecture/proposals/PROP-0043-read-only-plan-bash.md +74 -0
  223. package/docs/architecture/proposals/PROP-0044-work-slice-defaults.md +93 -0
  224. package/docs/architecture/proposals/PROP-0045-rename-checklist-to-todo.md +132 -0
  225. package/docs/architecture/proposals/PROP-0046-progress-aware-stall-guards.md +82 -0
  226. package/docs/architecture/proposals/PROP-0047-plugins-hub-separation.md +122 -0
  227. package/docs/architecture/proposals/README.md +24 -6
  228. package/docs/decisions/ADR-0001-owned-terminal.md +1 -1
  229. package/docs/decisions/ADR-0021-required-command-namespaces.md +1 -1
  230. package/docs/decisions/ADR-0031-plugin-command-owner-namespaces.md +37 -0
  231. package/docs/decisions/ADR-0032-compaction-run-checkpoints.md +33 -0
  232. package/docs/decisions/ADR-0033-plan-mode-research-delegation.md +47 -0
  233. package/docs/decisions/ADR-0034-first-class-harness-terminal-commands.md +25 -0
  234. package/docs/decisions/ADR-0035-one-launch-path.md +40 -0
  235. package/docs/decisions/ADR-0036-workspace-write-operation-boundary.md +54 -0
  236. package/docs/decisions/ADR-0037-usage-ledger-and-provider-limits.md +44 -0
  237. package/docs/decisions/ADR-0038-plan-bash-os-read-only.md +29 -0
  238. package/docs/decisions/ADR-0039-progress-aware-stall-guards.md +39 -0
  239. package/docs/decisions/ADR-0040-architecture-change-workflow.md +31 -0
  240. package/docs/decisions/ADR-0041-plugins-hub-separation.md +41 -0
  241. package/docs/decisions/ADR-0042-windows-shell-without-sandbox.md +40 -0
  242. package/docs/decisions/ADR-0043-parents-continue-stopped-subagents.md +49 -0
  243. package/docs/doctor.md +14 -1
  244. package/docs/experiments/EXP-0003-performance-audit/data/session-runtime-replication.json +420 -0
  245. package/docs/experiments/EXP-0003-performance-audit/data/session-runtime.json +420 -0
  246. package/docs/experiments/EXP-0003-performance-audit/data/terminal-compact.json +376 -0
  247. package/docs/experiments/EXP-0003-performance-audit/data/terminal-history.json +422 -0
  248. package/docs/experiments/EXP-0003-performance-audit/data/terminal-question.json +95 -0
  249. package/docs/experiments/EXP-0003-performance-audit/data/terminal-wide.json +1036 -0
  250. package/docs/experiments/EXP-0003-performance-audit/plan.md +109 -0
  251. package/docs/experiments/EXP-0003-performance-audit/results.md +151 -0
  252. package/docs/handoff-2026-10-25-app-parity-and-solo-tabs.md +202 -0
  253. package/docs/parity.md +83 -27
  254. package/docs/releases/1.1.1.md +28 -0
  255. package/docs/releases/1.2.0.md +49 -0
  256. package/docs/releases/1.3.0.md +21 -0
  257. package/docs/releases/4.0.0.md +10 -9
  258. package/docs/releases/README.md +35 -30
  259. package/docs/study/00-index.md +3 -0
  260. package/docs/study/STUDY-0003-long-horizon-runs.md +210 -0
  261. package/docs/terminal-tui.md +162 -82
  262. package/package.json +4 -3
  263. package/dist/sdk/tools/checklist.d.ts +0 -9
  264. package/dist/sdk/tools/checklist.js +0 -54
@@ -4,7 +4,9 @@
4
4
 
5
5
  A run's tools come from four places: the harness's own tools, the connected-apps broker,
6
6
  subagent tools, and the application's tool providers. Every call, whatever its source, passes one
7
- per-call gate that asks the application's policy, then standing approvals, then the person.
7
+ per-call gate. Native writes also obey the run's pinned workspace boundary, with shell writes
8
+ contained by an OS sandbox; the gate then applies application policy, standing approvals and the
9
+ person without letting remembered per-tool grants widen that boundary.
8
10
 
9
11
  ## Components
10
12
 
@@ -14,39 +16,102 @@ per-call gate that asks the application's policy, then standing approvals, then
14
16
  | `dispatch` | `tools/dispatch.ts` | One entry point for every History, Wiki and skill call, from a Pi tool, the server or a terminal. |
15
17
  | `harnessTools` | `tools/harnessTools.ts` | The definitions as `ToolSpec`s for one session. |
16
18
  | `askUserTool` (`ask_user`) | `tools/askUser.ts` | Stops an attended plan run and asks up to five related questions with choices and concise 1–2 word labels; absent from newly resolved normal runs. |
17
- | `checklistTool` (`checklist_write`) | `tools/checklist.ts` | Writes the run's whole checklist as a `checklist.updated` event (PROP-0006). Read-only for the gate, so plan mode allows it. Terminal sessions register the same tool; it reaches the run through the `checklist` telemetry call. The prompt's Progress group asks the model to keep it current because the user follows work from it. |
18
- | `subagentTools` | `tools/spawnSubagent.ts` | `spawn_subagent` (requires a short `title`, PROP-0030), `wait_subagents`. |
19
+ | `todoTool` (`todo_write`) | `tools/todo.ts` | Writes the run's whole todo list as a `todo.updated` event (PROP-0006, renamed by PROP-0045). Read-only for the gate, so plan mode allows it. Terminal sessions register the same tool; it reaches the run through the `todo` telemetry call. The prompt's Progress group asks the model to call it before the first other tool call when work has several steps, keep it current, and write one final update before replying; unfinished work is not automatically marked complete. The pre-rename `checklist.updated` event is still read, never written. |
20
+ | `subagentTools` | `tools/spawnSubagent.ts` | `spawn_subagent` (requires a short `title`, PROP-0030) and `wait_subagents`; normal-mode descriptions guide selective, bounded delegation, while plan-mode spawns require a named eligible read-only research profile. |
19
21
  | `annotationsPart` (`page_notes_list`, `page_notes_read`, `page_notes_mark_fixed`) | `annotations/part.ts` | World tools over the page notes a person shared with the session or agent (PROP-0017). `page_notes_mark_fixed` records the agent's claim that it fixed a note it was sent; it never resolves a note or changes grants (PROP-0018). |
20
22
  | `webTools` | `web/tools.ts` | `web_search` (Brave, key from the secret store), `web_fetch` (checked public reads). An application provides them as a provider. |
21
23
  | gate | `sessions/sessions.ts::gate`, `sessions/runner.ts` | `ToolGate { ask, check }`, loaded as the last extension (`xagent-approvals`). |
22
24
  | `Approvals`, `decide`, `grant`, `approvalKey` | `sessions/approvals.ts` | Standing approvals. |
23
25
 
24
- Harness tools: `history_search`, `history_read`, `trajectory_search`, `trajectory_read`,
25
- `wiki_search`, `wiki_read`, `wiki_list`, `wiki_write` (not in the default set), `skill_load`,
26
- `ask_user` (attended plan runs and pinned continuations only), `checklist_write`. Broker:
26
+ Harness tools: `get_capabilities` (read-only current-run discovery), `history_search`, `history_read`,
27
+ `trajectory_search`, `trajectory_read`, `wiki_search`, `wiki_read`, `wiki_list`, `wiki_write`
28
+ (not in the default set), `skill_load`, `ask_user` (attended plan runs and pinned continuations only),
29
+ `todo_write`. Broker:
27
30
  `mcp_list_tools`, `mcp_call_tool`. Native Pi tools: `read`, `grep`, `find`,
28
31
  `ls`, `edit`, `write`, `bash`.
29
32
 
33
+ ## Cross-surface registration (PROP-0040)
34
+
35
+ The terminal registers Harness History/trajectory, Wiki-read and skill tools through
36
+ `Terminals.ownTools` and dispatches them over the session socket; they are model tools, not merely
37
+ shell commands. Enabled first-party hooks load through the protected `firstParty.list` bridge and
38
+ `terminal/piExtension.ts`. Attended planning uses the shared `ask_user`; the terminal-only question
39
+ alias is removed.
40
+
41
+ `get_capabilities` is implemented as a read-only Harness tool. Structured sessions register it from
42
+ the current run's frozen capability snapshot and live Pi tool/schema inventory. The terminal
43
+ extension (`terminal/piExtension.ts`) registers the same schema from Pi's active and registered tools;
44
+ when plan mode is active it reports the plan's allowed tool set. `sessions/planMode.ts` includes it in
45
+ the shared read-only allowlist. Host sessions use this Harness tool rather than defining a duplicate.
46
+ It reports availability, never permission, and every call remains subject to the gate.
47
+
30
48
  ## Native file paths
31
49
 
32
50
  The read-only `read`, `grep`, `find` and `ls` tools accept paths relative to the working folder,
33
- absolute paths, and `~` paths. The working folder is a default location, not a repository boundary;
34
- the operating system's access for the Harness process decides what can be read. The compiled file
35
- guidance names the configured data root. `edit`, `write` and `bash` continue through the existing
36
- gate and policy. A side-question run has an empty capability set and no tools (PROP-0019).
51
+ absolute paths, and `~` paths. The working folder is a default location, not a read boundary; the
52
+ operating system's access for the Harness process decides what can be read. The compiled file
53
+ guidance names the configured data root. Each run pins `workspaceRoot`: the nearest Git root or
54
+ worktree above its effective working directory, or the canonical working directory when there is no
55
+ repository. The filesystem root itself is rejected because it would collapse the write boundary.
56
+ `edit` and `write` resolve targets canonically, revalidate the pinned target at mutation,
57
+ and atomically replace the directory entry in a helper process constrained by the OS sandbox. This
58
+ prevents hard-link writes from changing another alias; normal file mode is retained where possible,
59
+ but ACLs and extended attributes are not guaranteed to survive replacement. An outside target
60
+ requires a human-only one-call approval (or an eligible Full Permission answer) and is not covered by
61
+ remembered tool grants.
62
+
63
+ Bash, including an initial `!` command, runs in an OS-enforced sandbox that permits broad reads but
64
+ writes only inside the root. Before default-scope Bash, Harness scans the workspace for regular-file
65
+ inodes with links outside it; an incomplete scan or possible external alias blocks the command, which
66
+ must be repaired or copied. The sandbox also prevents its own processes from creating cross-boundary
67
+ hard links; macOS denies hard-link creation entirely, including within the workspace. A local process
68
+ outside Harness running as the same user is outside this protection.
69
+ The Bash tool's optional `workspaceWriteScope` defaults to `workspace`; `outside` requests a
70
+ human-only one-call approval before the exact command runs once with broader filesystem access. The
71
+ approval shows the full escaped command in scrollable details and fails closed if the terminal
72
+ cannot show both the details and the choices. The terminal uses `!outside <command>` for the same
73
+ explicit request on a direct initial command.
74
+ stdout/stderr never proves a sandbox denial: denial text cannot request approval, and a command is
75
+ never replayed after partial effects. Full Permission is the explicit eligible-run bypass.
76
+ Unsupported or unavailable sandbox enforcement fails closed. A side-question run has an empty
77
+ capability set and no tools (PROP-0019).
78
+
79
+ **Windows** has no write-boundary sandbox the harness can use, so the Bash tool treats every
80
+ command there as an outside request: a human-only one-call approval (or an eligible Full
81
+ Permission answer), then the command runs once without a sandbox. Plan-mode Bash is refused,
82
+ because a read-only scope cannot be enforced. Commands run in Git Bash when it is installed
83
+ (`%ProgramFiles%\Git\bin\bash.exe`, then `bash.exe` on `PATH`, never the WSL launcher in
84
+ `System32`), otherwise in PowerShell (`pwsh.exe`, then Windows PowerShell). The tool keeps the name
85
+ `bash`; its description names the shell. Native `edit` and `write` run their atomic helper with
86
+ Node directly, without an OS guard: the target is still canonicalized, authorized, revalidated and
87
+ replaced by rename, and outside targets still need their approval, but a junction or symlink swap
88
+ between the check and the rename is not prevented
89
+ ([ADR-0042](../decisions/ADR-0042-windows-shell-without-sandbox.md)).
37
90
 
38
91
  ## The gate, per call
39
92
 
93
+ For native `edit` and `write`, the canonical target check is added to policy scope before approval;
94
+ the registered tool can mutate only through the policy-bound atomic helper. Bash workspace scope
95
+ scans for external hard links and then runs under the OS sandbox. An explicit outside scope is
96
+ approved before execution and runs once; stdout/stderr never triggers approval or retry. The
97
+ eligible Full Permission switch may answer the explicit request under its existing restrictions, but
98
+ a remembered tool grant cannot.
99
+
40
100
  ```text
41
101
  child run and tool outside its snapshot ─► refuse
42
- plan mode and tool not research-safe ─► refuse (before approvals)
102
+ plan mode and tool/call not research-safe ─► refuse (including ineligible spawn profiles, outside-scope or denied Bash; before approvals)
103
+ plan-mode Bash ─► read-only OS sandbox, never widened, run once
104
+ canonicalize native write target / verify pinned root
43
105
  policy.scope(call)
44
106
  not allowed and (automatic or no approval possible) ─► refuse with reason
45
107
  policy.authorize(call) throws ─► refuse
46
- allowed, not humanOnly, (automatic or not gated) ─► run
47
- trigger probe or improver ─► refuse (nobody to ask)
48
- run.requestApproval(...) ─► standing approvals may answer, else the person
49
- denied ─► refuse
108
+ outside native file target ─► human-only one-call approval; eligible Full Permission may answer
109
+ Bash workspace scope ─► hard-link scan, OS sandbox, run once
110
+ Bash outside scope ─► pre-execution human-only approval, then run once unconfined
111
+ Bash on Windows (no sandbox) ─► as outside scope; plan-mode Bash refused
112
+ trigger probe, improver, reflection or unattended ─► refuse anything requiring a person
113
+ run.requestApproval(...) ─► standing approvals may answer where eligible, else the person
114
+ denied ─► refuse; never replay a command
50
115
  policy.authorize(call) again ─► run or refuse
51
116
  ```
52
117
 
@@ -60,23 +125,52 @@ the switch and global tools.
60
125
 
61
126
  - **INV-GATE-1** Every tool call of every run passes the gate. No tool source bypasses it,
62
127
  including extension-registered tools (which ask before every call) and the initial Bash command.
128
+ - **INV-TOOL-9** `checkpoint_write` records one bounded handoff for the active run and is read-only
129
+ and plan-safe: no field changes files, and the record is the `checkpoint` run event (PROP-0041).
130
+ - **INV-TOOL-10** Bash keeps one command budget on every surface: 120 seconds when the call says
131
+ nothing, 300 seconds as the ceiling without a `reason`, 900 seconds as the maximum, and a timeout
132
+ returns the partial output with a narrowing instruction instead of blocking the reply.
63
133
  - **INV-GATE-2** The gate is the last extension loaded, after disk, variant and inline extensions, so
64
134
  it sees the final input of every call.
65
- - **INV-GATE-3** Order is fixed: capability and plan-mode refusals, then the policy's scope and
66
- authorize, then standing approvals, then the person, then authorize again.
135
+ - **INV-GATE-3** Order is fixed: capability and plan-mode refusals, canonicalize native file-write
136
+ targets, consult the policy's scope and authorize, combine mandatory outside-write approval with
137
+ that scope, then eligible standing approvals or the person, then authorize again. Native mutations
138
+ revalidate the authorized target and use atomic replacement inside an OS-enforced write scope.
139
+ Default Bash scans for external hard links, then runs only inside the OS sandbox. `workspaceWriteScope:
140
+ 'outside'` requests human-only approval before running that exact command once with broader access.
141
+ Command output never proves a sandbox denial and never triggers approval or replay; earlier
142
+ side-effects are not repeated. The policy may tighten or deny a call, but cannot waive the boundary.
143
+ Outside file writes and broad Bash calls cannot use remembered per-tool approval; only the eligible
144
+ Full Permission switch can answer automatically under its existing restrictions. In plan mode, Bash
145
+ runs only in the read-only scope (PROP-0043): no writes but a discarded temp folder, no network,
146
+ no signals outside the sandbox, no macOS mach services; Full Permission and `outside` never apply.
147
+ On Windows, which has no sandbox, every Bash call takes the `outside` path and plan-mode Bash is
148
+ refused (ADR-0042).
67
149
  - **INV-GATE-4** Refinement runs (`probe`, `improver`) never ask a person; what would need one is
68
150
  refused, never queued (`INV-REF-4`).
69
151
  - **INV-GATE-5** SDK tools are registered only if their names are in the run's frozen capability
70
- set (`INV-CAP-1`). The terminal may retain question-tool definitions in its private Pi inventory,
71
- but normal mode deactivates them; a plan request activates only registered questions under its
72
- plan-mode gate.
152
+ set (`INV-CAP-1`). `get_capabilities` is a read-only Harness tool on structured and terminal
153
+ surfaces; it reports the frozen callable set and does not grant access. The terminal may retain
154
+ question-tool definitions in its private Pi inventory, but normal mode deactivates them; a plan
155
+ request activates only registered questions under its plan-mode gate.
73
156
  - **INV-GATE-6** Tool attachment bytes never enter the run-event stream; only references are
74
157
  recorded.
75
158
  - **INV-GATE-7** Tool descriptions name the product with `{product}` (filled by `describeTool`),
76
159
  never an application's name (`INV-BND-2`).
77
- - **INV-GATE-8** Native read-only file access is bounded by process and operating-system
78
- permissions, not by the repository root. Absolute and `~` paths are valid inputs. This does not
79
- change the gate or permissions for writes and commands.
160
+ - **INV-GATE-8** Native reads are bounded by process and operating-system permissions, not by the
161
+ workspace root; absolute and `~` paths are valid. Every run pins its canonical `workspaceRoot`.
162
+ Native `edit` and `write` mutations revalidate the authorized canonical target and atomically
163
+ replace it under an OS-enforced scope; outside targets require human-only one-call approval and
164
+ cannot use remembered tool grants. Default Bash scans the workspace for possible outside hard-link
165
+ aliases and is OS-sandboxed to write only inside the root while retaining broad reads; the sandbox
166
+ prevents its own processes from creating cross-boundary hard links, and macOS denies all hard-link
167
+ creation in the sandbox. An incomplete scan or missing
168
+ enforcement fails closed. An explicit `workspaceWriteScope: 'outside'` request is approved before
169
+ execution and runs once; command output never triggers approval or retry. The terminal exposes the
170
+ same choice as `!outside <command>`. Full Permission is the only standing boundary bypass and
171
+ remains subject to host policy, authorization, read-only, plan, unattended, probe, improver and
172
+ reflection restrictions. The rule does not protect against a peer process running as the same user.
173
+ On Windows the atomic replacement runs without an OS-enforced scope (ADR-0042).
80
174
 
81
175
  ## Data
82
176
 
@@ -85,13 +179,18 @@ the switch and global tools.
85
179
  ## Source map
86
180
 
87
181
  `src/tools/*.ts`, `src/web/*.ts`, `src/sessions/sessions.ts`, `src/sessions/runner.ts`,
88
- `src/sessions/approvals.ts`, `src/sessions/policy.ts`.
182
+ `src/sessions/workspaceBoundary.ts`, `src/sessions/initialBash.ts`, `src/core/workspaceBashTool.ts`,
183
+ `src/core/shell.ts`, `src/core/workspaceSandbox.ts`, `src/core/workspaceWriteOperations.ts`,
184
+ `src/sessions/approvals.ts`, `src/sessions/policy.ts`. Decisions:
185
+ [ADR-0036](../decisions/ADR-0036-workspace-write-operation-boundary.md),
186
+ [ADR-0042](../decisions/ADR-0042-windows-shell-without-sandbox.md).
89
187
 
90
188
  ## Session naming (PROP-0010)
91
189
 
92
190
  `session_name` (`tools/sessionName.ts`) binds to the current native session. It maintains
93
191
  only Pi session metadata and is explicitly plan-safe, while still subject to capability
94
- selection and the host policy. The terminal registers the same definition through its Pi
192
+ selection and the host policy. The prompt asks for it once before the first other tool call when
193
+ a request needs tools or changes state. The terminal registers the same definition through its Pi
95
194
  bridge; standalone policy permits naming without approval. See page 02 for validation and
96
195
  persistence. It is a foundation tool, not mutable variant data.
97
196
 
@@ -101,3 +200,10 @@ persistence. It is a foundation tool, not mutable variant data.
101
200
  intersect current capabilities, and execute tool calls through the existing gate. Calls that
102
201
  require an additional per-call approval report blocked; batch diagnostic consent does not grant
103
202
  standing permission. No raw tool inputs, results, or screenshots enter diagnostic findings.
203
+
204
+ A live check may also run one command the harness wrote itself, when the capability it diagnoses is
205
+ a native Pi tool rather than a harness tool: the shell check runs `printf` through the same
206
+ workspace root, hard-link scan and write-boundary sandbox as a Bash call, and reports only the exit
207
+ status. It passes the gate first, and a diagnostic never widens the boundary — Full Permission,
208
+ an outside-workspace request and a host bypass are all refused for it — so a boundary that stops
209
+ the command before the shell starts is reported as blocked with the boundary's own reason.
@@ -55,7 +55,9 @@ rebuildable SQLite index.
55
55
  lessons; nothing is evicted.
56
56
  - The `wiki` pointer section says how many lessons there are when there are any.
57
57
  - **Index.** Every finished run is indexed when it ends; `open` and `rebuildIndex()` sync from
58
- `runs/`.
58
+ `runs/`. The same pass writes the **usage ledger**: one `usage_requests` row per model request
59
+ from the run's `usage.updated` events, and one `usage_indexed` marker per run (PROP-0042).
60
+ `/usage:analysis` queries only that ledger; it is derived and rebuilt from run events.
59
61
 
60
62
  ## Invariants
61
63
 
@@ -84,7 +86,7 @@ rebuildable SQLite index.
84
86
  <data root>/wiki/ home.md, library/, projects/<slug>/
85
87
  <data root>/wiki-history/ earlier versions of notes
86
88
  <data root>/legacy/ an earlier Wiki's memory blocks, facts, revisions, Inbox (moved once)
87
- <data root>/index.sqlite derived: pages, links, runs, recall passages (FTS5)
89
+ <data root>/index.sqlite derived: pages, links, runs, recall passages (FTS5), usage rows
88
90
  <data root>/projects.json read only: the application owns it
89
91
  ```
90
92
 
@@ -38,7 +38,10 @@ skills, prompts, rules and Pi packages.
38
38
  - **`apps.expose(tools)`** offers the application's own tools through the broker, which is how a
39
39
  terminal session reaches them.
40
40
  - **Hub.** `hub.list`, `get`, `preview`, `install`, `uninstall`, `readDocument`. Pi packages need
41
- an exact npm version or a full Git commit. Documents are saved as inert JSON.
41
+ an exact npm version or a full Git commit. Documents are saved as inert JSON. The `/hub` Catalog
42
+ view filters Community entries for display; the service and other callers retain the full catalog.
43
+ Installed shows receipts from every channel. On page entry, cached/bundled content is shown before
44
+ a remote refresh, and origin, refresh time and failure status remain visible (PROP-0047).
42
45
 
43
46
  ## Invariants
44
47
 
@@ -62,12 +65,15 @@ skills, prompts, rules and Pi packages.
62
65
  nothing of it is stored.
63
66
  - **INV-MCP-4** Hub installation grants no attachment, trust, credential or permission. Writes
64
67
  are serialized; existing registry files are never overwritten; uninstall removes only the exact
65
- receipt's resources and revokes its attachment choices.
68
+ receipt's resources and revokes its attachment choices. Every removal route for a Hub-owned Pi
69
+ package, including `plugins.remove`, goes through Hub's receipt-owning uninstall operation. A
70
+ floating plugin-package update must not change a Hub-owned package; replacement uses an explicit
71
+ exact catalog version (PROP-0047).
66
72
 
67
73
  ## Data
68
74
 
69
75
  ```text
70
- <state dir>/accounts/ registry, per-account Pi agent folders, _shared/pi/, audit log
76
+ <state dir>/accounts/ registry, per-account Pi agent folders, _shared/pi/, audit log, per-account state (health, plan, limits)
71
77
  <state dir>/secrets.json default SecretStore (owner-only)
72
78
  <state dir>/connections.json connected apps, no secrets
73
79
  <state dir>/hub/catalog.json catalog cache
@@ -89,6 +95,36 @@ at 64 tokens, and records usage through the normal run writer. It never substitu
89
95
  MCP live diagnostics connect and list tools on the selected scoped connector, without calling
90
96
  connector tools or starting sign-in. Disposable grants and clients are closed afterwards.
91
97
 
98
+ ## Provider limits (PROP-0042)
99
+
100
+ A limit reading says what a provider itself reported: a plan window, a credit balance, a rate
101
+ limit, or a configured organization limit. Three sources are used, in order:
102
+
103
+ 1. **Response headers** on the account's own model requests. Each account runtime's providers are
104
+ wrapped so `onResponse` sees status and headers; a terminal session's own runtime forwards only
105
+ the limit-bearing headers to the parent over the control-key-protected session socket.
106
+ `usage/limits/normalize.ts` understands `anthropic-ratelimit-*`, Anthropic unified plan windows,
107
+ `x-codex-*` and `x-ratelimit-*`, plus `Retry-After` on a 429. Raw headers are never stored.
108
+ 2. **The provider's own usage endpoint**, read with `Models.getAuth(provider)` so OAuth refresh
109
+ stays in Pi's serialized credential path: OpenRouter `GET /api/v1/key`, DeepSeek
110
+ `GET /user/balance`, Anthropic's organization `rate_limits` for an admin API key (configured
111
+ limits, not usage), ChatGPT/Codex `GET https://chatgpt.com/backend-api/wham/usage`, and
112
+ OpenCode Go `GET https://opencode.ai/zen/go/v1/usage`. A Codex request carries the account id
113
+ from the access token's JWT claim; an OpenCode Go request carries the account's API key.
114
+ The request is a bounded HTTPS GET that refuses redirects, caps its body, and never puts a
115
+ credential in an error. An endpoint reading replaces every limit for that provider; a header
116
+ reading only merges the windows it saw.
117
+ 3. **Unavailable**, with a reason. No percentage is invented; local usage is shown instead.
118
+
119
+ Undocumented endpoints require the usage plugin's `experimentalProbes` setting. Readings are
120
+ cached for `refreshMinutes` (default 10) and refreshed on a page open or an explicit refresh, never
121
+ by a background timer. They are stored in the account's existing state (`limits`,
122
+ `providerLimits`), never in a new file, and no credential is written. A reading carries both `usedPercent` and the additive
123
+ `remainingPercent`. The Limits page is a centered dialog: each window is a label and reset line
124
+ above a quota-left bar, green at 50% or more left, amber from 20–49%, and red below 20%. It adds
125
+ the local seven-day ledger without a label, so a provider's zero reading and this app's own use
126
+ are not confused.
127
+
92
128
  ## Terminal connection setup
93
129
 
94
130
  The unified browser exposes existing connection save/test/sign-in/sign-out/remove services through
@@ -33,24 +33,82 @@ harness → host { v: 1, id, call, params } host → harness { v: 1
33
33
  - `harness.methods` lists every method. Groups in the table: `accounts`, `harnesses`, `runs`,
34
34
  `connections`, `plugins`, `wiki`, `refine`, `capabilities`, `hub`, `terminal`, `approvals`,
35
35
  `harness`, `subagents`, `agents`, `sessions`, `sideQuestions`, `library`, `recall`, `context`,
36
- `worktrees`, `annotations`.
36
+ `worktrees`, `annotations`, `commands`, `usage`.
37
37
  - Host calls (only with the matching `--host-*` flag): `secrets.get|set|delete`,
38
38
  `policy.scope|authorize|approval|connections`, `tools.call`. The host registers tools with
39
39
  `tools.register` and names with `directory.set`, and describes its parts with
40
40
  `plugins.describe`.
41
41
  - `refine.start` takes `{ task, k?, mode?, improver?, executor?, baseVersion?, retainWorkspaces?, id? }`;
42
42
  `refine.candidates` returns each execution with `workspace: string | null` (page 05, PROP-0002, PROP-0003).
43
- - `runs.checklist { runId }` returns the run's latest checklist, `[]` when it wrote none (PROP-0006).
43
+ - `runs.todo { runId }` returns the run's latest todo list, `[]` when it wrote none (PROP-0006,
44
+ renamed by PROP-0045). `runs.checklist` is the deprecated pre-rename alias.
45
+ - `runs.continuation` returns `todo`; `checklist` remains a deprecated mirror of it for one release.
46
+ - Run records include optional nullable `workspaceRoot`, the canonical root whose files a run may
47
+ modify by default (page 02). New Harness runs set it; older records may omit it. Hosts must
48
+ tolerate the additive field and must not nominate or widen the root.
44
49
  - `agents.list { cwd? }` returns `{ profiles, problems }`; `agents.get { cwd?, name }` one profile;
45
50
  `agents.create { cwd?, name, scope: 'global' | 'project', from? }` writes the template or a copy
46
51
  and refuses an existing file; `agents.remove { cwd?, name, scope }` deletes a person's own file.
47
52
  `subagents.spawn` takes `agent` as a profile name and returns `agent` and `unavailableTools`
48
53
  (PROP-0029). It takes an optional `title` (at most six words); without one the child's title is
49
- the first line of its brief (PROP-0030).
50
- - `runs.continuation { runId, sessionDir? }` returns a `Continuation`, and `sessions.run` accepts
51
- `continueFrom` (page 02, PROP-0007). `harness.status` reports `recovery.interruptedRunIds`.
54
+ the first line of its brief (PROP-0030). With `continue: <runId>` it continues a stopped child of
55
+ this conversation instead (no `agent` or `tools`; `brief` and `title` optional) and returns
56
+ `continued`, the run it continued (ADR-0043).
57
+ - `runs.continuation { runId, sessionDir? }` returns a `Continuation` (its `checkpoint` is the last
58
+ work-slice handoff), and `sessions.run` accepts `continueFrom` (page 02, PROP-0007) and `workSlice`
59
+ (PROP-0041). `harness.status` reports `recovery.interruptedRunIds`.
60
+ - `workSlice { enabled?, maxToolCalls?, maxMinutes?, maxNewTokens?, maxSlices?, continue? }` on
61
+ `sessions.run` bounds that reply; absent uses 320 calls, 60 minutes, no new-token cap, 8 slices and
62
+ automatic continuation. A token cap, when set, counts new input, cache writes and output, never the
63
+ cached prefix (PROP-0044). `enabled: false` turns the guard off for that run;
64
+ `XINGULAR_WORK_SLICE=off` in the launching process turns it off for every run in it, and nothing is
65
+ persisted. The policy is
66
+ carried into the continuation. A value outside its range is refused with `invalid_request` before
67
+ the run record is written.
68
+ - The run-event stream adds `checkpoint` (the bounded handoff) and `heartbeat` (steps, elapsed time,
69
+ last tool, compactions, slice, call budget). Hosts must accept both; an unknown event type is still
70
+ relayed in order (INV-RUN-3).
52
71
  - Errors carry a stable `code`, a message and an optional hint (`core/errors.ts`).
53
72
 
73
+ ## Usage (PROP-0042)
74
+
75
+ | Method | Input | Reply |
76
+ |---|---|---|
77
+ | `usage.summary` | `{ scope?: "session" \| "account" \| "project" \| "all", sessionId?, accountId?, projectId?, period?: "today" \| "7d" \| "30d" \| "all", timezoneOffsetMinutes? }` | `UsageSummary`: totals, cache hit rate, latency, day/model/provider/account/session breakdowns, unpriced count, ledger time |
78
+ | `usage.limits` | `{ accountId?, refresh?: boolean }` | `UsageLimitsReport`: per account and provider, the reading source, reason, observed time and limits |
79
+ | `usage.sync` | `{}` | `{ runs, indexed, lastIndexedAt }` |
80
+
81
+ The methods are contributed by the built-in `usage` plugin module and read only derived or stored
82
+ data; `refresh: true` is the only form that may contact a provider, once per due provider. The
83
+ terminal reaches the same service through protected `terminal.usage.summary|limits`, whose scope
84
+ comes from the terminal session, never from the request.
85
+
86
+ ## Commands and session controls (PROP-0040)
87
+
88
+ `commands.list { cwd?, accountId?, agentId?, projectId? }` returns `ListedCommand[]`: `name`,
89
+ optional `aliases`, `args`, `description`, `owner`, plus `group`, `source`
90
+ (`core | plugin | extension | prompt | skill`) and optional core `kind` (`session | page | local`).
91
+ Core metadata comes from `commands/registry.ts`; effective plugin contributions supply other routes.
92
+ Namespace/collision rules are shared; discovery neither runs a command nor proves surface acceptance.
93
+
94
+ For the methods below, `ref` means `{ sessionDir, sessionFile?, cwd? }`.
95
+
96
+ | Method | Input | Reply |
97
+ |---|---|---|
98
+ | `sessions.tree` | `ref` | `SessionTree`: file, leaf, entries and user-message fork points |
99
+ | `sessions.navigate` | `ref + { entryId }` | `{ leafId, editorText? }`; no summary/model request |
100
+ | `sessions.fork` | `ref + { entryId, targetDir }` | `{ sessionFile, editorText }` |
101
+ | `sessions.clone` | `ref + { targetDir }` | `{ sessionFile }` |
102
+ | `sessions.rename` | `ref + { name }` | `{ name }` |
103
+ | `sessions.lastReply` | `ref` | `{ text: string | null }` |
104
+ | `sessions.export` | `ref + { path }` | `{ path }`; absolute `.jsonl` branch export |
105
+ | `sessions.reload` | `{}` | `{ reloaded: true }`; reloads persistent hooks; structured turns load resources fresh |
106
+
107
+ `sessions.run` also accepts `command` for compact, navigation with optional summary, or HTML
108
+ export instead of prompt submission (page 02). These retain tracked run lifecycle and pins.
109
+ Saved-history helpers currently validate file scope but do not themselves fence active work;
110
+ host adapters must not infer concurrency safety from method availability.
111
+
54
112
  ## Invariants
55
113
 
56
114
  - **INV-SRV-1** `src/server/methods.ts` is the contract for every non-Node host. Adding a method
@@ -129,10 +187,14 @@ from preparation, never from the request.
129
187
  | `terminal.browser.connections.appClients` | `{}` | Existing available application OAuth catalog IDs |
130
188
  | `terminal.browser.connections.save` | `{ input: ConnectionInput }` | Existing safe `Connection` record |
131
189
  | `terminal.browser.connections.test\|signIn\|signOut\|remove` | `{ id }` | Existing connection service result |
132
-
133
- Protected `plugins.install { source }` and `plugins.remove { pluginId }` delegate to the package
134
- service. Optional matching callbacks extend `PluginControl`; hosts without them receive a clear
135
- unsupported-operation error. No protocol version or persisted schema changes.
190
+ | `terminal.usage.summary\|limits` | `{ scope, period, timezoneOffsetMinutes }` / `{ refresh? }` | Existing usage service result, scoped to this terminal's account and project |
191
+ | `terminal.usage.headers` | `{ provider, status, headers }` | `{}`; only limit-bearing headers, throttled, stored as an account limit reading |
192
+
193
+ Protected `plugins.install { source }`, `plugins.update { pluginId? }` and
194
+ `plugins.remove { pluginId }` delegate to the package service. Removing a Hub-owned package routes
195
+ through Hub's receipt-aware uninstall; a floating update refuses Hub-owned packages, while an
196
+ update-all skips them. Optional matching callbacks extend `PluginControl`; hosts without them
197
+ receive a clear unsupported-operation error. No protocol version or persisted schema changes.
136
198
 
137
199
  ## Worktrees (PROP-0016)
138
200