@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
package/dist/sdk/index.js CHANGED
@@ -20,9 +20,14 @@ export { fileSecretStore, memorySecretStore, secretKey } from "./accounts/secret
20
20
  export { dispatch as harnessCall } from "./tools/dispatch.js";
21
21
  export { compile, render, SECTION_ORDER, CONTEXT_MESSAGE_TYPE, CONTEXT_SNAPSHOT_KEY } from "./prompt/compile.js";
22
22
  export { runEventSchema, runRecordSchema, isActiveStatus } from "./sessions/contracts.js";
23
+ export { CORE_COMMANDS, coreCommand } from "./commands/registry.js";
24
+ export { STANDARD_CONNECTIONS } from "./prompt/standard.js";
25
+ export { SideQuestions, SIDE_QUESTION_INSTRUCTION, buildSideQuestionText } from "./sessions/sideQuestions.js";
23
26
  export { describeTool, HARNESS_TOOLS, DEFAULT_TOOL_NAMES, WIKI_WRITE } from "./tools/definitions.js";
24
27
  export { SPAWN_SUBAGENT, SUBAGENT_RELATION } from "./tools/spawnSubagent.js";
25
28
  export { CHECKLIST_WRITE, checklistOf } from "./tools/checklist.js";
29
+ export { BUILTIN_PROFILES } from "./agents/builtin.js";
30
+ export { PROFILE_COLORS, createProfile, listProfiles, parseProfile, profileDirs, removeProfile, resolveProfile } from "./agents/profiles.js";
26
31
  export { continuationOf } from "./sessions/continuation.js";
27
32
  export { webTools, WEB_PLUGIN, WEB_SEARCH_KEY } from "./web/tools.js";
28
33
  export { safeRequest } from "./web/safeRequest.js";
@@ -39,10 +44,15 @@ export { attach as attachPlugin, inventoryFor as pluginInventory, list as listPl
39
44
  export { HARNESS_PLUGINS } from "./plugins/builtin.js";
40
45
  export { FIRST_PARTY_PLUGINS } from "./plugins/firstParty.js";
41
46
  export { CONTRIBUTION_KINDS, PLUGIN_SOURCES } from "./plugins/types.js";
47
+ export { describePlugin, surfaceBadge } from "./plugins/surfaces.js";
42
48
  export { methods } from "./server/methods.js";
43
49
  export { remoteDirectory, remotePolicy, remoteSecrets, remoteTools } from "./server/remote.js";
44
50
  export { PROTOCOL_VERSION, RpcPeer, stdioTransport } from "./server/rpc.js";
45
51
  export { attach, serve } from "./server/serve.js";
46
52
  export { DEFAULT_SUBAGENT_DEPTH, MAX_SUBAGENT_DEPTH } from "./sessions/subagents.js";
47
53
  export { Subagents } from "./sessions/subagentService.js";
54
+ export { Worktrees } from "./worktrees/service.js";
48
55
  export { WAIT_SUBAGENTS } from "./sessions/subagents.js";
56
+ export * as pageNotes from "./annotations/store.js";
57
+ export { PAGE_SCRIPT } from "./annotations/pageScript.js";
58
+ export { NoteDeliveries } from "./annotations/delivery.js";
@@ -449,11 +449,12 @@ export class Connections {
449
449
  async launch(connection) {
450
450
  if (connection.kind === 'remote') {
451
451
  const headers = {};
452
- for (const key of connection.headerKeys) {
453
- const value = await this.secret(connection.id, headerItem(key));
454
- if (value !== null)
455
- headers[key] = value;
456
- }
452
+ if (connection.auth === 'headers')
453
+ for (const key of connection.headerKeys) {
454
+ const value = await this.secret(connection.id, headerItem(key));
455
+ if (value !== null)
456
+ headers[key] = value;
457
+ }
457
458
  return { id: connection.id, name: connection.name, transport: 'http', url: connection.url ?? '', headers, auth: connection.auth, scopes: connection.oauthScopes };
458
459
  }
459
460
  let command = findBinary(connection.command) ?? (isAbsolute(connection.command) ? connection.command : null);
@@ -573,7 +574,13 @@ export class Connections {
573
574
  throw scopeMigrationError();
574
575
  }
575
576
  connection.envKeys = [...(existing?.envKeys ?? [])];
576
- connection.headerKeys = [...(existing?.headerKeys ?? [])];
577
+ const keepHeaders = remote && connection.auth === 'headers' && existing?.kind === 'remote'
578
+ && existing.url === connection.url && existing.auth === 'headers';
579
+ connection.headerKeys = keepHeaders ? [...existing.headerKeys] : [];
580
+ if (!keepHeaders) {
581
+ for (const key of existing?.headerKeys ?? [])
582
+ await this.deleteSecret(connection.id, headerItem(key));
583
+ }
577
584
  // A sign-in belongs to one server and one client; never carry it to another.
578
585
  const sameServer = (existing?.url ?? null) === connection.url && (existing?.auth ?? '') === connection.auth && existing?.oauthClient === connection.oauthClient && existing?.catalogId === connection.catalogId && !oauthCredentials;
579
586
  if (!sameServer || connection.auth !== 'oauth')
@@ -588,7 +595,7 @@ export class Connections {
588
595
  else
589
596
  await this.deleteSecret(connection.id, OAUTH_CLIENT_SECRET);
590
597
  }
591
- for (const [key, value] of Object.entries(headers ?? {})) {
598
+ for (const [key, value] of Object.entries(remote && connection.auth === 'headers' ? headers ?? {} : {})) {
592
599
  if (!/^[A-Za-z0-9_-]+$/.test(key) || /[\r\n\0]/.test(value))
593
600
  throw invalid('Invalid header name or value.');
594
601
  await this.setSecret(connection.id, headerItem(key), value);
@@ -0,0 +1,3 @@
1
+ import type { Harness } from "../harness.js";
2
+ import type { Handler } from "../server/rpc.js";
3
+ export declare function connectedAppServerMethods(harness: Harness): Record<string, Handler>;
@@ -0,0 +1,22 @@
1
+ import { validateScopeIds } from "./connections.js";
2
+ import { optional, text } from "../server/params.js";
3
+ export function connectedAppServerMethods(harness) {
4
+ const apps = harness.apps;
5
+ return {
6
+ 'connections.list': () => apps.connections.list(),
7
+ 'connections.forScope': (params) => apps.connections.forScope({ agentId: optional(params, 'agentId'), projectId: optional(params, 'projectId') }),
8
+ 'connections.save': (params) => apps.save(params.input),
9
+ 'connections.allowTool': (params) => apps.connections.allowTool(text(params, 'connectionId'), text(params, 'tool')),
10
+ 'connections.remove': (params) => apps.remove(text(params, 'connectionId')),
11
+ 'connections.test': (params) => apps.test(text(params, 'connectionId')),
12
+ 'connections.signIn': (params) => apps.signIn(text(params, 'connectionId')),
13
+ 'connections.signOut': (params) => apps.signOut(text(params, 'connectionId')),
14
+ 'connections.runContext': (params) => apps.runContext(text(params, 'runId')),
15
+ 'connections.refreshSource': (params) => apps.refreshSource(text(params, 'runId'), text(params, 'traceId'), text(params, 'sourceUri')),
16
+ 'connections.setAgentScope': (params) => apps.setAgentScope(params.creator ?? {}, text(params, 'agentId'), Array.isArray(params.ids) ? params.ids : []),
17
+ 'connections.removeAgentScope': (params) => apps.removeAgentScope(text(params, 'agentId')),
18
+ 'connections.revision': () => apps.connections.revision(),
19
+ 'connections.appClients': () => apps.appClients(),
20
+ 'connections.validateScope': (params) => validateScopeIds(apps.connections.list(), { agentId: optional(params, 'agentId'), projectId: optional(params, 'projectId') }, Array.isArray(params.ids) ? params.ids : [])
21
+ };
22
+ }
@@ -1,4 +1,5 @@
1
- export declare const PINNED_PI_VERSION = "1.2.0";
1
+ export declare const PINNED_PI_VERSION = "1.4.0";
2
+ export declare const HTTP_DISPATCHER_CHUNK = "dist/bundle/chunks/chunk-MM3LKT73.js";
2
3
  type PiRuntimeModule = {
3
4
  VERSION: string;
4
5
  getPackageDir(): string;
@@ -1,7 +1,7 @@
1
1
  import { join } from 'node:path';
2
2
  import { pathToFileURL } from 'node:url';
3
- export const PINNED_PI_VERSION = '1.2.0';
4
- const HTTP_DISPATCHER_CHUNK = 'dist/bundle/chunks/chunk-TJXZSVTD.js';
3
+ export const PINNED_PI_VERSION = '1.4.0';
4
+ export const HTTP_DISPATCHER_CHUNK = 'dist/bundle/chunks/chunk-MM3LKT73.js';
5
5
  export function assertPiRuntimeVersion(version) {
6
6
  if (version !== PINNED_PI_VERSION)
7
7
  throw new Error(`The Harness Pi runtime requires Pi ${PINNED_PI_VERSION}; found ${version}. Install the Harness package's pinned dependencies.`);
@@ -3,4 +3,5 @@ import type { PluginDescriptor } from "./types.js";
3
3
  export declare const PI_PLUGIN: PluginDescriptor;
4
4
  /** The variant: the eight components that shape what an agent is told and can do. */
5
5
  export declare const VARIANT_PLUGIN: PluginDescriptor;
6
+ export declare const BUILTIN_PLUGIN_REGISTRY: import("./builtinRegistry.js").BuiltinPluginRegistry;
6
7
  export declare const HARNESS_PLUGINS: readonly PluginDescriptor[];
@@ -1,21 +1,50 @@
1
- // The harness's own parts, described as plugins. Each is a description of code that already
2
- // exists; none of it is loaded through Pi's extension system.
1
+ // Built-in feature modules register their contributions here; this registry never loads Pi code.
3
2
  import { CONNECTION_TOOLS, NATIVE_GROUP } from "../prompt/compile.js";
4
- import { ASK_USER } from "../tools/askUser.js";
5
- import { CHECKLIST_WRITE } from "../tools/checklist.js";
3
+ import { ASK_USER, askUserTool } from "../tools/askUser.js";
4
+ import { CHECKLIST_WRITE, checklistTool } from "../tools/checklist.js";
5
+ import { CHECKPOINT_WRITE, checkpointTool } from "../tools/checkpoint.js";
6
+ import { sliceOf } from "../sessions/workSlice.js";
6
7
  import { SPAWN_SUBAGENT, WAIT_SUBAGENTS } from "../sessions/subagents.js";
8
+ import { subagentTools } from "../tools/spawnSubagent.js";
9
+ import { SESSION_NAME } from "../tools/sessionName.js";
7
10
  import { RECALL_TOOLS, SKILL_TOOLS, TRAJECTORY_TOOLS, WIKI_READ_TOOLS, WIKI_WRITE_TOOLS } from "../tools/definitions.js";
8
11
  import { FIRST_PARTY_PLUGINS } from "./firstParty.js";
9
12
  import { WEB_PLUGIN } from "../web/tools.js";
10
- import { BROWSER_PLUGIN } from "../browser/index.js";
13
+ import { KEYLESS_SEARCH, webPart } from "../web/part.js";
14
+ import { BROWSER_PLUGIN, browserPluginPart } from "../browser/index.js";
15
+ import { ANNOTATIONS_PLUGIN } from "../annotations/part.js";
16
+ import { annotationsPart } from "../annotations/part.js";
17
+ import { webServerMethods } from "../web/serverMethods.js";
18
+ import { browserServerMethods } from "../browser/serverMethods.js";
19
+ import { annotationServerMethods } from "../annotations/serverMethods.js";
20
+ import { doctorServerMethods } from "../doctor/serverMethods.js";
21
+ import { worktreeServerMethods } from "../worktrees/serverMethods.js";
22
+ import { hubServerMethods } from "../hub/serverMethods.js";
23
+ import { refinementServerMethods } from "../refine/serverMethods.js";
24
+ import { wikiServerMethods } from "../wiki/serverMethods.js";
25
+ import { historyServerMethods } from "../history/serverMethods.js";
26
+ import { subagentServerMethods } from "../sessions/subagentServerMethods.js";
27
+ import { sideQuestionServerMethods } from "../sessions/sideQuestionServerMethods.js";
28
+ import { connectedAppServerMethods } from "../mcp/serverMethods.js";
29
+ import { harnessTools } from "../tools/harnessTools.js";
30
+ import { GET_CAPABILITIES } from "../tools/getCapabilities.js";
31
+ import { USAGE_SETTINGS } from "../usage/settings.js";
32
+ import { usageServerMethods } from "../usage/serverMethods.js";
33
+ import { createBuiltinPluginRegistry } from "./builtinRegistry.js";
11
34
  const tools = (definitions) => definitions.map((tool) => ({ name: tool.name, description: tool.label }));
35
+ const toolContribution = (definitions, toolOrder) => ({
36
+ toolOrder,
37
+ tools: (context) => context.harnessTools
38
+ ? harnessTools(context.env, context.caller, { variantDir: context.variantDir, definitions })
39
+ : []
40
+ });
12
41
  /** Pi itself. Its command's built-in extensions are added to it as they are found. */
13
42
  export const PI_PLUGIN = {
14
43
  id: 'pi',
15
44
  title: 'Pi',
16
45
  description: 'The engine every session runs on: its base prompt, its file and shell tools, and the extensions built into its command.',
17
46
  required: 'Pi runs every session.',
18
- tools: NATIVE_GROUP.map((name) => ({ name })),
47
+ tools: [...NATIVE_GROUP.map((name) => ({ name })), { name: SESSION_NAME }],
19
48
  toolGroups: ['Native']
20
49
  };
21
50
  /** The variant: the eight components that shape what an agent is told and can do. */
@@ -25,6 +54,7 @@ export const VARIANT_PLUGIN = {
25
54
  description: 'The agent\'s own variant: system prompt, guardrails, memory and tool guidance in every prompt; skills, scripts and subagents on demand; plugins in the tool loop. Versioned, and refined from evidence.',
26
55
  required: 'Every agent runs on a variant.',
27
56
  sections: [
57
+ { id: 'harness-identity', name: 'Harness identity', description: 'Fixed foundation identity; not part of the variant.' },
28
58
  { id: 'system', name: 'System prompt', description: 'c1: role and procedure.' },
29
59
  { id: 'guardrails', name: 'Guardrails', description: 'c2: standing rules.' },
30
60
  { id: 'memory', name: 'Memory', description: 'c3: durable facts about this kind of work.' },
@@ -34,35 +64,117 @@ export const VARIANT_PLUGIN = {
34
64
  ],
35
65
  tools: tools(SKILL_TOOLS)
36
66
  };
37
- export const HARNESS_PLUGINS = [
38
- PI_PLUGIN,
39
- { id: 'subagents', title: 'Subagents', description: 'Isolated child runs of the same caller, bounded by parent capabilities and nesting depth.', required: 'Availability is selected by the session host; child runs retain the parent permission boundary.', tools: [{ name: SPAWN_SUBAGENT, description: 'Start a subagent' }, { name: WAIT_SUBAGENTS, description: 'Wait for subagents' }] },
40
- VARIANT_PLUGIN,
67
+ const SUBAGENTS_PLUGIN = { id: 'subagents', title: 'Subagents', description: 'Isolated child runs of the same caller, bounded by parent capabilities and nesting depth.', required: 'Availability is selected by the session host; child runs retain the parent permission boundary.', tools: [{ name: SPAWN_SUBAGENT, description: 'Start a subagent' }, { name: WAIT_SUBAGENTS, description: 'Wait for subagents' }] };
68
+ const WIKI_PLUGIN = {
69
+ id: 'wiki',
70
+ title: 'Wiki',
71
+ description: 'Notes about projects, linked to each other, that agents search and read.',
72
+ required: 'Project notes are reached through it.',
73
+ tools: tools([...WIKI_READ_TOOLS, ...WIKI_WRITE_TOOLS]),
74
+ sections: [
75
+ { id: 'wiki', name: 'Wiki', description: 'The current project\'s notes.' },
76
+ { id: 'references', name: 'Selected references', description: 'Notes pinned to one request.' }
77
+ ],
78
+ toolGroups: ['Wiki']
79
+ };
80
+ const HISTORY_PLUGIN = { id: 'history', title: 'History', description: 'Search earlier conversations and inspect recorded run trajectories.', required: 'Earlier runs are how an agent picks up where work stopped.', tools: tools([...RECALL_TOOLS, ...TRAJECTORY_TOOLS]), toolGroups: ['History'] };
81
+ const ASK_USER_PLUGIN = { id: 'ask-user', title: 'Ask the user', description: 'Lets the agent stop and ask a question with choices.', required: 'An agent must be able to stop and ask you.', tools: [{ name: ASK_USER }] };
82
+ const CHECKLIST_PLUGIN = { id: 'checklist', title: 'Checklist', description: 'Lets the agent keep a checklist of the steps of its work, recorded with the run so progress can be shown and picked up again.', required: 'Progress of longer work is kept through it.', tools: [{ name: CHECKLIST_WRITE, description: 'Write the checklist' }] };
83
+ const CHECKPOINT_PLUGIN = { id: 'checkpoint', title: 'Checkpoint', description: 'Lets a bounded reply record a handoff at a work-slice boundary so the next slice starts from it.', required: 'A reply that stops at its budget leaves the state the next one resumes from.', tools: [{ name: CHECKPOINT_WRITE, description: 'Write the handoff checkpoint' }] };
84
+ const CONNECTED_APPS_PLUGIN = {
85
+ id: 'connected-apps',
86
+ title: 'Connected apps',
87
+ description: 'Outside services reached over MCP, behind two tools that list and call what is connected.',
88
+ required: 'Connected apps are reached only through it. Each app is switched on its own.',
89
+ manage: 'connections',
90
+ tools: CONNECTION_TOOLS.map((name) => ({ name })),
91
+ toolGroups: ['Connections']
92
+ };
93
+ const DOCTOR_PLUGIN = { id: 'doctor', title: 'Doctor', description: 'Local readiness checks and explicitly confirmed live probes for accounts, models and tools.', required: 'Every local terminal has readiness diagnostics.' };
94
+ const WORKTREES_PLUGIN = { id: 'worktrees', title: 'Worktrees', description: 'Create and manage isolated git worktrees, move changes between them, and restore removed worktrees.', required: 'Managed worktrees are available to every local terminal.' };
95
+ const HUB_PLUGIN = { id: 'hub', title: 'Hub', description: 'Browse and install reviewed skills, plugins and documents from configured registries.', required: 'Reviewed Harness resources are available to every host.' };
96
+ const REFINEMENT_PLUGIN = { id: 'refinement', title: 'Refinement', description: 'Improve variants from recorded evidence through isolated refinement runs and reviewed candidates.', required: 'Variant refinement is available to every host.' };
97
+ const CAPABILITIES_PLUGIN = { id: 'capabilities', title: 'Capability discovery', description: 'Inspect the callable tools of the current run, including their input schemas. Discovery never grants access.', required: 'Every interactive session can inspect its own registered capabilities.', tools: [{ name: GET_CAPABILITIES, description: 'Inspect current capabilities' }] };
98
+ const USAGE_PLUGIN = {
99
+ id: 'usage',
100
+ title: 'Usage',
101
+ description: 'Token, cost and latency totals from recorded runs, and the plan windows, balances or rate limits each provider reports.',
102
+ settings: [...USAGE_SETTINGS]
103
+ };
104
+ const SIDE_QUESTIONS_PLUGIN = {
105
+ id: 'side-questions',
106
+ title: 'Side questions',
107
+ description: 'Separate, tool-free answers that use a redacted projection of the main conversation.',
108
+ required: 'Every host can ask a side question without steering its main run.',
109
+ sections: [{ id: 'side-question', name: 'Side-question role', description: 'Fixed instructions for an independent, tool-free side run.' }]
110
+ };
111
+ export const BUILTIN_PLUGIN_REGISTRY = createBuiltinPluginRegistry([
112
+ {
113
+ descriptor: PI_PLUGIN,
114
+ toolOrder: 60,
115
+ tools: context => context.harnessTools ? [context.sessionName] : []
116
+ },
117
+ {
118
+ descriptor: SUBAGENTS_PLUGIN,
119
+ toolOrder: 70,
120
+ tools: context => context.allowedTools.includes(SPAWN_SUBAGENT)
121
+ ? subagentTools(context.subagents, context.runId).filter(tool => context.allowedTools.includes(tool.name))
122
+ : [],
123
+ serverMethods: subagentServerMethods
124
+ },
125
+ { descriptor: VARIANT_PLUGIN, ...toolContribution(SKILL_TOOLS, 30) },
126
+ { descriptor: WIKI_PLUGIN, ...toolContribution([...WIKI_READ_TOOLS, ...WIKI_WRITE_TOOLS], 20), serverMethods: wikiServerMethods },
41
127
  {
42
- id: 'wiki',
43
- title: 'Wiki',
44
- description: 'Notes about projects, linked to each other, that agents search and read.',
45
- required: 'Project notes are reached through it.',
46
- tools: tools([...WIKI_READ_TOOLS, ...WIKI_WRITE_TOOLS]),
47
- sections: [
48
- { id: 'wiki', name: 'Wiki', description: 'The current project\'s notes.' },
49
- { id: 'references', name: 'Selected references', description: 'Notes pinned to one request.' }
128
+ descriptor: HISTORY_PLUGIN,
129
+ ...toolContribution([...RECALL_TOOLS, ...TRAJECTORY_TOOLS], 10),
130
+ serverMethods: historyServerMethods
131
+ },
132
+ { descriptor: ASK_USER_PLUGIN, toolOrder: 40, tools: context => context.harnessTools && context.allowedTools.includes(ASK_USER) ? [askUserTool(context.run)] : [] },
133
+ { descriptor: CHECKLIST_PLUGIN, toolOrder: 50, tools: context => context.harnessTools ? [checklistTool(context.run)] : [] },
134
+ { descriptor: CHECKPOINT_PLUGIN, toolOrder: 51, tools: context => context.harnessTools && context.allowedTools.includes(CHECKPOINT_WRITE) ? [checkpointTool(context.run, () => sliceOf(context.env.root, context.runId))] : [] },
135
+ {
136
+ descriptor: CONNECTED_APPS_PLUGIN,
137
+ toolOrder: 0,
138
+ tools: context => context.connectionTools?.() ?? [],
139
+ serverMethods: connectedAppServerMethods
140
+ },
141
+ { descriptor: HUB_PLUGIN, serverMethods: hubServerMethods },
142
+ { descriptor: REFINEMENT_PLUGIN, serverMethods: refinementServerMethods },
143
+ { descriptor: SIDE_QUESTIONS_PLUGIN, serverMethods: sideQuestionServerMethods },
144
+ {
145
+ descriptor: WEB_PLUGIN,
146
+ createWorldPart: ({ options, setting }) => webPart({ secrets: options.secrets, request: options.request, keyless: () => setting(WEB_PLUGIN.id, KEYLESS_SEARCH) === 1 }),
147
+ serverMethods: webServerMethods
148
+ },
149
+ {
150
+ descriptor: BROWSER_PLUGIN,
151
+ createWorldPart: ({ browserEngine }) => browserEngine ? browserPluginPart(browserEngine) : null,
152
+ serverMethods: browserServerMethods
153
+ },
154
+ {
155
+ descriptor: ANNOTATIONS_PLUGIN,
156
+ commandPrefix: 'annotate',
157
+ defaultCommand: 'annotate',
158
+ commands: [
159
+ { name: 'notes', description: 'Review web annotations saved from pages and apps' },
160
+ { name: 'annotate', description: 'Inspect a page or app, comment on components, and send fixes: /annotate:annotate [url | --app <devtools address> | --bridge]' }
50
161
  ],
51
- toolGroups: ['Wiki']
162
+ createWorldPart: ({ options }) => annotationsPart({ root: options.root, changed: options.notesChanged }),
163
+ serverMethods: annotationServerMethods
52
164
  },
53
- { id: 'history', title: 'History', description: 'Search earlier conversations and inspect recorded run trajectories.', required: 'Earlier runs are how an agent picks up where work stopped.', tools: tools([...RECALL_TOOLS, ...TRAJECTORY_TOOLS]), toolGroups: ['History'] },
54
- { id: 'ask-user', title: 'Ask the user', description: 'Lets the agent stop and ask a question with choices.', required: 'An agent must be able to stop and ask you.', tools: [{ name: ASK_USER }] },
55
- { id: 'checklist', title: 'Checklist', description: 'Lets the agent keep a checklist of the steps of its work, recorded with the run so progress can be shown and picked up again.', required: 'Progress of longer work is kept through it.', tools: [{ name: CHECKLIST_WRITE, description: 'Write the checklist' }] },
165
+ { descriptor: CAPABILITIES_PLUGIN },
56
166
  {
57
- id: 'connected-apps',
58
- title: 'Connected apps',
59
- description: 'Outside services reached over MCP, behind two tools that list and call what is connected.',
60
- required: 'Connected apps are reached only through it. Each app is switched on its own.',
61
- manage: 'connections',
62
- tools: CONNECTION_TOOLS.map((name) => ({ name })),
63
- toolGroups: ['Connections']
167
+ descriptor: USAGE_PLUGIN,
168
+ commandPrefix: 'usage',
169
+ defaultCommand: 'analysis',
170
+ commands: [
171
+ { name: 'analysis', description: 'Token, cost and latency totals: /usage:analysis [today | 7d | 30d | all]' },
172
+ { name: 'limit', description: 'Provider plan windows, balances and rate limits: /usage:limit' }
173
+ ],
174
+ serverMethods: usageServerMethods
64
175
  },
65
- WEB_PLUGIN,
66
- BROWSER_PLUGIN,
67
- ...FIRST_PARTY_PLUGINS
68
- ];
176
+ { descriptor: DOCTOR_PLUGIN, serverMethods: doctorServerMethods },
177
+ { descriptor: WORKTREES_PLUGIN, serverMethods: worktreeServerMethods },
178
+ ...FIRST_PARTY_PLUGINS.map(descriptor => ({ descriptor }))
179
+ ]);
180
+ export const HARNESS_PLUGINS = BUILTIN_PLUGIN_REGISTRY.descriptors();
@@ -0,0 +1,60 @@
1
+ import type { Harness } from "../harness.js";
2
+ import type { Handler } from "../server/rpc.js";
3
+ import type { WorldOptions, WorldPart } from "../world/world.js";
4
+ import type { BrowserEngine } from "../browser/index.js";
5
+ import type { CallerContext } from "../core/caller.js";
6
+ import type { DispatchEnv } from "../tools/dispatch.js";
7
+ import type { ToolSpec } from "../tools/types.js";
8
+ import type { Subagents } from "../sessions/subagentService.js";
9
+ import type { ActiveRun } from "../sessions/registry.js";
10
+ import type { PluginDescriptor } from "./types.js";
11
+ export interface BuiltinPluginCommand {
12
+ pluginId: string;
13
+ prefix: string;
14
+ name: string;
15
+ description: string;
16
+ legacyBare: boolean;
17
+ }
18
+ export interface BuiltinWorldContext {
19
+ options: WorldOptions;
20
+ setting(pluginId: string, key: string): number;
21
+ browserEngine: BrowserEngine | null;
22
+ }
23
+ export interface BuiltinToolContext {
24
+ env: DispatchEnv;
25
+ caller: CallerContext;
26
+ variantDir: string | null;
27
+ run: ActiveRun;
28
+ runId: string;
29
+ allowedTools: readonly string[];
30
+ harnessTools: boolean;
31
+ subagents: Subagents;
32
+ sessionName: ToolSpec;
33
+ connectionTools?: () => ToolSpec[];
34
+ }
35
+ export interface BuiltinPluginModule {
36
+ descriptor: PluginDescriptor;
37
+ /** Stable terminal command namespace; defaults to the plugin id. */
38
+ commandPrefix?: string;
39
+ /** Command invoked by the namespace root, such as `/annotate:`. */
40
+ defaultCommand?: string;
41
+ /** Stable order for model tools, independent of descriptor display order. */
42
+ toolOrder?: number;
43
+ tools?: (context: BuiltinToolContext) => ToolSpec[];
44
+ commands?: readonly Omit<BuiltinPluginCommand, 'pluginId' | 'prefix' | 'legacyBare'>[];
45
+ createWorldPart?: (context: BuiltinWorldContext) => WorldPart | null;
46
+ serverMethods?: (harness: Harness) => Record<string, Handler>;
47
+ }
48
+ export interface BuiltinPluginRegistry {
49
+ readonly modules: readonly BuiltinPluginModule[];
50
+ descriptors(): PluginDescriptor[];
51
+ commands(): BuiltinPluginCommand[];
52
+ command(prefix: string, name: string): BuiltinPluginCommand | undefined;
53
+ commandsNamed(name: string): BuiltinPluginCommand[];
54
+ defaultCommand(prefix: string): BuiltinPluginCommand | undefined;
55
+ tools(context: BuiltinToolContext): ToolSpec[];
56
+ worldParts(context: BuiltinWorldContext): WorldPart[];
57
+ serverMethods(harness: Harness): Record<string, Handler>;
58
+ }
59
+ /** One checked registry for the Harness-owned plugin modules and their surface contributions. */
60
+ export declare function createBuiltinPluginRegistry(modules: readonly BuiltinPluginModule[]): BuiltinPluginRegistry;
@@ -0,0 +1,71 @@
1
+ /** One checked registry for the Harness-owned plugin modules and their surface contributions. */
2
+ export function createBuiltinPluginRegistry(modules) {
3
+ const pluginIds = new Set();
4
+ const prefixOwners = new Map();
5
+ const routeKeys = new Set();
6
+ for (const module of modules) {
7
+ const id = module.descriptor.id;
8
+ if (pluginIds.has(id))
9
+ throw new Error(`Duplicate built-in plugin id: ${id}`);
10
+ pluginIds.add(id);
11
+ const prefix = module.commandPrefix ?? id;
12
+ if (!/^[a-z][a-z0-9-]*$/.test(prefix) || prefix === 'plugin' || prefix === 'skill')
13
+ throw new Error(`Invalid built-in plugin command prefix: ${prefix}`);
14
+ if ((module.commands?.length || module.defaultCommand) && prefixOwners.has(prefix)) {
15
+ throw new Error(`Duplicate built-in plugin command prefix: ${prefix}`);
16
+ }
17
+ if (module.commands?.length || module.defaultCommand)
18
+ prefixOwners.set(prefix, id);
19
+ for (const command of module.commands ?? []) {
20
+ if (!/^[a-z][a-z0-9-]*$/.test(command.name))
21
+ throw new Error(`Invalid built-in plugin command: ${command.name}`);
22
+ const key = `${prefix}:${command.name}`;
23
+ if (routeKeys.has(key))
24
+ throw new Error(`Duplicate built-in plugin command: ${key}`);
25
+ routeKeys.add(key);
26
+ }
27
+ if (module.defaultCommand && !module.commands?.some(command => command.name === module.defaultCommand)) {
28
+ throw new Error(`Unknown default command for built-in plugin ${id}: ${module.defaultCommand}`);
29
+ }
30
+ }
31
+ const commands = modules.flatMap(module => (module.commands ?? []).map(command => ({
32
+ pluginId: module.descriptor.id,
33
+ prefix: module.commandPrefix ?? module.descriptor.id,
34
+ ...command,
35
+ legacyBare: !!module.descriptor.required
36
+ })));
37
+ const byRoute = new Map(commands.map(command => [`${command.prefix}:${command.name}`, command]));
38
+ const byName = new Map();
39
+ for (const command of commands)
40
+ byName.set(command.name, [...(byName.get(command.name) ?? []), command]);
41
+ const defaults = new Map(modules.flatMap(module => module.defaultCommand
42
+ ? [[module.commandPrefix ?? module.descriptor.id, byRoute.get(`${module.commandPrefix ?? module.descriptor.id}:${module.defaultCommand}`)]]
43
+ : []));
44
+ const toolModules = modules.map((module, index) => ({ module, index })).filter(({ module }) => module.tools)
45
+ .sort((left, right) => (left.module.toolOrder ?? left.index) - (right.module.toolOrder ?? right.index));
46
+ return {
47
+ modules,
48
+ descriptors: () => modules.map(module => module.descriptor),
49
+ commands: () => [...commands],
50
+ command: (prefix, name) => byRoute.get(`${prefix}:${name}`),
51
+ commandsNamed: name => [...(byName.get(name) ?? [])],
52
+ defaultCommand: prefix => defaults.get(prefix),
53
+ tools: context => toolModules.flatMap(({ module }) => module.tools(context)),
54
+ worldParts: context => modules.flatMap(module => {
55
+ const part = module.createWorldPart?.(context);
56
+ return part ? [part] : [];
57
+ }),
58
+ serverMethods: harness => {
59
+ const methods = {};
60
+ for (const module of modules) {
61
+ const contributed = module.serverMethods?.(harness) ?? {};
62
+ for (const [name, handler] of Object.entries(contributed)) {
63
+ if (name in methods)
64
+ throw new Error(`Duplicate built-in server method: ${name}`);
65
+ methods[name] = handler;
66
+ }
67
+ }
68
+ return methods;
69
+ }
70
+ };
71
+ }
@@ -43,6 +43,7 @@ function fromDescriptor(descriptor, source, attachments = null, caller = {}) {
43
43
  settings: (descriptor.settings ?? []).map((setting) => ({ ...setting, value: settingValue(setting, attachments?.settings[descriptor.id]) })),
44
44
  connectorTemplates: descriptor.connectorTemplates ?? [],
45
45
  attachment: switchable ? describe(attachments, descriptor.id, switchable.on) : null,
46
+ surfaces: descriptor.surfaces ?? null,
46
47
  contributions: [
47
48
  ...(descriptor.code ?? []).map((code) => contribution(descriptor.id, 'code', code.name, { description: code.description, state: on ? 'on' : 'off' })),
48
49
  ...(descriptor.sections ?? []).map((section) => contribution(descriptor.id, 'instruction', section.name, { description: section.description ?? '' })),
@@ -102,7 +103,7 @@ function foundContribution(plugin, item, trusted, input, projects) {
102
103
  const state = !item.enabled || !on ? 'off' : loads(item, trusted) ? 'on' : 'untrusted';
103
104
  const rest = { state, attachment, scope: attachment ? scopeWords(attachment, projects) : null };
104
105
  if (item.path.startsWith(BUILTIN_PREFIX))
105
- return contribution(plugin, kind, name, { ...rest, description: 'Built into the pi command. A terminal session loads it; other sessions do not have it.' });
106
+ return contribution(plugin, kind, name, { ...rest, description: 'Built into the pi command. Xingular sessions do not load it, in the terminal or in a host, so both offer the same tools.' });
106
107
  if (item.kind === 'extension') {
107
108
  const observed = input.registered[item.path];
108
109
  const hash = input.loading ? registrationHash(input.loading, item.path) : null;
@@ -1,5 +1,5 @@
1
1
  import { Harness, type HarnessOptions } from "../harness.js";
2
- export declare const PLUGINS_USAGE = "Usage: xharness plugins <command> [options]\n\n list Every plugin and whether it is on\n show <plugin id> One plugin: what it brings, where it is on, its code\n install <source> A folder, an npm name, or a git address. It arrives off and untrusted\n remove <plugin id> Remove a plugin you installed\n update [plugin id] Fetch a newer version of one installed plugin, or of all\n attach <id> Switch a plugin, or one thing it brings, on\n detach <id> Switch it off\n trust <plugin id> [--yes] Show the files of its code, then trust them\n untrust <plugin id> Stop trusting its code\n\nOptions:\n --data <dir> Data directory (default: ~/.xingular-harness/data)\n --state <dir> State directory (default: ~/.xingular-harness/state)\n --cwd <dir> Also list what this working folder brings\n --project <id> attach/detach for one project instead of everywhere\n --agent <id> attach/detach for one agent instead of everywhere\n";
2
+ export declare const PLUGINS_USAGE = "Usage: xagent plugins <command> [options]\n\n list Every plugin and whether it is on\n show <plugin id> One plugin: what it brings, where it is on, its code\n install <source> A folder, an npm name, or a git address. It arrives off and untrusted\n remove <plugin id> Remove a plugin you installed\n update [plugin id] Fetch a newer version of one installed plugin, or of all\n attach <id> Switch a plugin, or one thing it brings, on\n detach <id> Switch it off\n trust <plugin id> [--yes] Show the files of its code, then trust them\n untrust <plugin id> Stop trusting its code\n\nOptions:\n --data <dir> Data directory (default: ~/.xingular-harness/data)\n --state <dir> State directory (default: ~/.xingular-harness/state)\n --cwd <dir> Also list what this working folder brings\n --project <id> attach/detach for one project instead of everywhere\n --agent <id> attach/detach for one agent instead of everywhere\n";
3
3
  export interface PluginsCliDependencies {
4
4
  home?: string;
5
5
  cwd?: string;
@@ -1,12 +1,13 @@
1
- // `xharness plugins …`: plugin control for a person using the harness without an
1
+ // `xagent plugins …`: plugin control for a person using the harness without an
2
2
  // application. It runs outside any session, as the person who typed it, and acts directly.
3
3
  import { homedir } from 'node:os';
4
4
  import { join, resolve } from 'node:path';
5
5
  import { createInterface } from 'node:readline/promises';
6
+ import { DEFAULT_PRODUCT_NAME } from "../core/env.js";
6
7
  import { Harness } from "../harness.js";
7
8
  import * as api from "./api.js";
8
9
  import * as install from "./install.js";
9
- export const PLUGINS_USAGE = `Usage: xharness plugins <command> [options]
10
+ export const PLUGINS_USAGE = `Usage: xagent plugins <command> [options]
10
11
 
11
12
  list Every plugin and whether it is on
12
13
  show <plugin id> One plugin: what it brings, where it is on, its code
@@ -81,7 +82,7 @@ export async function runPluginsCli(argv, dependencies = {}) {
81
82
  }
82
83
  const base = dependencies.cwd ?? process.cwd();
83
84
  const root = join(dependencies.home ?? homedir(), '.xingular-harness');
84
- const options = { dataRoot: parsed.values.data ? resolve(base, parsed.values.data) : join(root, 'data'), stateDir: parsed.values.state ? resolve(base, parsed.values.state) : join(root, 'state'), productName: 'Xingular Harness' };
85
+ const options = { dataRoot: parsed.values.data ? resolve(base, parsed.values.data) : join(root, 'data'), stateDir: parsed.values.state ? resolve(base, parsed.values.state) : join(root, 'state'), productName: DEFAULT_PRODUCT_NAME };
85
86
  // Built without opening the data root: a plugin command must not settle runs or migrate a Wiki
86
87
  // that another process may be using.
87
88
  const harness = dependencies.createHarness ? dependencies.createHarness(options) : new Harness(options);
@@ -0,0 +1,8 @@
1
+ export interface CommandSourceInfo {
2
+ path: string;
3
+ source?: string;
4
+ origin?: 'package' | 'top-level';
5
+ baseDir?: string;
6
+ }
7
+ /** Stable command namespace for a Pi extension's owning package or loose extension file. */
8
+ export declare function pluginCommandPrefix(source: CommandSourceInfo): string;
@@ -0,0 +1,21 @@
1
+ import { basename, dirname, extname } from 'node:path';
2
+ import { packageManifest } from "./manifest.js";
3
+ const slug = (value) => {
4
+ const normalized = value.toLowerCase().replace(/[^a-z0-9-]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');
5
+ const prefix = /^[a-z]/.test(normalized) ? normalized : `plugin-${normalized || 'command'}`;
6
+ return prefix === 'plugin' || prefix === 'skill' ? `extension-${prefix}` : prefix;
7
+ };
8
+ /** Stable command namespace for a Pi extension's owning package or loose extension file. */
9
+ export function pluginCommandPrefix(source) {
10
+ if (source.origin === 'package' && source.baseDir) {
11
+ const manifest = packageManifest(source.baseDir);
12
+ return manifest.commandPrefix ?? slug(manifest.name);
13
+ }
14
+ if (source.path.startsWith('builtin:'))
15
+ return slug(source.path.slice('builtin:'.length));
16
+ const synthetic = /^<[^:>]+:([^>]+)>$/.exec(source.path);
17
+ if (synthetic)
18
+ return slug(synthetic[1]);
19
+ const file = basename(source.path, extname(source.path));
20
+ return slug(file === 'index' ? basename(dirname(source.path)) : file);
21
+ }
@@ -5,7 +5,7 @@ interface Api {
5
5
  on(event: 'tool_call', handler: (event: {
6
6
  toolName: string;
7
7
  }) => unknown): void;
8
- on(event: 'turn_start', handler: () => unknown): void;
8
+ on(event: 'turn_start' | 'agent_start', handler: () => unknown): void;
9
9
  on(event: 'message_end', handler: (event: {
10
10
  message: {
11
11
  role: string;
@@ -21,7 +21,7 @@ export const FIRST_PARTY_PLUGINS = [
21
21
  description: 'Cuts a very long tool result to its beginning and its end before the model reads it, and says how much was cut.',
22
22
  switchable: { on: false },
23
23
  settings: OUTPUT_TRIM_SETTINGS,
24
- code: [{ name: 'Trim long tool results', description: 'Runs after every tool call, in conversations, task threads and unattended work. Not in terminal sessions yet.' }]
24
+ code: [{ name: 'Trim long tool results', description: 'Runs after every tool call, in conversations, terminal sessions, task threads and unattended work.' }]
25
25
  },
26
26
  {
27
27
  id: BUDGET_GUARD,
@@ -29,7 +29,7 @@ export const FIRST_PARTY_PLUGINS = [
29
29
  description: 'Stops a reply that keeps going: past a limit of model requests or tokens, further tool calls are refused and the agent is told to wrap up.',
30
30
  switchable: { on: false },
31
31
  settings: BUDGET_GUARD_SETTINGS,
32
- code: [{ name: 'Refuse tool calls past the limit', description: 'Counts model requests and tokens in one reply, in conversations, task threads and unattended work. Not in terminal sessions yet.' }]
32
+ code: [{ name: 'Refuse tool calls past the limit', description: 'Counts model requests and tokens in one reply, in conversations, terminal sessions, task threads and unattended work.' }]
33
33
  },
34
34
  {
35
35
  id: LESSONS,
@@ -75,6 +75,12 @@ export function budgetGuard(saved) {
75
75
  let requests = 0;
76
76
  let tokens = 0;
77
77
  let refusedInRequest = 0;
78
+ // A terminal session keeps one Pi session for many replies; each reply starts its own count.
79
+ pi.on('agent_start', () => {
80
+ requests = 0;
81
+ tokens = 0;
82
+ refusedInRequest = 0;
83
+ });
78
84
  pi.on('turn_start', () => {
79
85
  requests += 1;
80
86
  });