@xingular/harness 1.0.0 → 1.2.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 (397) hide show
  1. package/CHANGELOG.md +46 -5
  2. package/README.md +75 -21
  3. package/dist/cli.js +17421 -8711
  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.d.ts +2 -0
  11. package/dist/sdk/agents/builtin.js +48 -0
  12. package/dist/sdk/agents/narrow.d.ts +13 -0
  13. package/dist/sdk/agents/narrow.js +29 -0
  14. package/dist/sdk/agents/planResearch.d.ts +5 -0
  15. package/dist/sdk/agents/planResearch.js +19 -0
  16. package/dist/sdk/agents/profiles.d.ts +81 -0
  17. package/dist/sdk/agents/profiles.js +226 -0
  18. package/dist/sdk/annotations/bridge.d.ts +42 -0
  19. package/dist/sdk/annotations/bridge.js +264 -0
  20. package/dist/sdk/annotations/capture.d.ts +116 -0
  21. package/dist/sdk/annotations/capture.js +308 -0
  22. package/dist/sdk/annotations/delivery.d.ts +72 -0
  23. package/dist/sdk/annotations/delivery.js +130 -0
  24. package/dist/sdk/annotations/inspect.d.ts +10 -0
  25. package/dist/sdk/annotations/inspect.js +33 -0
  26. package/dist/sdk/annotations/isolated.d.ts +6 -0
  27. package/dist/sdk/annotations/isolated.js +51 -0
  28. package/dist/sdk/annotations/pageScript.d.ts +28 -0
  29. package/dist/sdk/annotations/pageScript.js +871 -0
  30. package/dist/sdk/annotations/part.d.ts +10 -0
  31. package/dist/sdk/annotations/part.js +155 -0
  32. package/dist/sdk/annotations/queue.d.ts +4 -0
  33. package/dist/sdk/annotations/queue.js +40 -0
  34. package/dist/sdk/annotations/serverMethods.d.ts +3 -0
  35. package/dist/sdk/annotations/serverMethods.js +62 -0
  36. package/dist/sdk/annotations/store.d.ts +167 -0
  37. package/dist/sdk/annotations/store.js +394 -0
  38. package/dist/sdk/browser/backend.d.ts +16 -0
  39. package/dist/sdk/browser/backend.js +17 -0
  40. package/dist/sdk/browser/contracts.d.ts +19 -0
  41. package/dist/sdk/browser/contracts.js +116 -0
  42. package/dist/sdk/browser/index.d.ts +14 -3
  43. package/dist/sdk/browser/index.js +11 -4
  44. package/dist/sdk/browser/serverMethods.d.ts +3 -0
  45. package/dist/sdk/browser/serverMethods.js +7 -0
  46. package/dist/sdk/browser/session.d.ts +1 -0
  47. package/dist/sdk/browser/session.js +45 -9
  48. package/dist/sdk/browser/tools.d.ts +1 -4
  49. package/dist/sdk/browser/tools.js +14 -91
  50. package/dist/sdk/cli.js +24 -15
  51. package/dist/sdk/commands/list.d.ts +3 -0
  52. package/dist/sdk/commands/list.js +75 -0
  53. package/dist/sdk/commands/registry.d.ts +250 -0
  54. package/dist/sdk/commands/registry.js +47 -0
  55. package/dist/sdk/commands/routes.d.ts +16 -0
  56. package/dist/sdk/commands/routes.js +33 -0
  57. package/dist/sdk/core/bus.js +1 -1
  58. package/dist/sdk/core/commandBudget.d.ts +23 -0
  59. package/dist/sdk/core/commandBudget.js +57 -0
  60. package/dist/sdk/core/env.d.ts +1 -1
  61. package/dist/sdk/core/env.js +1 -1
  62. package/dist/sdk/core/index.js +17 -1
  63. package/dist/sdk/core/interactiveProfile.d.ts +46 -0
  64. package/dist/sdk/core/interactiveProfile.js +143 -0
  65. package/dist/sdk/core/workspace.d.ts +13 -0
  66. package/dist/sdk/core/workspace.js +88 -0
  67. package/dist/sdk/core/workspaceBashTool.d.ts +4 -0
  68. package/dist/sdk/core/workspaceBashTool.js +36 -0
  69. package/dist/sdk/core/workspaceSandbox.d.ts +31 -0
  70. package/dist/sdk/core/workspaceSandbox.js +320 -0
  71. package/dist/sdk/core/workspaceWriteOperations.d.ts +22 -0
  72. package/dist/sdk/core/workspaceWriteOperations.js +206 -0
  73. package/dist/sdk/doctor/serverMethods.d.ts +3 -0
  74. package/dist/sdk/doctor/serverMethods.js +8 -0
  75. package/dist/sdk/doctor/types.d.ts +2 -2
  76. package/dist/sdk/harness.d.ts +22 -0
  77. package/dist/sdk/harness.js +84 -5
  78. package/dist/sdk/history/recall.js +8 -8
  79. package/dist/sdk/history/serverMethods.d.ts +3 -0
  80. package/dist/sdk/history/serverMethods.js +8 -0
  81. package/dist/sdk/hub/cli.d.ts +1 -1
  82. package/dist/sdk/hub/cli.js +1 -1
  83. package/dist/sdk/hub/schema.d.ts +1 -1
  84. package/dist/sdk/hub/serverMethods.d.ts +3 -0
  85. package/dist/sdk/hub/serverMethods.js +11 -0
  86. package/dist/sdk/index.d.ts +16 -1
  87. package/dist/sdk/index.js +10 -0
  88. package/dist/sdk/mcp/connections.js +14 -7
  89. package/dist/sdk/mcp/serverMethods.d.ts +3 -0
  90. package/dist/sdk/mcp/serverMethods.js +22 -0
  91. package/dist/sdk/pi/runtime.d.ts +2 -1
  92. package/dist/sdk/pi/runtime.js +2 -2
  93. package/dist/sdk/plugins/builtin.d.ts +1 -0
  94. package/dist/sdk/plugins/builtin.js +145 -33
  95. package/dist/sdk/plugins/builtinRegistry.d.ts +60 -0
  96. package/dist/sdk/plugins/builtinRegistry.js +71 -0
  97. package/dist/sdk/plugins/catalogue.js +2 -1
  98. package/dist/sdk/plugins/cli.d.ts +1 -1
  99. package/dist/sdk/plugins/cli.js +4 -3
  100. package/dist/sdk/plugins/commandPrefix.d.ts +8 -0
  101. package/dist/sdk/plugins/commandPrefix.js +21 -0
  102. package/dist/sdk/plugins/firstParty.d.ts +1 -1
  103. package/dist/sdk/plugins/firstParty.js +8 -2
  104. package/dist/sdk/plugins/inventory.js +4 -3
  105. package/dist/sdk/plugins/manifest.d.ts +2 -0
  106. package/dist/sdk/plugins/manifest.js +2 -1
  107. package/dist/sdk/plugins/surfaces.d.ts +5 -0
  108. package/dist/sdk/plugins/surfaces.js +11 -0
  109. package/dist/sdk/plugins/types.d.ts +15 -0
  110. package/dist/sdk/prompt/compile.d.ts +19 -2
  111. package/dist/sdk/prompt/compile.js +79 -26
  112. package/dist/sdk/prompt/standard.d.ts +17 -0
  113. package/dist/sdk/prompt/standard.js +21 -0
  114. package/dist/sdk/refine/cli.d.ts +1 -1
  115. package/dist/sdk/refine/cli.js +2 -2
  116. package/dist/sdk/refine/serverMethods.d.ts +3 -0
  117. package/dist/sdk/refine/serverMethods.js +20 -0
  118. package/dist/sdk/server/methods.js +27 -86
  119. package/dist/sdk/server/params.d.ts +4 -0
  120. package/dist/sdk/server/params.js +11 -0
  121. package/dist/sdk/server/remote.js +36 -11
  122. package/dist/sdk/sessions/compactionCheckpoint.d.ts +11 -0
  123. package/dist/sdk/sessions/compactionCheckpoint.js +79 -0
  124. package/dist/sdk/sessions/continuation.d.ts +3 -0
  125. package/dist/sdk/sessions/continuation.js +5 -1
  126. package/dist/sdk/sessions/contracts.d.ts +185 -0
  127. package/dist/sdk/sessions/contracts.js +101 -4
  128. package/dist/sdk/sessions/control.d.ts +72 -0
  129. package/dist/sdk/sessions/control.js +158 -0
  130. package/dist/sdk/sessions/initialBash.d.ts +7 -0
  131. package/dist/sdk/sessions/initialBash.js +7 -0
  132. package/dist/sdk/sessions/planMode.d.ts +18 -4
  133. package/dist/sdk/sessions/planMode.js +82 -16
  134. package/dist/sdk/sessions/reasoningSummaries.d.ts +2 -2
  135. package/dist/sdk/sessions/reasoningSummaries.js +3 -3
  136. package/dist/sdk/sessions/registry.d.ts +2 -1
  137. package/dist/sdk/sessions/registry.js +6 -3
  138. package/dist/sdk/sessions/runIndex.js +7 -7
  139. package/dist/sdk/sessions/runStore.d.ts +14 -0
  140. package/dist/sdk/sessions/runStore.js +38 -1
  141. package/dist/sdk/sessions/runner.d.ts +40 -2
  142. package/dist/sdk/sessions/runner.js +163 -15
  143. package/dist/sdk/sessions/sessions.d.ts +40 -8
  144. package/dist/sdk/sessions/sessions.js +279 -27
  145. package/dist/sdk/sessions/sideQuestionServerMethods.d.ts +3 -0
  146. package/dist/sdk/sessions/sideQuestionServerMethods.js +19 -0
  147. package/dist/sdk/sessions/sideQuestions.d.ts +66 -0
  148. package/dist/sdk/sessions/sideQuestions.js +290 -0
  149. package/dist/sdk/sessions/subagentServerMethods.d.ts +3 -0
  150. package/dist/sdk/sessions/subagentServerMethods.js +41 -0
  151. package/dist/sdk/sessions/subagentService.d.ts +22 -2
  152. package/dist/sdk/sessions/subagentService.js +93 -16
  153. package/dist/sdk/sessions/subagents.d.ts +9 -1
  154. package/dist/sdk/sessions/subagents.js +19 -0
  155. package/dist/sdk/sessions/workSlice.d.ts +103 -0
  156. package/dist/sdk/sessions/workSlice.js +297 -0
  157. package/dist/sdk/sessions/workspaceBoundary.d.ts +15 -0
  158. package/dist/sdk/sessions/workspaceBoundary.js +46 -0
  159. package/dist/sdk/terminal/browser.d.ts +62 -0
  160. package/dist/sdk/terminal/browser.js +41 -0
  161. package/dist/sdk/terminal/browserControl.d.ts +29 -0
  162. package/dist/sdk/terminal/browserControl.js +187 -0
  163. package/dist/sdk/terminal/commandHelp.d.ts +17 -0
  164. package/dist/sdk/terminal/commandHelp.js +20 -0
  165. package/dist/sdk/terminal/controller.d.ts +15 -1
  166. package/dist/sdk/terminal/controller.js +67 -8
  167. package/dist/sdk/terminal/opentui/subagentsWidget.d.ts +28 -0
  168. package/dist/sdk/terminal/opentui/subagentsWidget.js +52 -0
  169. package/dist/sdk/terminal/opentui/theme.d.ts +43 -0
  170. package/dist/sdk/terminal/opentui/theme.js +87 -0
  171. package/dist/sdk/terminal/piExtension.d.ts +6 -1
  172. package/dist/sdk/terminal/piExtension.js +169 -84
  173. package/dist/sdk/terminal/socket.d.ts +6 -3
  174. package/dist/sdk/terminal/socket.js +40 -9
  175. package/dist/sdk/terminal/standalone.d.ts +9 -0
  176. package/dist/sdk/terminal/standalone.js +118 -19
  177. package/dist/sdk/terminal/subagentMonitor.d.ts +47 -0
  178. package/dist/sdk/terminal/subagentMonitor.js +152 -0
  179. package/dist/sdk/terminal/terminals.d.ts +60 -7
  180. package/dist/sdk/terminal/terminals.js +598 -47
  181. package/dist/sdk/terminal/trajectory.js +2 -2
  182. package/dist/sdk/terminal/tui/annotateCommand.d.ts +3 -0
  183. package/dist/sdk/terminal/tui/annotateCommand.js +22 -0
  184. package/dist/sdk/terminal/tui/commandPages.d.ts +7 -1
  185. package/dist/sdk/terminal/tui/commandPages.js +57 -6
  186. package/dist/sdk/terminal/tui/commands.d.ts +10 -4
  187. package/dist/sdk/terminal/tui/commands.js +269 -65
  188. package/dist/sdk/terminal/tui/dialogGeometry.d.ts +2 -2
  189. package/dist/sdk/terminal/tui/dialogGeometry.js +4 -2
  190. package/dist/sdk/terminal/tui/dialogs.d.ts +6 -1
  191. package/dist/sdk/terminal/tui/dialogs.js +9 -2
  192. package/dist/sdk/terminal/tui/list.d.ts +14 -1
  193. package/dist/sdk/terminal/tui/list.js +96 -14
  194. package/dist/sdk/terminal/tui/modelPicker.js +1 -6
  195. package/dist/sdk/terminal/tui/page.d.ts +3 -0
  196. package/dist/sdk/terminal/tui/pageOverlay.js +27 -7
  197. package/dist/sdk/terminal/tui/pages/accountsPage.d.ts +26 -4
  198. package/dist/sdk/terminal/tui/pages/accountsPage.js +264 -36
  199. package/dist/sdk/terminal/tui/pages/agentsPage.d.ts +74 -0
  200. package/dist/sdk/terminal/tui/pages/agentsPage.js +190 -0
  201. package/dist/sdk/terminal/tui/pages/annotatePage.d.ts +94 -0
  202. package/dist/sdk/terminal/tui/pages/annotatePage.js +341 -0
  203. package/dist/sdk/terminal/tui/pages/browserPage.d.ts +87 -0
  204. package/dist/sdk/terminal/tui/pages/browserPage.js +738 -0
  205. package/dist/sdk/terminal/tui/pages/doctorPage.d.ts +2 -0
  206. package/dist/sdk/terminal/tui/pages/doctorPage.js +103 -15
  207. package/dist/sdk/terminal/tui/pages/notesPage.d.ts +75 -0
  208. package/dist/sdk/terminal/tui/pages/notesPage.js +201 -0
  209. package/dist/sdk/terminal/tui/pages/pluginsPage.d.ts +0 -5
  210. package/dist/sdk/terminal/tui/pages/pluginsPage.js +9 -3
  211. package/dist/sdk/terminal/tui/pages/settingsPage.d.ts +8 -0
  212. package/dist/sdk/terminal/tui/pages/settingsPage.js +16 -1
  213. package/dist/sdk/terminal/tui/pages/subagentsPage.d.ts +24 -0
  214. package/dist/sdk/terminal/tui/pages/subagentsPage.js +152 -0
  215. package/dist/sdk/terminal/tui/pages/trajectoryPage.d.ts +12 -5
  216. package/dist/sdk/terminal/tui/pages/trajectoryPage.js +156 -83
  217. package/dist/sdk/terminal/tui/pages/usagePage.d.ts +43 -0
  218. package/dist/sdk/terminal/tui/pages/usagePage.js +370 -0
  219. package/dist/sdk/terminal/tui/pages/worktreesPage.d.ts +72 -0
  220. package/dist/sdk/terminal/tui/pages/worktreesPage.js +203 -0
  221. package/dist/sdk/terminal/tui/piAdapter.d.ts +1 -2
  222. package/dist/sdk/terminal/tui/piAdapter.js +3 -5
  223. package/dist/sdk/terminal/tui/planMode.d.ts +1 -1
  224. package/dist/sdk/terminal/tui/planMode.js +1 -1
  225. package/dist/sdk/terminal/tui/pluginCommands.d.ts +16 -0
  226. package/dist/sdk/terminal/tui/pluginCommands.js +31 -0
  227. package/dist/sdk/terminal/tui/questions.d.ts +2 -0
  228. package/dist/sdk/terminal/tui/runtime.js +27 -5
  229. package/dist/sdk/terminal/tui/sessionPicker.d.ts +40 -0
  230. package/dist/sdk/terminal/tui/sessionPicker.js +141 -0
  231. package/dist/sdk/terminal/tui/settingsModel.d.ts +2 -0
  232. package/dist/sdk/terminal/tui/settingsModel.js +32 -2
  233. package/dist/sdk/terminal/tui/sideQuestion.d.ts +26 -26
  234. package/dist/sdk/terminal/tui/sideQuestion.js +131 -98
  235. package/dist/sdk/terminal/tui/ui.d.ts +2 -0
  236. package/dist/sdk/terminal/tui/ui.js +1 -0
  237. package/dist/sdk/tools/askUser.js +26 -8
  238. package/dist/sdk/tools/checklist.js +3 -2
  239. package/dist/sdk/tools/checkpoint.d.ts +27 -0
  240. package/dist/sdk/tools/checkpoint.js +154 -0
  241. package/dist/sdk/tools/getCapabilities.d.ts +31 -0
  242. package/dist/sdk/tools/getCapabilities.js +34 -0
  243. package/dist/sdk/tools/harnessTools.d.ts +2 -0
  244. package/dist/sdk/tools/harnessTools.js +1 -1
  245. package/dist/sdk/tools/spawnSubagent.js +14 -4
  246. package/dist/sdk/usage/analytics.d.ts +20 -0
  247. package/dist/sdk/usage/analytics.js +151 -0
  248. package/dist/sdk/usage/ledger.d.ts +38 -0
  249. package/dist/sdk/usage/ledger.js +142 -0
  250. package/dist/sdk/usage/limits/adapters.d.ts +11 -0
  251. package/dist/sdk/usage/limits/adapters.js +349 -0
  252. package/dist/sdk/usage/limits/capture.d.ts +8 -0
  253. package/dist/sdk/usage/limits/capture.js +47 -0
  254. package/dist/sdk/usage/limits/http.d.ts +12 -0
  255. package/dist/sdk/usage/limits/http.js +51 -0
  256. package/dist/sdk/usage/limits/normalize.d.ts +15 -0
  257. package/dist/sdk/usage/limits/normalize.js +211 -0
  258. package/dist/sdk/usage/limits/service.d.ts +30 -0
  259. package/dist/sdk/usage/limits/service.js +176 -0
  260. package/dist/sdk/usage/limits/types.d.ts +65 -0
  261. package/dist/sdk/usage/limits/types.js +1 -0
  262. package/dist/sdk/usage/serverMethods.d.ts +3 -0
  263. package/dist/sdk/usage/serverMethods.js +22 -0
  264. package/dist/sdk/usage/service.d.ts +32 -0
  265. package/dist/sdk/usage/service.js +66 -0
  266. package/dist/sdk/usage/settings.d.ts +7 -0
  267. package/dist/sdk/usage/settings.js +28 -0
  268. package/dist/sdk/usage/types.d.ts +60 -0
  269. package/dist/sdk/usage/types.js +4 -0
  270. package/dist/sdk/web/part.d.ts +10 -0
  271. package/dist/sdk/web/part.js +6 -0
  272. package/dist/sdk/web/serverMethods.d.ts +3 -0
  273. package/dist/sdk/web/serverMethods.js +7 -0
  274. package/dist/sdk/wiki/serverMethods.d.ts +3 -0
  275. package/dist/sdk/wiki/serverMethods.js +26 -0
  276. package/dist/sdk/worktrees/cli.d.ts +11 -0
  277. package/dist/sdk/worktrees/cli.js +146 -0
  278. package/dist/sdk/worktrees/copy.d.ts +9 -0
  279. package/dist/sdk/worktrees/copy.js +111 -0
  280. package/dist/sdk/worktrees/git.d.ts +16 -0
  281. package/dist/sdk/worktrees/git.js +81 -0
  282. package/dist/sdk/worktrees/serverMethods.d.ts +3 -0
  283. package/dist/sdk/worktrees/serverMethods.js +30 -0
  284. package/dist/sdk/worktrees/service.d.ts +73 -0
  285. package/dist/sdk/worktrees/service.js +483 -0
  286. package/dist/sdk/worktrees/setup.d.ts +23 -0
  287. package/dist/sdk/worktrees/setup.js +65 -0
  288. package/dist/sdk/worktrees/types.d.ts +91 -0
  289. package/dist/sdk/worktrees/types.js +1 -0
  290. package/dist/sdk/world/cli.d.ts +2 -2
  291. package/dist/sdk/world/cli.js +6 -6
  292. package/dist/sdk/world/world.d.ts +3 -1
  293. package/dist/sdk/world/world.js +8 -9
  294. package/dist/terminal-opentui.js +16456 -5966
  295. package/dist/terminal-pi.js +1579 -573
  296. package/docs/README.md +22 -2
  297. package/docs/architecture/00-overview.md +28 -16
  298. package/docs/architecture/02-sessions-and-runs.md +184 -25
  299. package/docs/architecture/03-variants.md +10 -2
  300. package/docs/architecture/04-prompt.md +65 -7
  301. package/docs/architecture/06-plugins-and-capabilities.md +57 -4
  302. package/docs/architecture/07-tools-and-gate.md +112 -17
  303. package/docs/architecture/08-memory-and-history.md +4 -2
  304. package/docs/architecture/09-accounts-and-connectors.md +39 -1
  305. package/docs/architecture/10-server-protocol.md +168 -4
  306. package/docs/architecture/11-terminal.md +251 -8
  307. package/docs/architecture/12-storage.md +45 -3
  308. package/docs/architecture/13-world-tools.md +49 -6
  309. package/docs/architecture/14-surfaces-and-parity.md +136 -0
  310. package/docs/architecture/README.md +17 -4
  311. package/docs/architecture/proposals/PROP-0006-run-checklist.md +4 -2
  312. package/docs/architecture/proposals/PROP-0013-resource-browser.md +58 -0
  313. package/docs/architecture/proposals/PROP-0014-fullscreen-browser-tabs.md +58 -0
  314. package/docs/architecture/proposals/PROP-0015-one-capability-surface.md +88 -0
  315. package/docs/architecture/proposals/PROP-0016-managed-worktrees.md +156 -0
  316. package/docs/architecture/proposals/PROP-0017-page-annotations.md +131 -0
  317. package/docs/architecture/proposals/PROP-0018-annotation-queue-and-app-targets.md +179 -0
  318. package/docs/architecture/proposals/PROP-0019-contextual-side-questions.md +122 -0
  319. package/docs/architecture/proposals/PROP-0020-builtin-feature-plugins.md +105 -0
  320. package/docs/architecture/proposals/PROP-0021-command-namespaces-and-duplicates.md +99 -0
  321. package/docs/architecture/proposals/PROP-0022-plan-only-questions.md +102 -0
  322. package/docs/architecture/proposals/PROP-0023-xagent-cli-name.md +61 -0
  323. package/docs/architecture/proposals/PROP-0024-question-sketch-previews.md +130 -0
  324. package/docs/architecture/proposals/PROP-0025-contextual-question-wireframes.md +49 -0
  325. package/docs/architecture/proposals/PROP-0026-connected-sketch-display.md +94 -0
  326. package/docs/architecture/proposals/PROP-0027-xingular-agent-product-identity.md +60 -0
  327. package/docs/architecture/proposals/PROP-0028-normalize-question-wireframes.md +55 -0
  328. package/docs/architecture/proposals/PROP-0029-agent-profiles.md +124 -0
  329. package/docs/architecture/proposals/PROP-0030-subagent-title.md +86 -0
  330. package/docs/architecture/proposals/PROP-0031-plugin-command-owner-namespaces.md +54 -0
  331. package/docs/architecture/proposals/PROP-0032-planning-quality.md +196 -0
  332. package/docs/architecture/proposals/PROP-0033-compaction-plan-checkpoints.md +75 -0
  333. package/docs/architecture/proposals/PROP-0034-conversation-fast-mode.md +120 -0
  334. package/docs/architecture/proposals/PROP-0035-retain-subagent-status.md +47 -0
  335. package/docs/architecture/proposals/PROP-0036-first-class-harness-commands.md +59 -0
  336. package/docs/architecture/proposals/PROP-0037-workspace-write-boundary.md +63 -0
  337. package/docs/architecture/proposals/PROP-0038-annotate-open-shadow-roots.md +73 -0
  338. package/docs/architecture/proposals/PROP-0039-workspace-boundary-hardening.md +139 -0
  339. package/docs/architecture/proposals/PROP-0040-one-launch-path.md +87 -0
  340. package/docs/architecture/proposals/PROP-0041-bounded-work-slices.md +247 -0
  341. package/docs/architecture/proposals/PROP-0042-usage-and-provider-limits.md +127 -0
  342. package/docs/architecture/proposals/PROP-0043-read-only-plan-bash.md +74 -0
  343. package/docs/architecture/proposals/README.md +39 -0
  344. package/docs/decisions/ADR-0001-owned-terminal.md +1 -1
  345. package/docs/decisions/ADR-0009-xharness-command.md +6 -5
  346. package/docs/decisions/ADR-0014-public-release-baseline.md +3 -2
  347. package/docs/decisions/ADR-0015-resource-browser.md +28 -0
  348. package/docs/decisions/ADR-0016-fullscreen-browser-tabs.md +31 -0
  349. package/docs/decisions/ADR-0017-one-capability-surface.md +34 -0
  350. package/docs/decisions/ADR-0018-builtin-feature-plugins.md +35 -0
  351. package/docs/decisions/ADR-0019-managed-git-worktrees.md +31 -0
  352. package/docs/decisions/ADR-0020-page-annotations.md +37 -0
  353. package/docs/decisions/ADR-0021-required-command-namespaces.md +40 -0
  354. package/docs/decisions/ADR-0022-plan-only-question-tools.md +34 -0
  355. package/docs/decisions/ADR-0023-contextual-side-question-runs.md +35 -0
  356. package/docs/decisions/ADR-0024-xagent-command.md +40 -0
  357. package/docs/decisions/ADR-0025-question-choice-sketches.md +49 -0
  358. package/docs/decisions/ADR-0026-contextual-question-wireframes.md +58 -0
  359. package/docs/decisions/ADR-0027-connected-sketch-display.md +60 -0
  360. package/docs/decisions/ADR-0028-xingular-agent-product-identity.md +56 -0
  361. package/docs/decisions/ADR-0029-normalized-question-wireframe-borders.md +33 -0
  362. package/docs/decisions/ADR-0030-agent-profiles.md +43 -0
  363. package/docs/decisions/ADR-0031-plugin-command-owner-namespaces.md +37 -0
  364. package/docs/decisions/ADR-0032-compaction-run-checkpoints.md +33 -0
  365. package/docs/decisions/ADR-0033-plan-mode-research-delegation.md +47 -0
  366. package/docs/decisions/ADR-0034-first-class-harness-terminal-commands.md +25 -0
  367. package/docs/decisions/ADR-0035-one-launch-path.md +40 -0
  368. package/docs/decisions/ADR-0036-workspace-write-operation-boundary.md +54 -0
  369. package/docs/decisions/ADR-0037-usage-ledger-and-provider-limits.md +44 -0
  370. package/docs/decisions/ADR-0038-plan-bash-os-read-only.md +29 -0
  371. package/docs/doctor.md +10 -4
  372. package/docs/experiments/EXP-0003-performance-audit/data/session-runtime-replication.json +420 -0
  373. package/docs/experiments/EXP-0003-performance-audit/data/session-runtime.json +420 -0
  374. package/docs/experiments/EXP-0003-performance-audit/data/terminal-compact.json +376 -0
  375. package/docs/experiments/EXP-0003-performance-audit/data/terminal-history.json +422 -0
  376. package/docs/experiments/EXP-0003-performance-audit/data/terminal-question.json +95 -0
  377. package/docs/experiments/EXP-0003-performance-audit/data/terminal-wide.json +1036 -0
  378. package/docs/experiments/EXP-0003-performance-audit/plan.md +109 -0
  379. package/docs/experiments/EXP-0003-performance-audit/results.md +151 -0
  380. package/docs/features/README.md +26 -0
  381. package/docs/features/interfaces/README.md +1 -1
  382. package/docs/future-work.md +48 -0
  383. package/docs/handoff-2026-10-25-app-parity-and-solo-tabs.md +202 -0
  384. package/docs/parity.md +134 -0
  385. package/docs/releases/1.0.0.md +2 -2
  386. package/docs/releases/1.1.1.md +28 -0
  387. package/docs/releases/1.2.0.md +49 -0
  388. package/docs/releases/4.0.0.md +47 -0
  389. package/docs/releases/README.md +37 -27
  390. package/docs/study/00-index.md +8 -0
  391. package/docs/study/STUDY-0003-long-horizon-runs.md +210 -0
  392. package/docs/study/autonomous-engineering-sources.md +277 -0
  393. package/docs/study/autonomy-sources.md +147 -0
  394. package/docs/study/proactive-autonomy.md +408 -0
  395. package/docs/study/tui-resource-browser.md +78 -0
  396. package/docs/terminal-tui.md +386 -113
  397. package/package.json +6 -5
@@ -17,7 +17,8 @@ callable result for one run.
17
17
  | `Plugins` (`loading`, `loaded`) | `plugins/plugins.ts` | Chooses the paths a session or terminal loads; records what each extension registered. |
18
18
  | discovery | `plugins/discover.ts` | Finds items with Pi's own resolver, which runs no extension code. |
19
19
  | attachments (`load`, `save`, `attached`, `decided`, `set`) | `plugins/attachments.ts` | The one store of what is switched on, per scope. |
20
- | `HARNESS_PLUGINS` | `plugins/builtin.ts` | Descriptors of the harness's own parts: `pi`, `harness`, `subagents`, `wiki`, `history`, `ask-user`, `checklist`, `connected-apps`. |
20
+ | `BuiltinPluginRegistry`, `BuiltinPluginModule` | `plugins/builtinRegistry.ts`, `plugins/builtin.ts` | Registers built-in modules and their descriptors, world parts, server handlers and plugin-owned terminal commands. Harness core commands live in `commands/registry.ts`, shared by both surfaces. |
21
+ | `HARNESS_PLUGINS` | `plugins/builtin.ts` | Descriptor view of the registered Harness parts and feature plugins. |
21
22
  | `FIRST_PARTY_PLUGINS` | `plugins/firstParty.ts` | `output-trim`, `budget-guard`: inline extensions shipped switched off. `lessons`: switched off; its contribution turns on reflection after a run (page 08, PROP-0008) and loads no Pi code. |
22
23
  | `Hooks` | `plugins/hooks.ts` | Runs a package's hooks file after a write. |
23
24
  | install / trust | `plugins/install.ts`, `plugins/trust.ts` | Install through Pi's package manager with scripts off; trust code by hash. |
@@ -28,21 +29,41 @@ callable result for one run.
28
29
  ## Contracts
29
30
 
30
31
  - **Loading.** `Plugins.loading({ cwd, agentDir, caller, contributions, install? })` returns
31
- `extensionPaths`, `skillPaths`, `promptPaths`, `themePaths`, `builtins` (terminal only), `hooks`,
32
+ `extensionPaths`, `skillPaths`, `promptPaths`, `themePaths`, `builtins` (legacy shape; no Pi CLI built-ins selected), `hooks`,
32
33
  `found`, `detached`, `projectCode`, `packageCode`. A session opens Pi with its own discovery off
33
34
  and only these paths; a terminal receives them as `--extension`, `--skill`,
34
35
  `--prompt-template` and `--theme` after `--no-extensions --no-skills --no-prompt-templates
35
36
  --no-themes`. Pi still reads `AGENTS.md` and `SYSTEM.md` itself.
37
+ - **Surface metadata (PROP-0040).** `PluginDescriptor.surfaces` and `Plugin.surfaces` optionally
38
+ carry `{ preferred: 'host', terminal: 'fallback' | 'unavailable', note: string }`.
39
+ `plugins/surfaces.ts` formats the note and badge. Inspection explains what the host adds and
40
+ what the terminal does instead; this is not a category, attachment switch or permission.
41
+ - **Shared resources (PROP-0040).** Both surfaces load Harness-selected resources and enabled
42
+ first-party hooks, including output trim and budget guard. Terminal preparation exposes these
43
+ through its protected bridge. Pi CLI-only llama.cpp, codemode, tool-search and MCP built-ins are
44
+ not selected or advertised as extra terminal capabilities. This does not remove Harness MCP.
36
45
  - **Attachments.** `config/plugin-attachments.json` holds `global`, `agents`, `projects` (each
37
46
  `{ on, off }`) and `settings` per plugin. The narrowest scope that says something wins: agent,
38
47
  then project, then everywhere. With no entry an item keeps its default.
48
+ - **Package metadata.** A Pi package may declare `"harness": { "extends": [...], "hooks": "./hooks.mjs", "commandPrefix": "my-tools" }`.
49
+ `commandPrefix` is optional; in the terminal, commands otherwise use a normalized package name as
50
+ their owner prefix. Prefixes use lowercase letters, digits and hyphens, starting with a letter;
51
+ `plugin` and `skill` are reserved. See page 11 for the command route and collision rules.
39
52
  - **Hooks.** A package declares `"harness": { "extends": [...], "hooks": "./hooks.mjs" }`. Events:
40
53
  `wiki.page.saved`, `history.run.ended`. A hook has 30 seconds; its errors are kept in
41
54
  `plugin-hooks.json`. `ctx.call(connection, tool, args)` reaches only a connected app that is on
42
55
  for everyone, and only a tool marked to run without asking.
43
56
  - **Capability set** (`CapabilitySet`): `{ version: 1, tools, connectors, contributions }`.
44
57
  `capabilities.resolve` returns the set available to a caller; `capabilities.intersect` /
45
- `toolIntersection` narrows it for a child.
58
+ `toolIntersection` narrows it for a child. The required `ask-user` plugin remains attached, but its
59
+ `ask_user` tool is included only for an attended plan run or a continuation pinned with that
60
+ capability. Automatic or refinement-triggered continuations with it are rejected rather than
61
+ weakening the frozen set. The `side-questions` descriptor owns the fixed instruction for the
62
+ restricted side-question run; it has no tools, providers, connectors, subagents or variant code
63
+ (PROP-0019). In plan mode, delegation is limited to research children: the resolved profile must
64
+ have explicit tool and plugin allowlists confined to the research set, and the child's frozen
65
+ capabilities are intersected with the parent and profile. A profile name or its instructions alone
66
+ never grants eligibility (INV-RUN-8).
46
67
 
47
68
  ## Invariants
48
69
 
@@ -70,8 +91,19 @@ callable result for one run.
70
91
  each delivery. A working folder's package cannot bring a hook.
71
92
  - **INV-PLG-9** Unattended runs load no extension found on disk (`INV-RUN-5`). The harness's own
72
93
  parts are required and refuse to be switched off; switching something on grants no permission.
94
+ A side-question run also has no variant plugin code or tool guidance (PROP-0019).
95
+ - **INV-PLG-10** Every Harness-managed built-in feature is registered by `BuiltinPluginRegistry`.
96
+ Its descriptor, world tools, server handlers and any plugin-owned terminal commands share one
97
+ owner. First-class Harness terminal commands are registered by the terminal command registry and
98
+ do not depend on a feature plugin's command metadata or attachment state. A module's world part
99
+ releases resources through the existing session and Harness lifecycle. This registry does not
100
+ load third-party Pi code or bypass its trust checks.
101
+ - **INV-PLG-11** Built-in plugin categories are a documentation ownership taxonomy. They are not a
102
+ `PluginDescriptor` field, a public response field or a second attachment scope.
73
103
  - **INV-CAP-1** A capability set only narrows. `intersect` never adds access; a run's set is
74
- frozen when it starts (`INV-RUN-2`).
104
+ frozen when it starts (`INV-RUN-2`). An agent profile's `plugins` list keeps only the parent's
105
+ contributions of those plugins (required plugins always stay) and drops the tools they own; it
106
+ never adds one (PROP-0029).
75
107
  - **INV-CAP-2** The capability contract is generic. It names no application task, role or UI
76
108
  concept.
77
109
  - **INV-CAP-3** A capability set says what may be called, not whether a call may run. The gate
@@ -91,3 +123,24 @@ callable result for one run.
91
123
  ## Source map
92
124
 
93
125
  `src/plugins/*.ts`, `src/capabilities/*.ts`, `src/core/changes.ts`.
126
+
127
+ ## Built-in ownership taxonomy (PROP-0020)
128
+
129
+ These categories make ownership visible in docs and source layout. They do not change plugin
130
+ metadata or availability:
131
+
132
+ | Category | Features | Foundation boundary |
133
+ |---|---|---|
134
+ | Foundation | Accounts, sessions and run recording, prompt and variant validation, gate, plugin loading/trust/attachments, resource browser, server and terminal frameworks | Release-owned infrastructure and security contracts |
135
+ | World | Web search/read tools, browser tools, page annotations | The isolated browser engine and network policy remain Foundation services |
136
+ | Memory | Wiki, history and trajectory | Storage and run records remain Foundation-owned services |
137
+ | Automation | Subagents, ask-user, checklist, lessons and refinement | Run lifecycle, capability narrowing and approval gate remain Foundation-owned |
138
+ | Integrations | Connected apps/MCP and Hub | Connector credentials and plugin installation remain behind Foundation services |
139
+ | Operations | Doctor, worktrees and usage | Diagnostics, repository operations and usage analytics remain Harness-managed services |
140
+
141
+ ## Terminal resource inspection
142
+
143
+ The unified browser joins saved plugin/contribution metadata with actual session skills and tool
144
+ registration. A saved on/off state does not prove a resource loaded; origins and owners distinguish
145
+ same-name resources. Protected install/remove, settings, attachment and trust actions call the
146
+ existing services. No second discovery or enablement mechanism is introduced (PROP-0013).
@@ -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
 
@@ -13,30 +15,90 @@ per-call gate that asks the application's policy, then standing approvals, then
13
15
  | `HarnessToolDefinition`, `RECALL_TOOLS`, `TRAJECTORY_TOOLS`, `WIKI_READ_TOOLS`, `WIKI_WRITE_TOOLS`, `SKILL_TOOLS`, `DEFAULT_TOOL_NAMES` | `tools/definitions.ts` | The harness's own tools, defined once. |
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
- | `askUserTool` (`ask_user`) | `tools/askUser.ts` | Stops the run and asks a question with choices. |
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. |
18
- | `subagentTools` | `tools/spawnSubagent.ts` | `spawn_subagent`, `wait_subagents`. |
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. |
19
+ | `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 and write one final update before replying; unfinished work is not automatically marked complete. |
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. |
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). |
19
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. |
20
23
  | gate | `sessions/sessions.ts::gate`, `sessions/runner.ts` | `ToolGate { ask, check }`, loaded as the last extension (`xagent-approvals`). |
21
24
  | `Approvals`, `decide`, `grant`, `approvalKey` | `sessions/approvals.ts` | Standing approvals. |
22
25
 
23
- Harness tools: `history_search`, `history_read`, `trajectory_search`, `trajectory_read`,
24
- `wiki_search`, `wiki_read`, `wiki_list`, `wiki_write` (not in the default set), `skill_load`,
25
- `ask_user`, `checklist_write`. Broker: `mcp_list_tools`, `mcp_call_tool`. Native Pi tools: `read`, `grep`, `find`,
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
+ `checklist_write`. Broker:
30
+ `mcp_list_tools`, `mcp_call_tool`. Native Pi tools: `read`, `grep`, `find`,
26
31
  `ls`, `edit`, `write`, `bash`.
27
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
+
48
+ ## Native file paths
49
+
50
+ The read-only `read`, `grep`, `find` and `ls` tools accept paths relative to the working folder,
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
+
28
79
  ## The gate, per call
29
80
 
81
+ For native `edit` and `write`, the canonical target check is added to policy scope before approval;
82
+ the registered tool can mutate only through the policy-bound atomic helper. Bash workspace scope
83
+ scans for external hard links and then runs under the OS sandbox. An explicit outside scope is
84
+ approved before execution and runs once; stdout/stderr never triggers approval or retry. The
85
+ eligible Full Permission switch may answer the explicit request under its existing restrictions, but
86
+ a remembered tool grant cannot.
87
+
30
88
  ```text
31
89
  child run and tool outside its snapshot ─► refuse
32
- plan mode and tool not research-safe ─► refuse (before approvals)
90
+ plan mode and tool/call not research-safe ─► refuse (including ineligible spawn profiles, outside-scope or denied Bash; before approvals)
91
+ plan-mode Bash ─► read-only OS sandbox, never widened, run once
92
+ canonicalize native write target / verify pinned root
33
93
  policy.scope(call)
34
94
  not allowed and (automatic or no approval possible) ─► refuse with reason
35
95
  policy.authorize(call) throws ─► refuse
36
- allowed, not humanOnly, (automatic or not gated) ─► run
37
- trigger probe or improver ─► refuse (nobody to ask)
38
- run.requestApproval(...) ─► standing approvals may answer, else the person
39
- denied ─► refuse
96
+ outside native file target ─► human-only one-call approval; eligible Full Permission may answer
97
+ Bash workspace scope ─► hard-link scan, OS sandbox, run once
98
+ Bash outside scope ─► pre-execution human-only approval, then run once unconfined
99
+ trigger probe, improver, reflection or unattended ─► refuse anything requiring a person
100
+ run.requestApproval(...) ─► standing approvals may answer where eligible, else the person
101
+ denied ─► refuse; never replay a command
40
102
  policy.authorize(call) again ─► run or refuse
41
103
  ```
42
104
 
@@ -50,18 +112,49 @@ the switch and global tools.
50
112
 
51
113
  - **INV-GATE-1** Every tool call of every run passes the gate. No tool source bypasses it,
52
114
  including extension-registered tools (which ask before every call) and the initial Bash command.
115
+ - **INV-TOOL-9** `checkpoint_write` records one bounded handoff for the active run and is read-only
116
+ and plan-safe: no field changes files, and the record is the `checkpoint` run event (PROP-0041).
117
+ - **INV-TOOL-10** Bash keeps one command budget on every surface: 120 seconds when the call says
118
+ nothing, 300 seconds as the ceiling without a `reason`, 900 seconds as the maximum, and a timeout
119
+ returns the partial output with a narrowing instruction instead of blocking the reply.
53
120
  - **INV-GATE-2** The gate is the last extension loaded, after disk, variant and inline extensions, so
54
121
  it sees the final input of every call.
55
- - **INV-GATE-3** Order is fixed: capability and plan-mode refusals, then the policy's scope and
56
- authorize, then standing approvals, then the person, then authorize again.
122
+ - **INV-GATE-3** Order is fixed: capability and plan-mode refusals, canonicalize native file-write
123
+ targets, consult the policy's scope and authorize, combine mandatory outside-write approval with
124
+ that scope, then eligible standing approvals or the person, then authorize again. Native mutations
125
+ revalidate the authorized target and use atomic replacement inside an OS-enforced write scope.
126
+ Default Bash scans for external hard links, then runs only inside the OS sandbox. `workspaceWriteScope:
127
+ 'outside'` requests human-only approval before running that exact command once with broader access.
128
+ Command output never proves a sandbox denial and never triggers approval or replay; earlier
129
+ side-effects are not repeated. The policy may tighten or deny a call, but cannot waive the boundary.
130
+ Outside file writes and broad Bash calls cannot use remembered per-tool approval; only the eligible
131
+ Full Permission switch can answer automatically under its existing restrictions. In plan mode, Bash
132
+ runs only in the read-only scope (PROP-0043): no writes but a discarded temp folder, no network,
133
+ no signals outside the sandbox, no macOS mach services; Full Permission and `outside` never apply.
57
134
  - **INV-GATE-4** Refinement runs (`probe`, `improver`) never ask a person; what would need one is
58
135
  refused, never queued (`INV-REF-4`).
59
- - **INV-GATE-5** A tool is registered only if its name is in the run's frozen capability set, in
60
- that order (`INV-CAP-1`).
136
+ - **INV-GATE-5** SDK tools are registered only if their names are in the run's frozen capability
137
+ set (`INV-CAP-1`). `get_capabilities` is a read-only Harness tool on structured and terminal
138
+ surfaces; it reports the frozen callable set and does not grant access. The terminal may retain
139
+ question-tool definitions in its private Pi inventory, but normal mode deactivates them; a plan
140
+ request activates only registered questions under its plan-mode gate.
61
141
  - **INV-GATE-6** Tool attachment bytes never enter the run-event stream; only references are
62
142
  recorded.
63
143
  - **INV-GATE-7** Tool descriptions name the product with `{product}` (filled by `describeTool`),
64
144
  never an application's name (`INV-BND-2`).
145
+ - **INV-GATE-8** Native reads are bounded by process and operating-system permissions, not by the
146
+ workspace root; absolute and `~` paths are valid. Every run pins its canonical `workspaceRoot`.
147
+ Native `edit` and `write` mutations revalidate the authorized canonical target and atomically
148
+ replace it under an OS-enforced scope; outside targets require human-only one-call approval and
149
+ cannot use remembered tool grants. Default Bash scans the workspace for possible outside hard-link
150
+ aliases and is OS-sandboxed to write only inside the root while retaining broad reads; the sandbox
151
+ prevents its own processes from creating cross-boundary hard links, and macOS denies all hard-link
152
+ creation in the sandbox. An incomplete scan or missing
153
+ enforcement fails closed. An explicit `workspaceWriteScope: 'outside'` request is approved before
154
+ execution and runs once; command output never triggers approval or retry. The terminal exposes the
155
+ same choice as `!outside <command>`. Full Permission is the only standing boundary bypass and
156
+ remains subject to host policy, authorization, read-only, plan, unattended, probe, improver and
157
+ reflection restrictions. The rule does not protect against a peer process running as the same user.
65
158
 
66
159
  ## Data
67
160
 
@@ -70,7 +163,9 @@ the switch and global tools.
70
163
  ## Source map
71
164
 
72
165
  `src/tools/*.ts`, `src/web/*.ts`, `src/sessions/sessions.ts`, `src/sessions/runner.ts`,
73
- `src/sessions/approvals.ts`, `src/sessions/policy.ts`.
166
+ `src/sessions/workspaceBoundary.ts`, `src/sessions/initialBash.ts`, `src/core/workspaceBashTool.ts`,
167
+ `src/core/workspaceSandbox.ts`, `src/core/workspaceWriteOperations.ts`, `src/sessions/approvals.ts`,
168
+ `src/sessions/policy.ts`. Decision: [ADR-0036](../decisions/ADR-0036-workspace-write-operation-boundary.md).
74
169
 
75
170
  ## Session naming (PROP-0010)
76
171
 
@@ -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
 
@@ -67,7 +67,7 @@ skills, prompts, rules and Pi packages.
67
67
  ## Data
68
68
 
69
69
  ```text
70
- <state dir>/accounts/ registry, per-account Pi agent folders, _shared/pi/, audit log
70
+ <state dir>/accounts/ registry, per-account Pi agent folders, _shared/pi/, audit log, per-account state (health, plan, limits)
71
71
  <state dir>/secrets.json default SecretStore (owner-only)
72
72
  <state dir>/connections.json connected apps, no secrets
73
73
  <state dir>/hub/catalog.json catalog cache
@@ -88,3 +88,41 @@ labels this local readiness. A selected live model probe sends one synthetic req
88
88
  at 64 tokens, and records usage through the normal run writer. It never substitutes an account.
89
89
  MCP live diagnostics connect and list tools on the selected scoped connector, without calling
90
90
  connector tools or starting sign-in. Disposable grants and clients are closed afterwards.
91
+
92
+ ## Provider limits (PROP-0042)
93
+
94
+ A limit reading says what a provider itself reported: a plan window, a credit balance, a rate
95
+ limit, or a configured organization limit. Three sources are used, in order:
96
+
97
+ 1. **Response headers** on the account's own model requests. Each account runtime's providers are
98
+ wrapped so `onResponse` sees status and headers; a terminal session's own runtime forwards only
99
+ the limit-bearing headers to the parent over the control-key-protected session socket.
100
+ `usage/limits/normalize.ts` understands `anthropic-ratelimit-*`, Anthropic unified plan windows,
101
+ `x-codex-*` and `x-ratelimit-*`, plus `Retry-After` on a 429. Raw headers are never stored.
102
+ 2. **The provider's own usage endpoint**, read with `Models.getAuth(provider)` so OAuth refresh
103
+ stays in Pi's serialized credential path: OpenRouter `GET /api/v1/key`, DeepSeek
104
+ `GET /user/balance`, Anthropic's organization `rate_limits` for an admin API key (configured
105
+ limits, not usage), ChatGPT/Codex `GET https://chatgpt.com/backend-api/wham/usage`, and
106
+ OpenCode Go `GET https://opencode.ai/zen/go/v1/usage`. A Codex request carries the account id
107
+ from the access token's JWT claim; an OpenCode Go request carries the account's API key.
108
+ The request is a bounded HTTPS GET that refuses redirects, caps its body, and never puts a
109
+ credential in an error. An endpoint reading replaces every limit for that provider; a header
110
+ reading only merges the windows it saw.
111
+ 3. **Unavailable**, with a reason. No percentage is invented; local usage is shown instead.
112
+
113
+ Undocumented endpoints require the usage plugin's `experimentalProbes` setting. Readings are
114
+ cached for `refreshMinutes` (default 10) and refreshed on a page open or an explicit refresh, never
115
+ by a background timer. They are stored in the account's existing state (`limits`,
116
+ `providerLimits`), never in a new file, and no credential is written. A reading carries both `usedPercent` and the additive
117
+ `remainingPercent`. The Limits page is a centered dialog: each window is a label and reset line
118
+ above a quota-left bar, green at 50% or more left, amber from 20–49%, and red below 20%. It adds
119
+ the local seven-day ledger without a label, so a provider's zero reading and this app's own use
120
+ are not confused.
121
+
122
+ ## Terminal connection setup
123
+
124
+ The unified browser exposes existing connection save/test/sign-in/sign-out/remove services through
125
+ private terminal controls (PROP-0013). New definitions are saved disabled. Saving does not connect,
126
+ sign in or approve tools. Secrets use masked fields and the existing secret store; snapshots omit
127
+ saved credential values and scrub connection errors/tool metadata. Hub documents remain inert until
128
+ a person explicitly chooses setup and completes the normal validated connection form.
@@ -12,7 +12,7 @@ to the host for the extension points the host supplies.
12
12
  | Type / function | Module | Role |
13
13
  |---|---|---|
14
14
  | `RpcPeer`, `Transport`, `stdioTransport`, `PROTOCOL_VERSION` | `server/rpc.ts` | Framing, requests, replies, host calls. |
15
- | `methods(harness)` | `server/methods.ts` | The method table. |
15
+ | `methods(harness)` | `server/methods.ts` | Merges Foundation handlers with built-in plugin handlers from `BuiltinPluginRegistry` and rejects overlapping ownership. |
16
16
  | `serve`, `attach` | `server/serve.ts` | Registers the table, forwards events and notices. |
17
17
  | `remoteSecrets`, remote policy, directory, tools | `server/remote.ts` | Extension points supplied by the host over the protocol. |
18
18
  | CLI `serve` | `src/cli.ts` | `serve --state <dir> --data <dir> --name <product> [--builtins <dir>] [--host-secrets] [--host-policy] [--host-tools] [--host-directory]`. |
@@ -27,9 +27,13 @@ harness → host { v: 1, id, call, params } host → harness { v: 1
27
27
  ```
28
28
 
29
29
  - stdout carries only protocol lines; diagnostics go to stderr.
30
+ - Run events use the validated, persisted payload schemas in page 02. `question.requested` may carry
31
+ the optional bounded ASCII sketch metadata described there; the server relays it without changing
32
+ answer payloads or the protocol framing (PROP-0024).
30
33
  - `harness.methods` lists every method. Groups in the table: `accounts`, `harnesses`, `runs`,
31
34
  `connections`, `plugins`, `wiki`, `refine`, `capabilities`, `hub`, `terminal`, `approvals`,
32
- `harness`, `subagents`, `sessions`, `library`, `recall`, `context`.
35
+ `harness`, `subagents`, `agents`, `sessions`, `sideQuestions`, `library`, `recall`, `context`,
36
+ `worktrees`, `annotations`, `commands`, `usage`.
33
37
  - Host calls (only with the matching `--host-*` flag): `secrets.get|set|delete`,
34
38
  `policy.scope|authorize|approval|connections`, `tools.call`. The host registers tools with
35
39
  `tools.register` and names with `directory.set`, and describes its parts with
@@ -37,10 +41,69 @@ harness → host { v: 1, id, call, params } host → harness { v: 1
37
41
  - `refine.start` takes `{ task, k?, mode?, improver?, executor?, baseVersion?, retainWorkspaces?, id? }`;
38
42
  `refine.candidates` returns each execution with `workspace: string | null` (page 05, PROP-0002, PROP-0003).
39
43
  - `runs.checklist { runId }` returns the run's latest checklist, `[]` when it wrote none (PROP-0006).
40
- - `runs.continuation { runId, sessionDir? }` returns a `Continuation`, and `sessions.run` accepts
41
- `continueFrom` (page 02, PROP-0007). `harness.status` reports `recovery.interruptedRunIds`.
44
+ - Run records include optional nullable `workspaceRoot`, the canonical root whose files a run may
45
+ modify by default (page 02). New Harness runs set it; older records may omit it. Hosts must
46
+ tolerate the additive field and must not nominate or widen the root.
47
+ - `agents.list { cwd? }` returns `{ profiles, problems }`; `agents.get { cwd?, name }` one profile;
48
+ `agents.create { cwd?, name, scope: 'global' | 'project', from? }` writes the template or a copy
49
+ and refuses an existing file; `agents.remove { cwd?, name, scope }` deletes a person's own file.
50
+ `subagents.spawn` takes `agent` as a profile name and returns `agent` and `unavailableTools`
51
+ (PROP-0029). It takes an optional `title` (at most six words); without one the child's title is
52
+ the first line of its brief (PROP-0030).
53
+ - `runs.continuation { runId, sessionDir? }` returns a `Continuation` (its `checkpoint` is the last
54
+ work-slice handoff), and `sessions.run` accepts `continueFrom` (page 02, PROP-0007) and `workSlice`
55
+ (PROP-0041). `harness.status` reports `recovery.interruptedRunIds`.
56
+ - `workSlice { enabled?, maxToolCalls?, maxMinutes?, maxNewTokens?, maxSlices?, continue? }` on
57
+ `sessions.run` bounds that reply; absent uses 160 calls, 40 minutes, 320 000 new tokens, 8 slices and
58
+ automatic continuation. A token cap counts new input, cache writes and output, never the cached
59
+ prefix. `enabled: false` turns the guard off for that run; `XINGULAR_WORK_SLICE=off` in the
60
+ launching process turns it off for every run in it, and nothing is persisted. The policy is
61
+ carried into the continuation. A value outside its range is refused with `invalid_request` before
62
+ the run record is written.
63
+ - The run-event stream adds `checkpoint` (the bounded handoff) and `heartbeat` (steps, elapsed time,
64
+ last tool, compactions, slice, call budget). Hosts must accept both; an unknown event type is still
65
+ relayed in order (INV-RUN-3).
42
66
  - Errors carry a stable `code`, a message and an optional hint (`core/errors.ts`).
43
67
 
68
+ ## Usage (PROP-0042)
69
+
70
+ | Method | Input | Reply |
71
+ |---|---|---|
72
+ | `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 |
73
+ | `usage.limits` | `{ accountId?, refresh?: boolean }` | `UsageLimitsReport`: per account and provider, the reading source, reason, observed time and limits |
74
+ | `usage.sync` | `{}` | `{ runs, indexed, lastIndexedAt }` |
75
+
76
+ The methods are contributed by the built-in `usage` plugin module and read only derived or stored
77
+ data; `refresh: true` is the only form that may contact a provider, once per due provider. The
78
+ terminal reaches the same service through protected `terminal.usage.summary|limits`, whose scope
79
+ comes from the terminal session, never from the request.
80
+
81
+ ## Commands and session controls (PROP-0040)
82
+
83
+ `commands.list { cwd?, accountId?, agentId?, projectId? }` returns `ListedCommand[]`: `name`,
84
+ optional `aliases`, `args`, `description`, `owner`, plus `group`, `source`
85
+ (`core | plugin | extension | prompt | skill`) and optional core `kind` (`session | page | local`).
86
+ Core metadata comes from `commands/registry.ts`; effective plugin contributions supply other routes.
87
+ Namespace/collision rules are shared; discovery neither runs a command nor proves surface acceptance.
88
+
89
+ For the methods below, `ref` means `{ sessionDir, sessionFile?, cwd? }`.
90
+
91
+ | Method | Input | Reply |
92
+ |---|---|---|
93
+ | `sessions.tree` | `ref` | `SessionTree`: file, leaf, entries and user-message fork points |
94
+ | `sessions.navigate` | `ref + { entryId }` | `{ leafId, editorText? }`; no summary/model request |
95
+ | `sessions.fork` | `ref + { entryId, targetDir }` | `{ sessionFile, editorText }` |
96
+ | `sessions.clone` | `ref + { targetDir }` | `{ sessionFile }` |
97
+ | `sessions.rename` | `ref + { name }` | `{ name }` |
98
+ | `sessions.lastReply` | `ref` | `{ text: string | null }` |
99
+ | `sessions.export` | `ref + { path }` | `{ path }`; absolute `.jsonl` branch export |
100
+ | `sessions.reload` | `{}` | `{ reloaded: true }`; reloads persistent hooks; structured turns load resources fresh |
101
+
102
+ `sessions.run` also accepts `command` for compact, navigation with optional summary, or HTML
103
+ export instead of prompt submission (page 02). These retain tracked run lifecycle and pins.
104
+ Saved-history helpers currently validate file scope but do not themselves fence active work;
105
+ host adapters must not infer concurrency safety from method availability.
106
+
44
107
  ## Invariants
45
108
 
46
109
  - **INV-SRV-1** `src/server/methods.ts` is the contract for every non-Node host. Adding a method
@@ -56,6 +119,10 @@ harness → host { v: 1, id, call, params } host → harness { v: 1
56
119
  variants, the Wiki, the prompt, connected apps, a recorded session, a plugin hook and the
57
120
  refinement demo. The App's sidecar tests parse every reply with its schemas and must pass too.
58
121
 
122
+ Built-in feature modules may contribute handlers through `BuiltinPluginRegistry`, but the
123
+ `methods(harness)` result remains the public contract. Plugin module ownership does not rename
124
+ methods or change their params, result shapes or authorization paths (PROP-0020).
125
+
59
126
  ## Source map
60
127
 
61
128
  `src/server/*.ts`, `src/cli.ts`, `src/core/errors.ts`, `scripts/prove-standalone.mjs`.
@@ -78,7 +145,104 @@ account/model, findings, and available live-check notices. Findings distinguish
78
145
  `live` and statuses `pass`, `warning`, `fail`, `disabled`, `blocked`, `unverified`. Schemas and
79
146
  Node types are exported. Jobs are in-memory until shutdown; real live-run records remain.
80
147
 
148
+ ## Side questions (PROP-0019)
149
+
150
+ | Method | Input | Reply |
151
+ |---|---|---|
152
+ | `sideQuestions.start` | `{ question, cwd, caller, context?: { instructions?, transcript?, references? }, parentRunId?, parentSessionId?, accountId?, model?, effort?, runId?, sessionId? }` | `{ runId, sessionId, nativeSessionId }` |
153
+ | `sideQuestions.read` | `{ runId, sessionId, afterSequence? }` | `{ run: RunRecord, events: RunEvent[] }` |
154
+ | `sideQuestions.interrupt` | `{ runId, sessionId }` | `{ runId }` |
155
+
156
+ The Harness builds bounded context from the parent's persisted effective prompt and public events
157
+ plus the surface's visible transcript. Read and interrupt require the side run's session id. The
158
+ standalone terminal exposes the same operations through control-key-protected
159
+ `terminal.sideQuestions.*` calls; its caller identity, account and working folder come from terminal
160
+ preparation, not client-supplied values.
161
+
81
162
  Remote `tools.register` may include `diagnostics: [{ id, category, title, tools, probe?: { notice,
82
163
  tool, input, contains } }]`. The host answers `tools.diagnose({ id, context })` with `{ status,
83
164
  evidence, remedy? }` for local inspection. A probe is a declared registered tool call through
84
165
  the gate, with an expected response marker; it cannot supply arbitrary executable code.
166
+
167
+ ## Private terminal resource controls (PROP-0013)
168
+
169
+ These methods are session-socket controls, not additions to the public host RPC table. All
170
+ require the claimed terminal control key; account, working directory and variant pin come
171
+ from preparation, never from the request.
172
+
173
+ | Method | Input | Reply |
174
+ |---|---|---|
175
+ | `terminal.browser.config` | `{}` | `{ allowPrivate }`, the device-local private-address setting |
176
+ | `terminal.browser.configure` | `{ allowPrivate: boolean }` | `{ allowPrivate }`, updated setting |
177
+ | `terminal.browser.snapshot` | `{ refresh?: boolean }` | `BrowserSnapshot`: resources, plugins, safe connection records, pinned/latest variant identity and Hub overview |
178
+ | `terminal.browser.read` | `{ id, latest?: boolean }` | `{ content }`, bounded enumerated resource content |
179
+ | `terminal.browser.importSkill` | `{ path }` | `{}`, validated bounded local bundle imported into the existing library |
180
+ | `terminal.browser.hubPreview` | `{ id, version, offset? }` | Existing `HubPreviewPage` |
181
+ | `terminal.browser.hubDocument` | `{ id, version }` | Existing verified installed document |
182
+ | `terminal.browser.connections.appClients` | `{}` | Existing available application OAuth catalog IDs |
183
+ | `terminal.browser.connections.save` | `{ input: ConnectionInput }` | Existing safe `Connection` record |
184
+ | `terminal.browser.connections.test\|signIn\|signOut\|remove` | `{ id }` | Existing connection service result |
185
+ | `terminal.usage.summary\|limits` | `{ scope, period, timezoneOffsetMinutes }` / `{ refresh? }` | Existing usage service result, scoped to this terminal's account and project |
186
+ | `terminal.usage.headers` | `{ provider, status, headers }` | `{}`; only limit-bearing headers, throttled, stored as an account limit reading |
187
+
188
+ Protected `plugins.install { source }` and `plugins.remove { pluginId }` delegate to the package
189
+ service. Optional matching callbacks extend `PluginControl`; hosts without them receive a clear
190
+ unsupported-operation error. No protocol version or persisted schema changes.
191
+
192
+ ## Worktrees (PROP-0016)
193
+
194
+ | Method | Input | Reply |
195
+ |---|---|---|
196
+ | `worktrees.list` | `{ repo? }` | active `WorktreeRecord[]` (of the repository `repo` is in) |
197
+ | `worktrees.removed` | `{ repo? }` | removed records that `restore` can bring back |
198
+ | `worktrees.status` | `{ id }` | `WorktreeStatus`: exists, head, changed paths, commits since it started |
199
+ | `worktrees.create` | `{ repo, name?, baseRef?, branch?, kind?, carryChanges?, setup? }` | `{ worktree, carried, included, setup }` |
200
+ | `worktrees.branch` | `{ id, name }` | the record, on branch `<prefix><name>` |
201
+ | `worktrees.handoff` | `{ id, direction: "toSource" \| "toWorktree", move? }` | `{ direction, patched, copied, stash }` |
202
+ | `worktrees.remove` | `{ id, force? }` | `{ worktree, snapshot }` |
203
+ | `worktrees.restore` | `{ id }` | the record |
204
+ | `worktrees.prune` | `{ repo?, keep? }` | `{ removed, failed }` |
205
+ | `worktrees.adopt` | `{ path }` | the record (kind `permanent`, origin `adopted`) |
206
+ | `worktrees.setup.trust` | `{ repo, hash }` | `{}` |
207
+
208
+ Errors: `not_a_repository`, `repository_empty`, `worktree_exists`, `branch_exists`,
209
+ `worktree_in_use`, `worktree_has_work`, `worktree_removed`, `worktree_missing`, `not_a_worktree`,
210
+ `handoff_target_dirty`, `handoff_conflict`, `git_failed`, `git_unavailable`. The terminal reaches the
211
+ same service through `terminal.worktrees.*` routes, which need the control key (`INV-TUI-4`).
212
+
213
+ ## Page notes (PROP-0017)
214
+
215
+ | Method | Input | Reply |
216
+ |---|---|---|
217
+ | `annotations.list` | `{ url?, query?, status?, offset?, limit? }` | `{ notes, total }`, newest first |
218
+ | `annotations.read` | `{ id }` | `Note` |
219
+ | `annotations.create` | `{ source, target, body, tags? }` | `Note` (private) |
220
+ | `annotations.update` | `{ id, expectedVersion, patch: { body?, tags?, status?, target? } }` | `Note` |
221
+ | `annotations.delete` | `{ id, expectedVersion }` | `{}` |
222
+ | `annotations.share` | `{ id, principal: { sessionId } \| { agentId }, binding? }` | `Note` |
223
+ | `annotations.unshare` | `{ id, principal }` | `Note` |
224
+ | `annotations.revokeBinding` | `{ binding }` | `{ revoked }` |
225
+ | `annotations.import` | `{ notes }` | `{ imported, skipped }` (ids kept) |
226
+ | `annotations.pageScript` | `{}` | `{ script }`: the page helper, with `__ARGS__` for one operation |
227
+ | `annotations.queue` | `{ id, sessionId, expectedVersion?, autoSend? }` | `Note`, shared with the session and queued (PROP-0018) |
228
+ | `annotations.dequeue` / `annotations.confirm` | `{ id, expectedVersion? }` | `Note` |
229
+ | `annotations.queued` | `{ sessionId }` | `{ notes }`, oldest first |
230
+ | `annotations.createAndAct` | `{ note, action: save \| queue \| send, sessionId?, trusted? }` | `{ note, send }`; an untrusted send waits for `confirm` |
231
+ | `annotations.compose` | `{ sessionId, ids? }` | `{ text, ids }`: one instruction for a host's own `sessions.run` |
232
+ | `annotations.delivered` | `{ ids, sessionId, runId }` | `{ notes }`, marked sent |
233
+ | `annotations.send` | `{ sessionId, ids? }` | `{ state: sent \| busy \| host \| empty, … }` |
234
+ | `annotations.capture.attach` | `{ key, kind: web \| cdp \| bridge, endpoint?, name? }` | `{ kind, app, windows, bridge? }` |
235
+ | `annotations.capture.target` | `{ key }` | `{ kind, app, inspecting, windows }` |
236
+ | `annotations.capture.selectWindow` | `{ key, window }` | `{}` |
237
+ | `annotations.capture.open` | `{ key, url? }` | `{ url, title }` |
238
+ | `annotations.capture.inspect` / `stopInspect` | `{ key }` | `{ captureId }` / `{}` |
239
+ | `annotations.capture.next` | `{ key, sessionId?, surface? }` | `{ active, trusted, app, note, send, message, … }` |
240
+ | `annotations.capture.release` | `{ key }` | `{}` |
241
+ | `annotations.bridge.start` | `{}` | `{ port, token, scriptUrl, snippet }` |
242
+
243
+ Notices: `annotations.changed { sessionId, ids }` after any queue, send or fix;
244
+ `annotations.ready { sessionId, ids }` when a host session's waiting notes should be sent now.
245
+
246
+ Errors: `version_conflict`, `not_found`, `annotation_limit`, `invalid_request`, `invalid_data`. The
247
+ terminal reaches the same store through `terminal.annotations.*`, which shares only with its own
248
+ session and needs the control key (`INV-TUI-4`).