@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
@@ -31,6 +31,8 @@ export declare const runEventTypeSchema: z.ZodEnum<{
31
31
  "reaction.added": "reaction.added";
32
32
  "agent.message": "agent.message";
33
33
  "checklist.updated": "checklist.updated";
34
+ checkpoint: "checkpoint";
35
+ heartbeat: "heartbeat";
34
36
  "artifact.added": "artifact.added";
35
37
  "file.changed": "file.changed";
36
38
  "usage.updated": "usage.updated";
@@ -50,10 +52,19 @@ export declare const toolAttachmentRefsSchema: z.ZodArray<z.ZodObject<{
50
52
  mimeType: z.ZodString;
51
53
  }, z.core.$strict>>;
52
54
  export type ToolAttachmentRef = z.infer<typeof toolAttachmentRefSchema>;
55
+ export declare const QUESTION_SKETCH_MAX_LINES = 24;
56
+ export declare const QUESTION_SKETCH_MAX_COLUMNS = 80;
57
+ export declare const QUESTION_SKETCH_MAX_LENGTH: number;
58
+ export declare const QUESTION_SKETCH_PATTERN = "^(?:[\\x20-\\x7e]{0,80})(?:\\n[\\x20-\\x7e]{0,80}){0,23}$";
59
+ export declare const questionSketchSchema: z.ZodString;
60
+ export declare function questionSketchError(uiSketch: unknown, options: readonly {
61
+ sketch?: unknown;
62
+ }[]): string | undefined;
53
63
  export declare const questionOptionSchema: z.ZodObject<{
54
64
  label: z.ZodString;
55
65
  description: z.ZodOptional<z.ZodString>;
56
66
  recommended: z.ZodOptional<z.ZodBoolean>;
67
+ sketch: z.ZodOptional<z.ZodString>;
57
68
  }, z.core.$strip>;
58
69
  export type QuestionOption = z.infer<typeof questionOptionSchema>;
59
70
  /** One line of the run's checklist. The list has no ids: every update replaces all of it. */
@@ -67,6 +78,73 @@ export declare const checklistItemSchema: z.ZodObject<{
67
78
  }, z.core.$strict>;
68
79
  export type ChecklistItem = z.infer<typeof checklistItemSchema>;
69
80
  export declare const MAX_CHECKLIST_ITEMS = 50;
81
+ export declare const MAX_CHECKPOINT_SUMMARY = 1200;
82
+ export declare const MAX_CHECKPOINT_DONE = 20;
83
+ export declare const MAX_CHECKPOINT_EVIDENCE = 5;
84
+ export declare const MAX_CHECKPOINT_FILES = 20;
85
+ export declare const MAX_CHECKPOINT_CHECKS = 8;
86
+ export declare const MAX_CHECKPOINT_DECISIONS = 8;
87
+ /**
88
+ * The handoff a reply writes when it reaches its work-slice budget. The harness validates and
89
+ * records it; the next slice is told where this one stopped from it (PROP-0041).
90
+ */
91
+ export declare const checkpointItemSchema: z.ZodObject<{
92
+ item: z.ZodString;
93
+ evidence: z.ZodDefault<z.ZodArray<z.ZodString>>;
94
+ }, z.core.$strict>;
95
+ export declare const checkpointFileSchema: z.ZodObject<{
96
+ path: z.ZodString;
97
+ why: z.ZodDefault<z.ZodString>;
98
+ }, z.core.$strict>;
99
+ export declare const checkpointCheckSchema: z.ZodObject<{
100
+ command: z.ZodString;
101
+ ok: z.ZodBoolean;
102
+ detail: z.ZodOptional<z.ZodString>;
103
+ }, z.core.$strict>;
104
+ export declare const checkpointDecisionSchema: z.ZodObject<{
105
+ what: z.ZodString;
106
+ why: z.ZodDefault<z.ZodString>;
107
+ }, z.core.$strict>;
108
+ export declare const checkpointReasonSchema: z.ZodEnum<{
109
+ budget: "budget";
110
+ stuck: "stuck";
111
+ "compaction-thrash": "compaction-thrash";
112
+ requested: "requested";
113
+ }>;
114
+ declare const checkpointPayload: z.ZodObject<{
115
+ summary: z.ZodString;
116
+ done: z.ZodDefault<z.ZodArray<z.ZodObject<{
117
+ item: z.ZodString;
118
+ evidence: z.ZodDefault<z.ZodArray<z.ZodString>>;
119
+ }, z.core.$strict>>>;
120
+ next: z.ZodDefault<z.ZodString>;
121
+ blocked: z.ZodOptional<z.ZodString>;
122
+ files: z.ZodDefault<z.ZodArray<z.ZodObject<{
123
+ path: z.ZodString;
124
+ why: z.ZodDefault<z.ZodString>;
125
+ }, z.core.$strict>>>;
126
+ checks: z.ZodDefault<z.ZodArray<z.ZodObject<{
127
+ command: z.ZodString;
128
+ ok: z.ZodBoolean;
129
+ detail: z.ZodOptional<z.ZodString>;
130
+ }, z.core.$strict>>>;
131
+ decisions: z.ZodDefault<z.ZodArray<z.ZodObject<{
132
+ what: z.ZodString;
133
+ why: z.ZodDefault<z.ZodString>;
134
+ }, z.core.$strict>>>;
135
+ slice: z.ZodNumber;
136
+ reason: z.ZodEnum<{
137
+ budget: "budget";
138
+ stuck: "stuck";
139
+ "compaction-thrash": "compaction-thrash";
140
+ requested: "requested";
141
+ }>;
142
+ }, z.core.$strict>;
143
+ export type Checkpoint = z.infer<typeof checkpointPayload>;
144
+ export type CheckpointItem = z.infer<typeof checkpointItemSchema>;
145
+ export type CheckpointFile = z.infer<typeof checkpointFileSchema>;
146
+ export type CheckpointCheck = z.infer<typeof checkpointCheckSchema>;
147
+ export type CheckpointDecision = z.infer<typeof checkpointDecisionSchema>;
70
148
  /** Where a cost figure comes from: Pi reported it, or the tokens were priced at list rates. */
71
149
  export declare const costSourceSchema: z.ZodEnum<{
72
150
  harness: "harness";
@@ -148,9 +226,37 @@ export declare const accountLimitSchema: z.ZodObject<{
148
226
  id: z.ZodString;
149
227
  label: z.ZodString;
150
228
  usedPercent: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
229
+ remainingPercent: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
151
230
  resetsAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
152
231
  windowMinutes: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
153
232
  status: z.ZodOptional<z.ZodNullable<z.ZodString>>;
233
+ provider: z.ZodOptional<z.ZodNullable<z.ZodString>>;
234
+ kind: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
235
+ error: "error";
236
+ window: "window";
237
+ rate: "rate";
238
+ credit: "credit";
239
+ configured: "configured";
240
+ }>>>;
241
+ unit: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
242
+ requests: "requests";
243
+ percent: "percent";
244
+ tokens: "tokens";
245
+ usd: "usd";
246
+ currency: "currency";
247
+ count: "count";
248
+ }>>>;
249
+ used: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
250
+ limit: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
251
+ remaining: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
252
+ source: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
253
+ error: "error";
254
+ headers: "headers";
255
+ estimate: "estimate";
256
+ provider: "provider";
257
+ }>>>;
258
+ observedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
259
+ detail: z.ZodOptional<z.ZodNullable<z.ZodString>>;
154
260
  }, z.core.$strip>;
155
261
  export type AccountLimit = z.infer<typeof accountLimitSchema>;
156
262
  /** Payload schema per discriminant. */
@@ -277,10 +383,12 @@ export declare const runEventPayloadSchemas: {
277
383
  questionId: z.ZodString;
278
384
  question: z.ZodString;
279
385
  summary: z.ZodOptional<z.ZodString>;
386
+ uiSketch: z.ZodOptional<z.ZodLiteral<true>>;
280
387
  options: z.ZodArray<z.ZodObject<{
281
388
  label: z.ZodString;
282
389
  description: z.ZodOptional<z.ZodString>;
283
390
  recommended: z.ZodOptional<z.ZodBoolean>;
391
+ sketch: z.ZodOptional<z.ZodString>;
284
392
  }, z.core.$strip>>;
285
393
  multiSelect: z.ZodBoolean;
286
394
  allowText: z.ZodBoolean;
@@ -334,6 +442,43 @@ export declare const runEventPayloadSchemas: {
334
442
  }>;
335
443
  }, z.core.$strict>>;
336
444
  }, z.core.$strict>;
445
+ checkpoint: z.ZodObject<{
446
+ summary: z.ZodString;
447
+ done: z.ZodDefault<z.ZodArray<z.ZodObject<{
448
+ item: z.ZodString;
449
+ evidence: z.ZodDefault<z.ZodArray<z.ZodString>>;
450
+ }, z.core.$strict>>>;
451
+ next: z.ZodDefault<z.ZodString>;
452
+ blocked: z.ZodOptional<z.ZodString>;
453
+ files: z.ZodDefault<z.ZodArray<z.ZodObject<{
454
+ path: z.ZodString;
455
+ why: z.ZodDefault<z.ZodString>;
456
+ }, z.core.$strict>>>;
457
+ checks: z.ZodDefault<z.ZodArray<z.ZodObject<{
458
+ command: z.ZodString;
459
+ ok: z.ZodBoolean;
460
+ detail: z.ZodOptional<z.ZodString>;
461
+ }, z.core.$strict>>>;
462
+ decisions: z.ZodDefault<z.ZodArray<z.ZodObject<{
463
+ what: z.ZodString;
464
+ why: z.ZodDefault<z.ZodString>;
465
+ }, z.core.$strict>>>;
466
+ slice: z.ZodNumber;
467
+ reason: z.ZodEnum<{
468
+ budget: "budget";
469
+ stuck: "stuck";
470
+ "compaction-thrash": "compaction-thrash";
471
+ requested: "requested";
472
+ }>;
473
+ }, z.core.$strict>;
474
+ heartbeat: z.ZodObject<{
475
+ steps: z.ZodNumber;
476
+ elapsedMs: z.ZodNumber;
477
+ lastTool: z.ZodNullable<z.ZodString>;
478
+ compactions: z.ZodNumber;
479
+ slice: z.ZodNumber;
480
+ maxToolCalls: z.ZodNumber;
481
+ }, z.core.$strict>;
337
482
  'artifact.added': z.ZodObject<{
338
483
  artifactId: z.ZodString;
339
484
  name: z.ZodString;
@@ -401,9 +546,37 @@ export declare const runEventPayloadSchemas: {
401
546
  id: z.ZodString;
402
547
  label: z.ZodString;
403
548
  usedPercent: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
549
+ remainingPercent: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
404
550
  resetsAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
405
551
  windowMinutes: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
406
552
  status: z.ZodOptional<z.ZodNullable<z.ZodString>>;
553
+ provider: z.ZodOptional<z.ZodNullable<z.ZodString>>;
554
+ kind: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
555
+ error: "error";
556
+ window: "window";
557
+ rate: "rate";
558
+ credit: "credit";
559
+ configured: "configured";
560
+ }>>>;
561
+ unit: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
562
+ requests: "requests";
563
+ percent: "percent";
564
+ tokens: "tokens";
565
+ usd: "usd";
566
+ currency: "currency";
567
+ count: "count";
568
+ }>>>;
569
+ used: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
570
+ limit: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
571
+ remaining: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
572
+ source: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
573
+ error: "error";
574
+ headers: "headers";
575
+ estimate: "estimate";
576
+ provider: "provider";
577
+ }>>>;
578
+ observedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
579
+ detail: z.ZodOptional<z.ZodNullable<z.ZodString>>;
407
580
  }, z.core.$strip>>>;
408
581
  }, z.core.$strip>;
409
582
  'status.changed': z.ZodObject<{
@@ -452,6 +625,8 @@ export declare const runEventSchema: z.ZodObject<{
452
625
  "reaction.added": "reaction.added";
453
626
  "agent.message": "agent.message";
454
627
  "checklist.updated": "checklist.updated";
628
+ checkpoint: "checkpoint";
629
+ heartbeat: "heartbeat";
455
630
  "artifact.added": "artifact.added";
456
631
  "file.changed": "file.changed";
457
632
  "usage.updated": "usage.updated";
@@ -483,6 +658,8 @@ export interface RunRecord {
483
658
  sessionId: string;
484
659
  nativeSessionId: string | null;
485
660
  workingDirectory: string | null;
661
+ /** Canonical filesystem root whose writes this run may make by default. */
662
+ workspaceRoot?: string | null;
486
663
  worktreeId: string | null;
487
664
  goal: string | null;
488
665
  attachmentCount: number;
@@ -500,6 +677,10 @@ export interface RunRecord {
500
677
  /** The variant the run used: its scope and version fingerprint. */
501
678
  variantScope?: string | null;
502
679
  variantVersion?: string | null;
680
+ /** The agent profile a subagent started from (PROP-0029); null for a copy of its parent. */
681
+ profile?: string | null;
682
+ /** The short name a parent gave a subagent, shown in the roster (PROP-0030). */
683
+ title?: string | null;
503
684
  }
504
685
  export declare const runRecordSchema: z.ZodObject<{
505
686
  resumedFromRunId: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>;
@@ -514,6 +695,7 @@ export declare const runRecordSchema: z.ZodObject<{
514
695
  sessionId: z.ZodString;
515
696
  nativeSessionId: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>;
516
697
  workingDirectory: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>;
698
+ workspaceRoot: z.ZodOptional<z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>>;
517
699
  worktreeId: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>;
518
700
  goal: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>;
519
701
  attachmentCount: z.ZodDefault<z.ZodNumber>;
@@ -527,8 +709,11 @@ export declare const runRecordSchema: z.ZodObject<{
527
709
  trigger: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>;
528
710
  variantScope: z.ZodOptional<z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>>;
529
711
  variantVersion: z.ZodOptional<z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>>;
712
+ profile: z.ZodOptional<z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>>;
713
+ title: z.ZodOptional<z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>>;
530
714
  }, z.core.$strip>;
531
715
  /** Records written before PROP-0009 name the variant `harnessScope` and `harnessVersion`. */
532
716
  export declare function upgradeRunRecord(raw: unknown): unknown;
533
717
  export declare const ACTIVE_STATUSES: readonly string[];
534
718
  export declare function isActiveStatus(status: string): boolean;
719
+ export {};
@@ -22,6 +22,8 @@ export const runEventTypeSchema = z.enum([
22
22
  'reaction.added',
23
23
  'agent.message',
24
24
  'checklist.updated',
25
+ 'checkpoint',
26
+ 'heartbeat',
25
27
  'artifact.added',
26
28
  'file.changed',
27
29
  'usage.updated',
@@ -91,7 +93,39 @@ const approvalRequestedPayload = z.object({
91
93
  automatic: approvalAutomaticSchema.optional()
92
94
  });
93
95
  const approvalResolvedPayload = z.object({ approvalId: z.string(), decision: z.enum(['approved', 'denied', 'native']), automatic: approvalAutomaticSchema.optional() });
94
- export const questionOptionSchema = z.object({ label: z.string().min(1), description: z.string().optional(), recommended: z.boolean().optional() });
96
+ export const QUESTION_SKETCH_MAX_LINES = 24;
97
+ export const QUESTION_SKETCH_MAX_COLUMNS = 80;
98
+ export const QUESTION_SKETCH_MAX_LENGTH = QUESTION_SKETCH_MAX_LINES * QUESTION_SKETCH_MAX_COLUMNS + QUESTION_SKETCH_MAX_LINES - 1;
99
+ export const QUESTION_SKETCH_PATTERN = `^(?:[\\x20-\\x7e]{0,${QUESTION_SKETCH_MAX_COLUMNS}})(?:\\n[\\x20-\\x7e]{0,${QUESTION_SKETCH_MAX_COLUMNS}}){0,${QUESTION_SKETCH_MAX_LINES - 1}}$`;
100
+ export const questionSketchSchema = z.string()
101
+ .min(1)
102
+ .max(QUESTION_SKETCH_MAX_LENGTH)
103
+ .regex(new RegExp(QUESTION_SKETCH_PATTERN), 'Sketches use up to 24 LF-separated lines of at most 80 printable ASCII characters.')
104
+ .refine((sketch) => {
105
+ const lines = sketch.split('\n');
106
+ return lines.length <= QUESTION_SKETCH_MAX_LINES &&
107
+ lines.every((line) => line.length <= QUESTION_SKETCH_MAX_COLUMNS && /^[\x20-\x7e]*$/u.test(line)) &&
108
+ /[^ \n]/u.test(sketch);
109
+ }, 'A sketch needs visible content and must use up to 24 LF-separated lines of at most 80 printable ASCII characters.');
110
+ export function questionSketchError(uiSketch, options) {
111
+ if (uiSketch !== undefined && uiSketch !== true)
112
+ return 'Set uiSketch to true to enable question sketches.';
113
+ const sketches = options.map((option) => option.sketch);
114
+ if (uiSketch === true && sketches.some((sketch) => sketch === undefined))
115
+ return 'Sketch mode requires a sketch for every choice.';
116
+ if (uiSketch !== true && sketches.some((sketch) => sketch !== undefined))
117
+ return 'Choice sketches require uiSketch: true.';
118
+ if (sketches.some((sketch) => sketch !== undefined && !questionSketchSchema.safeParse(sketch).success)) {
119
+ return 'Each choice sketch must use 1–24 lines of at most 80 printable ASCII characters and contain a visible character.';
120
+ }
121
+ return undefined;
122
+ }
123
+ export const questionOptionSchema = z.object({
124
+ label: z.string().min(1),
125
+ description: z.string().optional(),
126
+ recommended: z.boolean().optional(),
127
+ sketch: questionSketchSchema.optional()
128
+ });
95
129
  const questionBatchFields = {
96
130
  batchId: z.string().min(1).optional(),
97
131
  batchIndex: z.number().int().min(1).max(5).optional(),
@@ -110,12 +144,17 @@ const questionRequestedPayload = z.object({
110
144
  questionId: z.string(),
111
145
  question: z.string().min(1),
112
146
  summary: z.string().min(1).max(100).optional(),
147
+ uiSketch: z.literal(true).optional(),
113
148
  options: z.array(questionOptionSchema),
114
149
  multiSelect: z.boolean(),
115
150
  allowText: z.boolean(),
116
151
  userOnly: z.boolean().optional(),
117
152
  ...questionBatchFields
118
- }).superRefine(questionBatchRefinement);
153
+ }).superRefine(questionBatchRefinement).superRefine((value, context) => {
154
+ const error = questionSketchError(value.uiSketch, value.options);
155
+ if (error)
156
+ context.addIssue({ code: z.ZodIssueCode.custom, path: ['options'], message: error });
157
+ });
119
158
  const questionAnsweredPayload = z.object({
120
159
  questionId: z.string(),
121
160
  selected: z.array(z.string()),
@@ -140,6 +179,49 @@ export const checklistItemSchema = z.object({ text: z.string().min(1).max(500),
140
179
  export const MAX_CHECKLIST_ITEMS = 50;
141
180
  /** The whole checklist as the model last wrote it; the latest event replaces every earlier one. */
142
181
  const checklistPayload = z.object({ items: z.array(checklistItemSchema).max(MAX_CHECKLIST_ITEMS) }).strict();
182
+ export const MAX_CHECKPOINT_SUMMARY = 1_200;
183
+ export const MAX_CHECKPOINT_DONE = 20;
184
+ export const MAX_CHECKPOINT_EVIDENCE = 5;
185
+ export const MAX_CHECKPOINT_FILES = 20;
186
+ export const MAX_CHECKPOINT_CHECKS = 8;
187
+ export const MAX_CHECKPOINT_DECISIONS = 8;
188
+ /**
189
+ * The handoff a reply writes when it reaches its work-slice budget. The harness validates and
190
+ * records it; the next slice is told where this one stopped from it (PROP-0041).
191
+ */
192
+ export const checkpointItemSchema = z.object({
193
+ item: z.string().min(1).max(300),
194
+ evidence: z.array(z.string().min(1).max(300)).max(MAX_CHECKPOINT_EVIDENCE).default([])
195
+ }).strict();
196
+ export const checkpointFileSchema = z.object({ path: z.string().min(1).max(300), why: z.string().max(200).default('') }).strict();
197
+ export const checkpointCheckSchema = z.object({
198
+ command: z.string().min(1).max(200),
199
+ ok: z.boolean(),
200
+ detail: z.string().max(300).optional()
201
+ }).strict();
202
+ export const checkpointDecisionSchema = z.object({ what: z.string().min(1).max(200), why: z.string().max(300).default('') }).strict();
203
+ export const checkpointReasonSchema = z.enum(['budget', 'stuck', 'compaction-thrash', 'requested']);
204
+ const checkpointPayload = z.object({
205
+ summary: z.string().max(MAX_CHECKPOINT_SUMMARY),
206
+ done: z.array(checkpointItemSchema).max(MAX_CHECKPOINT_DONE).default([]),
207
+ next: z.string().max(500).default(''),
208
+ blocked: z.string().max(500).optional(),
209
+ files: z.array(checkpointFileSchema).max(MAX_CHECKPOINT_FILES).default([]),
210
+ checks: z.array(checkpointCheckSchema).max(MAX_CHECKPOINT_CHECKS).default([]),
211
+ decisions: z.array(checkpointDecisionSchema).max(MAX_CHECKPOINT_DECISIONS).default([]),
212
+ /** Which slice of the session wrote it, from 1. */
213
+ slice: z.number().int().positive(),
214
+ reason: checkpointReasonSchema
215
+ }).strict();
216
+ /** Counters a live reply reports while it works; a person and the watchdog read liveness from it. */
217
+ const heartbeatPayload = z.object({
218
+ steps: z.number().int().nonnegative(),
219
+ elapsedMs: z.number().nonnegative(),
220
+ lastTool: z.string().max(120).nullable(),
221
+ compactions: z.number().int().nonnegative(),
222
+ slice: z.number().int().positive(),
223
+ maxToolCalls: z.number().int().nonnegative()
224
+ }).strict();
143
225
  const artifactPayload = z.object({ artifactId: z.string(), name: z.string(), file: z.unknown().optional() });
144
226
  const fileChangedPayload = z.object({ path: z.string(), change: z.enum(['added', 'modified', 'deleted']) });
145
227
  /** Where a cost figure comes from: Pi reported it, or the tokens were priced at list rates. */
@@ -191,9 +273,19 @@ export const accountLimitSchema = z.object({
191
273
  id: z.string(),
192
274
  label: z.string(),
193
275
  usedPercent: z.number().nullable().optional(),
276
+ remainingPercent: z.number().nullable().optional(),
194
277
  resetsAt: z.string().nullable().optional(),
195
278
  windowMinutes: z.number().nullable().optional(),
196
- status: z.string().nullable().optional()
279
+ status: z.string().nullable().optional(),
280
+ provider: z.string().nullable().optional(),
281
+ kind: z.enum(['window', 'rate', 'credit', 'configured', 'error']).nullable().optional(),
282
+ unit: z.enum(['percent', 'requests', 'tokens', 'usd', 'currency', 'count']).nullable().optional(),
283
+ used: z.number().nullable().optional(),
284
+ limit: z.number().nullable().optional(),
285
+ remaining: z.number().nullable().optional(),
286
+ source: z.enum(['headers', 'provider', 'estimate', 'error']).nullable().optional(),
287
+ observedAt: z.string().nullable().optional(),
288
+ detail: z.string().nullable().optional()
197
289
  });
198
290
  /** Limit snapshots, plan changes, and classified account failures. */
199
291
  const accountStatusPayload = z.object({
@@ -228,6 +320,8 @@ export const runEventPayloadSchemas = {
228
320
  'reaction.added': reactionAddedPayload,
229
321
  'agent.message': agentMessagePayload,
230
322
  'checklist.updated': checklistPayload,
323
+ checkpoint: checkpointPayload,
324
+ heartbeat: heartbeatPayload,
231
325
  'artifact.added': artifactPayload,
232
326
  'file.changed': fileChangedPayload,
233
327
  'usage.updated': usagePayloadSchema,
@@ -269,6 +363,7 @@ export const runRecordSchema = z.object({
269
363
  sessionId: z.string(),
270
364
  nativeSessionId: text,
271
365
  workingDirectory: text,
366
+ workspaceRoot: text.optional(),
272
367
  worktreeId: text,
273
368
  goal: text,
274
369
  attachmentCount: z.number().int().nonnegative().default(0),
@@ -281,7 +376,9 @@ export const runRecordSchema = z.object({
281
376
  agentId: text,
282
377
  trigger: text,
283
378
  variantScope: text.optional(),
284
- variantVersion: text.optional()
379
+ variantVersion: text.optional(),
380
+ profile: text.optional(),
381
+ title: text.optional()
285
382
  });
286
383
  /** Records written before PROP-0009 name the variant `harnessScope` and `harnessVersion`. */
287
384
  export function upgradeRunRecord(raw) {
@@ -0,0 +1,72 @@
1
+ /** Which saved history a command acts on: one file in the folder, or the newest there. */
2
+ export interface SessionRef {
3
+ sessionDir: string;
4
+ sessionFile?: string | null;
5
+ /** Recorded in a new history's header. Defaults to the source history's own folder. */
6
+ cwd?: string | null;
7
+ }
8
+ export interface SessionTreeEntry {
9
+ id: string;
10
+ parentId: string | null;
11
+ type: string;
12
+ /** `user`, `assistant`, `toolResult`, ... for a message entry. */
13
+ role?: string;
14
+ /** One line of what the entry says, at most 160 characters. */
15
+ text: string;
16
+ label?: string;
17
+ timestamp: string;
18
+ /** How deep in the tree, for indentation. */
19
+ depth: number;
20
+ }
21
+ export interface SessionTree {
22
+ sessionFile: string;
23
+ leafId: string | null;
24
+ entries: SessionTreeEntry[];
25
+ /** The person's messages on the current branch, newest last: where `/fork` may start. */
26
+ forkPoints: {
27
+ entryId: string;
28
+ text: string;
29
+ }[];
30
+ }
31
+ /** A move without a summary is saved as this entry, so the next turn opens on the chosen branch. */
32
+ export declare const NAVIGATION_ENTRY = "xingular-navigation";
33
+ export declare function tree(ref: SessionRef): SessionTree;
34
+ /**
35
+ * Moves the conversation to another entry without a summary. Choosing one of the person's
36
+ * messages goes to just before it and gives its text back to edit, as the terminal does.
37
+ */
38
+ export declare function navigate(ref: SessionRef & {
39
+ entryId: string;
40
+ }): {
41
+ leafId: string | null;
42
+ editorText?: string;
43
+ };
44
+ /** A new history in `targetDir` that ends just before one of the person's messages. */
45
+ export declare function fork(ref: SessionRef & {
46
+ entryId: string;
47
+ targetDir: string;
48
+ }): {
49
+ sessionFile: string;
50
+ editorText: string;
51
+ };
52
+ /** A new history in `targetDir` with the whole current branch. */
53
+ export declare function clone(ref: SessionRef & {
54
+ targetDir: string;
55
+ }): {
56
+ sessionFile: string;
57
+ };
58
+ export declare function rename(ref: SessionRef & {
59
+ name: string;
60
+ }): {
61
+ name: string;
62
+ };
63
+ /** The text of the last reply on the current branch, or null before the first. */
64
+ export declare function lastReply(ref: SessionRef): {
65
+ text: string | null;
66
+ };
67
+ /** Writes the current branch as JSONL. HTML needs a live session: see `SessionCommand`. */
68
+ export declare function exportJsonl(ref: SessionRef & {
69
+ path: string;
70
+ }): {
71
+ path: string;
72
+ };
@@ -0,0 +1,158 @@
1
+ // Session commands that need no model: read the branch tree, move to another branch, fork, clone,
2
+ // name, copy the last reply, and export to JSONL. They act on the saved native history directly,
3
+ // so a host that opens one Pi session per turn offers the same commands as the terminal.
4
+ // Compacting, navigating with a summary and exporting to HTML need a live session: they run as a
5
+ // session command through `sessions.run` (see `SessionCommand`).
6
+ import { existsSync, mkdirSync, realpathSync, writeFileSync } from 'node:fs';
7
+ import { isAbsolute, relative } from 'node:path';
8
+ import { SessionManager } from '@earendil-works/pi-coding-agent';
9
+ import { invalid, notFound } from "../core/errors.js";
10
+ import { sessionFile as newestSessionFile } from "../prompt/compile.js";
11
+ /** A move without a summary is saved as this entry, so the next turn opens on the chosen branch. */
12
+ export const NAVIGATION_ENTRY = 'xingular-navigation';
13
+ function within(dir, file) {
14
+ const path = relative(realpathSync(dir), realpathSync(file));
15
+ return !path.startsWith('..') && !isAbsolute(path);
16
+ }
17
+ function resolveFile(ref) {
18
+ if (!ref.sessionDir || !existsSync(ref.sessionDir))
19
+ throw notFound('This conversation has no saved history yet.');
20
+ const file = ref.sessionFile ?? newestSessionFile(ref.sessionDir);
21
+ if (!file || !existsSync(file))
22
+ throw notFound('This conversation has no saved history yet.');
23
+ if (!file.endsWith('.jsonl') || !within(ref.sessionDir, file))
24
+ throw invalid('The history must be a .jsonl file in the session folder.');
25
+ return realpathSync(file);
26
+ }
27
+ function open(ref, targetDir) {
28
+ const file = resolveFile(ref);
29
+ return { manager: SessionManager.open(file, targetDir ?? ref.sessionDir, ref.cwd ?? undefined), file };
30
+ }
31
+ function contentText(content) {
32
+ if (typeof content === 'string')
33
+ return content;
34
+ if (!Array.isArray(content))
35
+ return '';
36
+ return content.map((part) => part && typeof part === 'object' && part.type === 'text' ? String(part.text ?? '') : '').join(' ');
37
+ }
38
+ function entryText(entry) {
39
+ const record = entry;
40
+ if (entry.type === 'message') {
41
+ const message = record.message;
42
+ return { role: message?.role, text: contentText(message?.content) };
43
+ }
44
+ if (entry.type === 'branch_summary' || entry.type === 'compaction')
45
+ return { text: String(record.summary ?? '') };
46
+ if (entry.type === 'session_info')
47
+ return { text: String(record.name ?? '') };
48
+ if (entry.type === 'model_change')
49
+ return { text: `${record.provider ?? ''}/${record.modelId ?? ''}` };
50
+ return { text: '' };
51
+ }
52
+ const oneLine = (text) => text.replace(/\s+/g, ' ').trim().slice(0, 160);
53
+ function flatten(nodes, depth, out) {
54
+ for (const node of nodes) {
55
+ const entry = node.entry;
56
+ const { role, text } = entryText(entry);
57
+ if (entry.type === 'custom' || entry.type === 'label') {
58
+ flatten(node.children, depth, out);
59
+ continue;
60
+ }
61
+ out.push({
62
+ id: entry.id,
63
+ parentId: entry.parentId ?? null,
64
+ type: entry.type,
65
+ ...(role ? { role } : {}),
66
+ text: oneLine(text),
67
+ ...(node.label ? { label: node.label } : {}),
68
+ timestamp: entry.timestamp,
69
+ depth
70
+ });
71
+ flatten(node.children, node.children.length > 1 ? depth + 1 : depth, out);
72
+ }
73
+ }
74
+ export function tree(ref) {
75
+ const { manager, file } = open(ref);
76
+ const entries = [];
77
+ flatten(manager.getTree(), 0, entries);
78
+ const forkPoints = manager.getBranch()
79
+ .filter((entry) => entry.type === 'message' && entryText(entry).role === 'user')
80
+ .map((entry) => ({ entryId: entry.id, text: oneLine(entryText(entry).text) }));
81
+ return { sessionFile: file, leafId: manager.getLeafId(), entries, forkPoints };
82
+ }
83
+ /**
84
+ * Moves the conversation to another entry without a summary. Choosing one of the person's
85
+ * messages goes to just before it and gives its text back to edit, as the terminal does.
86
+ */
87
+ export function navigate(ref) {
88
+ const { manager } = open(ref);
89
+ const entry = manager.getEntry(ref.entryId);
90
+ if (!entry)
91
+ throw notFound(`No entry ${ref.entryId} in this conversation.`);
92
+ const { role, text } = entryText(entry);
93
+ const userMessage = entry.type === 'message' && role === 'user';
94
+ const target = userMessage ? entry.parentId ?? null : entry.id;
95
+ if (target)
96
+ manager.branch(target);
97
+ else
98
+ manager.resetLeaf();
99
+ manager.appendCustomEntry(NAVIGATION_ENTRY, { to: target });
100
+ return { leafId: target, ...(userMessage ? { editorText: text } : {}) };
101
+ }
102
+ /** A new history in `targetDir` that ends just before one of the person's messages. */
103
+ export function fork(ref) {
104
+ const { manager } = open(ref, ensureDir(ref.targetDir));
105
+ const entry = manager.getEntry(ref.entryId);
106
+ const { role, text } = entry ? entryText(entry) : { text: '' };
107
+ if (!entry || entry.type !== 'message' || role !== 'user')
108
+ throw invalid('Fork from one of your messages.');
109
+ const sessionFile = entry.parentId
110
+ ? manager.createBranchedSession(entry.parentId)
111
+ : SessionManager.create(manager.getCwd(), ref.targetDir).getSessionFile();
112
+ if (!sessionFile)
113
+ throw invalid('The fork could not be saved.');
114
+ return { sessionFile, editorText: text };
115
+ }
116
+ /** A new history in `targetDir` with the whole current branch. */
117
+ export function clone(ref) {
118
+ const { manager } = open(ref, ensureDir(ref.targetDir));
119
+ const leaf = manager.getLeafId();
120
+ if (!leaf)
121
+ throw invalid('Nothing to clone yet.');
122
+ const sessionFile = manager.createBranchedSession(leaf);
123
+ if (!sessionFile)
124
+ throw invalid('The clone could not be saved.');
125
+ return { sessionFile };
126
+ }
127
+ export function rename(ref) {
128
+ const name = ref.name.trim();
129
+ if (!name)
130
+ throw invalid('A session name cannot be empty.');
131
+ open(ref).manager.appendSessionInfo(name);
132
+ return { name };
133
+ }
134
+ /** The text of the last reply on the current branch, or null before the first. */
135
+ export function lastReply(ref) {
136
+ const branch = open(ref).manager.getBranch();
137
+ for (let index = branch.length - 1; index >= 0; index -= 1) {
138
+ const { role, text } = entryText(branch[index]);
139
+ if (branch[index].type === 'message' && role === 'assistant' && text.trim())
140
+ return { text: text.trim() };
141
+ }
142
+ return { text: null };
143
+ }
144
+ /** Writes the current branch as JSONL. HTML needs a live session: see `SessionCommand`. */
145
+ export function exportJsonl(ref) {
146
+ if (!isAbsolute(ref.path) || !ref.path.endsWith('.jsonl'))
147
+ throw invalid('Export to an absolute .jsonl path.');
148
+ const { manager } = open(ref);
149
+ const lines = [manager.getHeader(), ...manager.getBranch()].filter(Boolean).map((entry) => JSON.stringify(entry));
150
+ writeFileSync(ref.path, `${lines.join('\n')}\n`, 'utf8');
151
+ return { path: ref.path };
152
+ }
153
+ function ensureDir(dir) {
154
+ if (!isAbsolute(dir))
155
+ throw invalid('The new history folder must be an absolute path.');
156
+ mkdirSync(dir, { recursive: true });
157
+ return dir;
158
+ }