@xingular/harness 0.1.7 → 1.0.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 (683) hide show
  1. package/CHANGELOG.md +97 -1
  2. package/LICENSE +202 -0
  3. package/NOTICE.md +22 -0
  4. package/README.md +187 -85
  5. package/THIRD_PARTY_LICENSES.md +942 -0
  6. package/dist/cli.js +13701 -13498
  7. package/dist/sdk/accounts/accounts.d.ts +165 -0
  8. package/dist/sdk/accounts/accounts.js +730 -0
  9. package/dist/sdk/accounts/choices.d.ts +23 -0
  10. package/dist/sdk/accounts/choices.js +62 -0
  11. package/dist/sdk/accounts/env.d.ts +78 -0
  12. package/dist/sdk/accounts/env.js +294 -0
  13. package/dist/sdk/accounts/secrets.d.ts +16 -0
  14. package/dist/sdk/accounts/secrets.js +40 -0
  15. package/dist/sdk/accounts/store.d.ts +114 -0
  16. package/dist/sdk/accounts/store.js +255 -0
  17. package/dist/sdk/browser/config.d.ts +16 -0
  18. package/dist/sdk/browser/config.js +22 -0
  19. package/dist/sdk/browser/diagnostics.d.ts +4 -0
  20. package/dist/sdk/browser/diagnostics.js +38 -0
  21. package/dist/sdk/browser/index.d.ts +17 -0
  22. package/dist/sdk/browser/index.js +65 -0
  23. package/dist/sdk/browser/network.d.ts +10 -0
  24. package/dist/sdk/browser/network.js +59 -0
  25. package/dist/sdk/browser/session.d.ts +84 -0
  26. package/dist/sdk/browser/session.js +192 -0
  27. package/dist/sdk/browser/tools.d.ts +8 -0
  28. package/dist/sdk/browser/tools.js +329 -0
  29. package/dist/sdk/capabilities/api.d.ts +22 -0
  30. package/dist/sdk/capabilities/api.js +54 -0
  31. package/dist/sdk/capabilities/runSnapshot.d.ts +18 -0
  32. package/dist/sdk/capabilities/runSnapshot.js +47 -0
  33. package/dist/sdk/capabilities/types.d.ts +29 -0
  34. package/dist/sdk/capabilities/types.js +1 -0
  35. package/dist/sdk/cli.d.ts +2 -0
  36. package/dist/sdk/cli.js +142 -0
  37. package/dist/sdk/core/bus.d.ts +23 -0
  38. package/dist/sdk/core/bus.js +76 -0
  39. package/dist/sdk/core/caller.d.ts +22 -0
  40. package/dist/sdk/core/caller.js +16 -0
  41. package/dist/sdk/core/changes.d.ts +15 -0
  42. package/dist/sdk/core/changes.js +15 -0
  43. package/dist/sdk/core/effort.d.ts +2 -0
  44. package/dist/sdk/core/effort.js +1 -0
  45. package/dist/sdk/core/env.d.ts +18 -0
  46. package/dist/sdk/core/env.js +8 -0
  47. package/dist/sdk/core/errors.d.ts +15 -0
  48. package/dist/sdk/core/errors.js +24 -0
  49. package/dist/sdk/core/frontmatter.d.ts +12 -0
  50. package/dist/sdk/core/frontmatter.js +50 -0
  51. package/dist/sdk/core/fs.d.ts +18 -0
  52. package/dist/sdk/core/fs.js +106 -0
  53. package/dist/sdk/core/index.d.ts +24 -0
  54. package/dist/sdk/core/index.js +187 -0
  55. package/dist/sdk/core/path.d.ts +7 -0
  56. package/dist/sdk/core/path.js +79 -0
  57. package/dist/sdk/core/projects.d.ts +18 -0
  58. package/dist/sdk/core/projects.js +67 -0
  59. package/dist/sdk/core/secrets.d.ts +2 -0
  60. package/dist/sdk/core/secrets.js +5 -0
  61. package/dist/sdk/core/text.d.ts +7 -0
  62. package/dist/sdk/core/text.js +40 -0
  63. package/dist/sdk/doctor/checks.d.ts +5 -0
  64. package/dist/sdk/doctor/checks.js +208 -0
  65. package/dist/sdk/doctor/probe.d.ts +4 -0
  66. package/dist/sdk/doctor/probe.js +92 -0
  67. package/dist/sdk/doctor/service.d.ts +23 -0
  68. package/dist/sdk/doctor/service.js +144 -0
  69. package/dist/sdk/doctor/types.d.ts +141 -0
  70. package/dist/sdk/doctor/types.js +29 -0
  71. package/dist/sdk/harness.d.ts +133 -0
  72. package/dist/sdk/harness.js +299 -0
  73. package/dist/sdk/history/lessonPrompt.d.ts +2 -0
  74. package/dist/sdk/history/lessonPrompt.js +15 -0
  75. package/dist/sdk/history/lessons.d.ts +52 -0
  76. package/dist/sdk/history/lessons.js +173 -0
  77. package/dist/sdk/history/recall.d.ts +68 -0
  78. package/dist/sdk/history/recall.js +199 -0
  79. package/dist/sdk/history/trajectory.d.ts +7 -0
  80. package/dist/sdk/history/trajectory.js +216 -0
  81. package/dist/sdk/hub/catalog.json +123 -0
  82. package/dist/sdk/hub/cli.d.ts +7 -0
  83. package/dist/sdk/hub/cli.js +81 -0
  84. package/dist/sdk/hub/hub.d.ts +74 -0
  85. package/dist/sdk/hub/hub.js +474 -0
  86. package/dist/sdk/hub/schema.d.ts +280 -0
  87. package/dist/sdk/hub/schema.js +78 -0
  88. package/dist/sdk/index.d.ts +63 -0
  89. package/dist/sdk/index.js +48 -0
  90. package/dist/sdk/mcp/connections.d.ts +83 -0
  91. package/dist/sdk/mcp/connections.js +669 -0
  92. package/dist/sdk/mcp/manager.d.ts +26 -0
  93. package/dist/sdk/mcp/manager.js +124 -0
  94. package/dist/sdk/mcp/oauth.d.ts +35 -0
  95. package/dist/sdk/mcp/oauth.js +171 -0
  96. package/dist/sdk/mcp/scopeMigration.d.ts +19 -0
  97. package/dist/sdk/mcp/scopeMigration.js +198 -0
  98. package/dist/sdk/mcp/service.d.ts +160 -0
  99. package/dist/sdk/mcp/service.js +510 -0
  100. package/dist/sdk/mcp/types.d.ts +131 -0
  101. package/dist/sdk/mcp/types.js +49 -0
  102. package/dist/sdk/pi/runtime.d.ts +13 -0
  103. package/dist/sdk/pi/runtime.js +31 -0
  104. package/dist/sdk/plugins/api.d.ts +66 -0
  105. package/dist/sdk/plugins/api.js +155 -0
  106. package/dist/sdk/plugins/attachments.d.ts +46 -0
  107. package/dist/sdk/plugins/attachments.js +111 -0
  108. package/dist/sdk/plugins/builtin.d.ts +6 -0
  109. package/dist/sdk/plugins/builtin.js +68 -0
  110. package/dist/sdk/plugins/catalogue.d.ts +29 -0
  111. package/dist/sdk/plugins/catalogue.js +196 -0
  112. package/dist/sdk/plugins/cli.d.ts +13 -0
  113. package/dist/sdk/plugins/cli.js +187 -0
  114. package/dist/sdk/plugins/discover.d.ts +42 -0
  115. package/dist/sdk/plugins/discover.js +115 -0
  116. package/dist/sdk/plugins/firstParty.d.ts +50 -0
  117. package/dist/sdk/plugins/firstParty.js +113 -0
  118. package/dist/sdk/plugins/hooks.d.ts +94 -0
  119. package/dist/sdk/plugins/hooks.js +162 -0
  120. package/dist/sdk/plugins/identity.d.ts +19 -0
  121. package/dist/sdk/plugins/identity.js +48 -0
  122. package/dist/sdk/plugins/install.d.ts +20 -0
  123. package/dist/sdk/plugins/install.js +110 -0
  124. package/dist/sdk/plugins/inventory.d.ts +22 -0
  125. package/dist/sdk/plugins/inventory.js +110 -0
  126. package/dist/sdk/plugins/manifest.d.ts +13 -0
  127. package/dist/sdk/plugins/manifest.js +56 -0
  128. package/dist/sdk/plugins/plugins.d.ts +104 -0
  129. package/dist/sdk/plugins/plugins.js +164 -0
  130. package/dist/sdk/plugins/runtime.d.ts +9 -0
  131. package/dist/sdk/plugins/runtime.js +95 -0
  132. package/dist/sdk/plugins/trust.d.ts +44 -0
  133. package/dist/sdk/plugins/trust.js +120 -0
  134. package/dist/sdk/plugins/types.d.ts +159 -0
  135. package/dist/sdk/plugins/types.js +7 -0
  136. package/dist/sdk/prompt/compile.d.ts +174 -0
  137. package/dist/sdk/prompt/compile.js +396 -0
  138. package/dist/sdk/refine/cli.d.ts +4 -0
  139. package/dist/sdk/refine/cli.js +186 -0
  140. package/dist/sdk/refine/demo.d.ts +21 -0
  141. package/dist/sdk/refine/demo.js +114 -0
  142. package/dist/sdk/refine/evidence.d.ts +55 -0
  143. package/dist/sdk/refine/evidence.js +330 -0
  144. package/dist/sdk/refine/host.d.ts +51 -0
  145. package/dist/sdk/refine/host.js +76 -0
  146. package/dist/sdk/refine/ledger.d.ts +48 -0
  147. package/dist/sdk/refine/ledger.js +76 -0
  148. package/dist/sdk/refine/library.d.ts +55 -0
  149. package/dist/sdk/refine/library.js +177 -0
  150. package/dist/sdk/refine/pi.d.ts +72 -0
  151. package/dist/sdk/refine/pi.js +248 -0
  152. package/dist/sdk/refine/prompts.d.ts +45 -0
  153. package/dist/sdk/refine/prompts.js +390 -0
  154. package/dist/sdk/refine/recursion.d.ts +113 -0
  155. package/dist/sdk/refine/recursion.js +258 -0
  156. package/dist/sdk/refine/runner.d.ts +81 -0
  157. package/dist/sdk/refine/runner.js +150 -0
  158. package/dist/sdk/refine/selection.d.ts +57 -0
  159. package/dist/sdk/refine/selection.js +251 -0
  160. package/dist/sdk/refine/service.d.ts +84 -0
  161. package/dist/sdk/refine/service.js +165 -0
  162. package/dist/sdk/refine/suite.d.ts +67 -0
  163. package/dist/sdk/refine/suite.js +174 -0
  164. package/dist/sdk/refine/trajectory.d.ts +9 -0
  165. package/dist/sdk/refine/trajectory.js +68 -0
  166. package/dist/sdk/refine/types.d.ts +77 -0
  167. package/dist/sdk/refine/types.js +10 -0
  168. package/dist/sdk/server/methods.d.ts +3 -0
  169. package/dist/sdk/server/methods.js +370 -0
  170. package/dist/sdk/server/remote.d.ts +19 -0
  171. package/dist/sdk/server/remote.js +84 -0
  172. package/dist/sdk/server/rpc.d.ts +20 -0
  173. package/dist/sdk/server/rpc.js +102 -0
  174. package/dist/sdk/server/serve.d.ts +10 -0
  175. package/dist/sdk/server/serve.js +18 -0
  176. package/dist/sdk/sessions/approvals.d.ts +47 -0
  177. package/dist/sdk/sessions/approvals.js +119 -0
  178. package/dist/sdk/sessions/continuation.d.ts +48 -0
  179. package/dist/sdk/sessions/continuation.js +85 -0
  180. package/dist/sdk/sessions/contracts.d.ts +534 -0
  181. package/dist/sdk/sessions/contracts.js +299 -0
  182. package/dist/sdk/sessions/extensionUi.d.ts +19 -0
  183. package/dist/sdk/sessions/extensionUi.js +64 -0
  184. package/dist/sdk/sessions/history.d.ts +16 -0
  185. package/dist/sdk/sessions/history.js +68 -0
  186. package/dist/sdk/sessions/lineageJoin.d.ts +2 -0
  187. package/dist/sdk/sessions/lineageJoin.js +61 -0
  188. package/dist/sdk/sessions/planMode.d.ts +36 -0
  189. package/dist/sdk/sessions/planMode.js +84 -0
  190. package/dist/sdk/sessions/policy.d.ts +43 -0
  191. package/dist/sdk/sessions/policy.js +1 -0
  192. package/dist/sdk/sessions/pricing.d.ts +34 -0
  193. package/dist/sdk/sessions/pricing.js +40 -0
  194. package/dist/sdk/sessions/reasoningSummaries.d.ts +11 -0
  195. package/dist/sdk/sessions/reasoningSummaries.js +61 -0
  196. package/dist/sdk/sessions/registry.d.ts +102 -0
  197. package/dist/sdk/sessions/registry.js +383 -0
  198. package/dist/sdk/sessions/runIndex.d.ts +21 -0
  199. package/dist/sdk/sessions/runIndex.js +65 -0
  200. package/dist/sdk/sessions/runStore.d.ts +66 -0
  201. package/dist/sdk/sessions/runStore.js +335 -0
  202. package/dist/sdk/sessions/runner.d.ts +213 -0
  203. package/dist/sdk/sessions/runner.js +589 -0
  204. package/dist/sdk/sessions/sessions.d.ts +140 -0
  205. package/dist/sdk/sessions/sessions.js +394 -0
  206. package/dist/sdk/sessions/subagentService.d.ts +41 -0
  207. package/dist/sdk/sessions/subagentService.js +247 -0
  208. package/dist/sdk/sessions/subagents.d.ts +50 -0
  209. package/dist/sdk/sessions/subagents.js +68 -0
  210. package/dist/sdk/terminal/accountsMenu.d.ts +46 -0
  211. package/dist/sdk/terminal/accountsMenu.js +392 -0
  212. package/dist/sdk/terminal/cli.d.ts +20 -0
  213. package/dist/sdk/terminal/cli.js +121 -0
  214. package/dist/sdk/terminal/client.d.ts +15 -0
  215. package/dist/sdk/terminal/client.js +126 -0
  216. package/dist/sdk/terminal/control.d.ts +4 -0
  217. package/dist/sdk/terminal/control.js +25 -0
  218. package/dist/sdk/terminal/controller.d.ts +72 -0
  219. package/dist/sdk/terminal/controller.js +351 -0
  220. package/dist/sdk/terminal/hubMenu.d.ts +10 -0
  221. package/dist/sdk/terminal/hubMenu.js +34 -0
  222. package/dist/sdk/terminal/launch.d.ts +5 -0
  223. package/dist/sdk/terminal/launch.js +27 -0
  224. package/dist/sdk/terminal/logs.d.ts +14 -0
  225. package/dist/sdk/terminal/logs.js +59 -0
  226. package/dist/sdk/terminal/piExtension.d.ts +6 -0
  227. package/dist/sdk/terminal/piExtension.js +392 -0
  228. package/dist/sdk/terminal/pluginMenu.d.ts +34 -0
  229. package/dist/sdk/terminal/pluginMenu.js +101 -0
  230. package/dist/sdk/terminal/socket.d.ts +70 -0
  231. package/dist/sdk/terminal/socket.js +256 -0
  232. package/dist/sdk/terminal/standalone.d.ts +18 -0
  233. package/dist/sdk/terminal/standalone.js +146 -0
  234. package/dist/sdk/terminal/terminals.d.ts +176 -0
  235. package/dist/sdk/terminal/terminals.js +767 -0
  236. package/dist/sdk/terminal/trajectory.d.ts +10 -0
  237. package/dist/sdk/terminal/trajectory.js +30 -0
  238. package/dist/sdk/terminal/tui/chrome.d.ts +64 -0
  239. package/dist/sdk/terminal/tui/chrome.js +169 -0
  240. package/dist/sdk/terminal/tui/clipboardFiles.d.ts +11 -0
  241. package/dist/sdk/terminal/tui/clipboardFiles.js +74 -0
  242. package/dist/sdk/terminal/tui/commandPages.d.ts +7 -0
  243. package/dist/sdk/terminal/tui/commandPages.js +63 -0
  244. package/dist/sdk/terminal/tui/commands.d.ts +42 -0
  245. package/dist/sdk/terminal/tui/commands.js +276 -0
  246. package/dist/sdk/terminal/tui/dialogGeometry.d.ts +27 -0
  247. package/dist/sdk/terminal/tui/dialogGeometry.js +50 -0
  248. package/dist/sdk/terminal/tui/dialogs.d.ts +75 -0
  249. package/dist/sdk/terminal/tui/dialogs.js +363 -0
  250. package/dist/sdk/terminal/tui/keybindings.d.ts +11 -0
  251. package/dist/sdk/terminal/tui/keybindings.js +49 -0
  252. package/dist/sdk/terminal/tui/list.d.ts +73 -0
  253. package/dist/sdk/terminal/tui/list.js +196 -0
  254. package/dist/sdk/terminal/tui/modeChoices.d.ts +42 -0
  255. package/dist/sdk/terminal/tui/modeChoices.js +70 -0
  256. package/dist/sdk/terminal/tui/modelPicker.d.ts +55 -0
  257. package/dist/sdk/terminal/tui/modelPicker.js +155 -0
  258. package/dist/sdk/terminal/tui/mouse.d.ts +3 -0
  259. package/dist/sdk/terminal/tui/mouse.js +3 -0
  260. package/dist/sdk/terminal/tui/page.d.ts +14 -0
  261. package/dist/sdk/terminal/tui/page.js +1 -0
  262. package/dist/sdk/terminal/tui/pageOverlay.d.ts +27 -0
  263. package/dist/sdk/terminal/tui/pageOverlay.js +145 -0
  264. package/dist/sdk/terminal/tui/pages/accountsPage.d.ts +54 -0
  265. package/dist/sdk/terminal/tui/pages/accountsPage.js +181 -0
  266. package/dist/sdk/terminal/tui/pages/componentsPage.d.ts +47 -0
  267. package/dist/sdk/terminal/tui/pages/componentsPage.js +119 -0
  268. package/dist/sdk/terminal/tui/pages/doctorPage.d.ts +37 -0
  269. package/dist/sdk/terminal/tui/pages/doctorPage.js +145 -0
  270. package/dist/sdk/terminal/tui/pages/hubPage.d.ts +39 -0
  271. package/dist/sdk/terminal/tui/pages/hubPage.js +128 -0
  272. package/dist/sdk/terminal/tui/pages/logPage.d.ts +38 -0
  273. package/dist/sdk/terminal/tui/pages/logPage.js +189 -0
  274. package/dist/sdk/terminal/tui/pages/permissionsPage.d.ts +44 -0
  275. package/dist/sdk/terminal/tui/pages/permissionsPage.js +124 -0
  276. package/dist/sdk/terminal/tui/pages/pluginsPage.d.ts +57 -0
  277. package/dist/sdk/terminal/tui/pages/pluginsPage.js +243 -0
  278. package/dist/sdk/terminal/tui/pages/settingsPage.d.ts +55 -0
  279. package/dist/sdk/terminal/tui/pages/settingsPage.js +88 -0
  280. package/dist/sdk/terminal/tui/pages/trajectoryPage.d.ts +58 -0
  281. package/dist/sdk/terminal/tui/pages/trajectoryPage.js +377 -0
  282. package/dist/sdk/terminal/tui/piAdapter.d.ts +18 -0
  283. package/dist/sdk/terminal/tui/piAdapter.js +48 -0
  284. package/dist/sdk/terminal/tui/planMode.d.ts +2 -0
  285. package/dist/sdk/terminal/tui/planMode.js +2 -0
  286. package/dist/sdk/terminal/tui/questionPicker.d.ts +20 -0
  287. package/dist/sdk/terminal/tui/questionPicker.js +150 -0
  288. package/dist/sdk/terminal/tui/questions.d.ts +19 -0
  289. package/dist/sdk/terminal/tui/questions.js +42 -0
  290. package/dist/sdk/terminal/tui/runtime.d.ts +114 -0
  291. package/dist/sdk/terminal/tui/runtime.js +441 -0
  292. package/dist/sdk/terminal/tui/search.d.ts +22 -0
  293. package/dist/sdk/terminal/tui/search.js +60 -0
  294. package/dist/sdk/terminal/tui/selection.d.ts +16 -0
  295. package/dist/sdk/terminal/tui/selection.js +16 -0
  296. package/dist/sdk/terminal/tui/sessionUi.d.ts +3 -0
  297. package/dist/sdk/terminal/tui/sessionUi.js +30 -0
  298. package/dist/sdk/terminal/tui/settingsModel.d.ts +12 -0
  299. package/dist/sdk/terminal/tui/settingsModel.js +84 -0
  300. package/dist/sdk/terminal/tui/sideQuestion.d.ts +53 -0
  301. package/dist/sdk/terminal/tui/sideQuestion.js +197 -0
  302. package/dist/sdk/terminal/tui/skillInvocation.d.ts +9 -0
  303. package/dist/sdk/terminal/tui/skillInvocation.js +43 -0
  304. package/dist/sdk/terminal/tui/status.d.ts +18 -0
  305. package/dist/sdk/terminal/tui/status.js +67 -0
  306. package/dist/sdk/terminal/tui/theme.d.ts +45 -0
  307. package/dist/sdk/terminal/tui/theme.js +176 -0
  308. package/dist/sdk/terminal/tui/treeModel.d.ts +79 -0
  309. package/dist/sdk/terminal/tui/treeModel.js +483 -0
  310. package/dist/sdk/terminal/tui/treePicker.d.ts +49 -0
  311. package/dist/sdk/terminal/tui/treePicker.js +251 -0
  312. package/dist/sdk/terminal/tui/ui.d.ts +47 -0
  313. package/dist/sdk/terminal/tui/ui.js +148 -0
  314. package/dist/sdk/terminal/tui/workingStatus.d.ts +9 -0
  315. package/dist/sdk/terminal/tui/workingStatus.js +229 -0
  316. package/dist/sdk/tools/askUser.d.ts +6 -0
  317. package/dist/sdk/tools/askUser.js +74 -0
  318. package/dist/sdk/tools/checklist.d.ts +9 -0
  319. package/dist/sdk/tools/checklist.js +54 -0
  320. package/dist/sdk/tools/definitions.d.ts +30 -0
  321. package/dist/sdk/tools/definitions.js +117 -0
  322. package/dist/sdk/tools/dispatch.d.ts +16 -0
  323. package/dist/sdk/tools/dispatch.js +67 -0
  324. package/dist/sdk/tools/harnessTools.d.ts +6 -0
  325. package/dist/sdk/tools/harnessTools.js +20 -0
  326. package/dist/sdk/tools/sessionName.d.ts +7 -0
  327. package/dist/sdk/tools/sessionName.js +31 -0
  328. package/dist/sdk/tools/spawnSubagent.d.ts +4 -0
  329. package/dist/sdk/tools/spawnSubagent.js +49 -0
  330. package/dist/sdk/tools/types.d.ts +48 -0
  331. package/dist/sdk/tools/types.js +1 -0
  332. package/dist/sdk/variant/components.d.ts +34 -0
  333. package/dist/sdk/variant/components.js +230 -0
  334. package/dist/sdk/variant/materialise.d.ts +66 -0
  335. package/dist/sdk/variant/materialise.js +81 -0
  336. package/dist/sdk/variant/migrate.d.ts +4 -0
  337. package/dist/sdk/variant/migrate.js +41 -0
  338. package/dist/sdk/variant/seed.d.ts +20 -0
  339. package/dist/sdk/variant/seed.js +116 -0
  340. package/dist/sdk/variant/store.d.ts +82 -0
  341. package/dist/sdk/variant/store.js +151 -0
  342. package/dist/sdk/variant/surface.d.ts +56 -0
  343. package/dist/sdk/variant/surface.js +81 -0
  344. package/dist/sdk/variant/trust.d.ts +27 -0
  345. package/dist/sdk/variant/trust.js +64 -0
  346. package/dist/sdk/variant/variant.d.ts +71 -0
  347. package/dist/sdk/variant/variant.js +331 -0
  348. package/dist/sdk/web/markdown.d.ts +10 -0
  349. package/dist/sdk/web/markdown.js +66 -0
  350. package/dist/sdk/web/safeRequest.d.ts +34 -0
  351. package/dist/sdk/web/safeRequest.js +175 -0
  352. package/dist/sdk/web/search.d.ts +53 -0
  353. package/dist/sdk/web/search.js +168 -0
  354. package/dist/sdk/web/text.d.ts +2 -0
  355. package/dist/sdk/web/text.js +7 -0
  356. package/dist/sdk/web/tools.d.ts +22 -0
  357. package/dist/sdk/web/tools.js +195 -0
  358. package/dist/sdk/web/turndown-plugin-gfm.d.ts +4 -0
  359. package/dist/sdk/wiki/notes.d.ts +68 -0
  360. package/dist/sdk/wiki/notes.js +297 -0
  361. package/dist/sdk/world/actions.d.ts +23 -0
  362. package/dist/sdk/world/actions.js +31 -0
  363. package/dist/sdk/world/cli.d.ts +12 -0
  364. package/dist/sdk/world/cli.js +166 -0
  365. package/dist/sdk/world/images.d.ts +20 -0
  366. package/dist/sdk/world/images.js +48 -0
  367. package/dist/sdk/world/untrusted.d.ts +12 -0
  368. package/dist/sdk/world/untrusted.js +20 -0
  369. package/dist/sdk/world/world.d.ts +65 -0
  370. package/dist/sdk/world/world.js +80 -0
  371. package/dist/terminal-opentui.js +13612 -0
  372. package/dist/terminal-pi.js +808 -151
  373. package/docs/README.md +22 -0
  374. package/docs/architecture/00-overview.md +159 -0
  375. package/docs/architecture/01-extension-points.md +78 -0
  376. package/docs/architecture/02-sessions-and-runs.md +146 -0
  377. package/docs/architecture/03-variants.md +95 -0
  378. package/docs/architecture/04-prompt.md +102 -0
  379. package/docs/architecture/05-refinement.md +107 -0
  380. package/docs/architecture/06-plugins-and-capabilities.md +93 -0
  381. package/docs/architecture/07-tools-and-gate.md +88 -0
  382. package/docs/architecture/08-memory-and-history.md +94 -0
  383. package/docs/architecture/09-accounts-and-connectors.md +90 -0
  384. package/docs/architecture/10-server-protocol.md +84 -0
  385. package/docs/architecture/11-terminal.md +81 -0
  386. package/docs/architecture/12-storage.md +61 -0
  387. package/docs/architecture/13-world-tools.md +23 -0
  388. package/docs/architecture/README.md +114 -0
  389. package/docs/architecture/proposals/PROP-0001-reporting-section.md +106 -0
  390. package/docs/architecture/proposals/PROP-0002-retain-rollout-workspaces.md +104 -0
  391. package/docs/architecture/proposals/PROP-0003-executor-settings.md +81 -0
  392. package/docs/architecture/proposals/PROP-0004-flexible-reporting-guidance.md +71 -0
  393. package/docs/architecture/proposals/PROP-0005-xharness-cli-name.md +78 -0
  394. package/docs/architecture/proposals/PROP-0006-run-checklist.md +68 -0
  395. package/docs/architecture/proposals/PROP-0007-run-continuation.md +80 -0
  396. package/docs/architecture/proposals/PROP-0008-lessons-from-runs.md +80 -0
  397. package/docs/architecture/proposals/PROP-0009-foundation-and-variants.md +78 -0
  398. package/docs/architecture/proposals/PROP-0010-session-names.md +73 -0
  399. package/docs/architecture/proposals/PROP-0011-doctor.md +63 -0
  400. package/docs/architecture/proposals/PROP-0012-release-baseline.md +56 -0
  401. package/docs/architecture/proposals/README.md +76 -0
  402. package/docs/decisions/ADR-0002-native-subagent-lifecycle.md +49 -0
  403. package/docs/decisions/ADR-0003-shared-asynchronous-subagents.md +70 -0
  404. package/docs/decisions/ADR-0004-fullscreen-terminal-layout.md +50 -0
  405. package/docs/decisions/ADR-0005-app-provided-oauth-clients.md +54 -0
  406. package/docs/decisions/ADR-0006-opentui-only-terminal.md +47 -0
  407. package/docs/decisions/ADR-0007-reporting-section.md +33 -0
  408. package/docs/decisions/ADR-0008-flexible-reporting-guidance.md +38 -0
  409. package/docs/decisions/ADR-0009-xharness-command.md +38 -0
  410. package/docs/decisions/ADR-0010-lessons-in-the-wiki.md +31 -0
  411. package/docs/decisions/ADR-0011-foundation-and-variants.md +28 -0
  412. package/docs/decisions/ADR-0012-native-session-names.md +34 -0
  413. package/docs/decisions/ADR-0013-doctor.md +27 -0
  414. package/docs/decisions/ADR-0014-public-release-baseline.md +21 -0
  415. package/docs/doctor.md +74 -0
  416. package/docs/experiments/EXP-0001-terminal-input-latency/plan.md +81 -0
  417. package/docs/experiments/EXP-0001-terminal-input-latency/results.md +46 -0
  418. package/docs/experiments/EXP-0002-opentui-typing-latency/plan.md +70 -0
  419. package/docs/experiments/EXP-0002-opentui-typing-latency/results.md +92 -0
  420. package/docs/features/README.md +20 -0
  421. package/docs/features/automations/README.md +41 -0
  422. package/docs/features/cores/README.md +39 -0
  423. package/docs/features/google-harness2/README.md +52 -0
  424. package/docs/features/integrations/README.md +40 -0
  425. package/docs/features/interfaces/README.md +29 -0
  426. package/docs/features/memory/README.md +28 -0
  427. package/docs/releases/1.0.0.md +40 -0
  428. package/docs/releases/README.md +36 -0
  429. package/docs/study/00-index.md +78 -0
  430. package/docs/study/arms/00-matrix.md +20 -0
  431. package/docs/study/arms/01-system-prompt.md +211 -0
  432. package/docs/study/arms/02-tools.md +79 -0
  433. package/docs/study/arms/03-subagents.md +90 -0
  434. package/docs/study/arms/04-skills.md +75 -0
  435. package/docs/study/arms/05-context-management.md +90 -0
  436. package/docs/study/arms/06-memory.md +90 -0
  437. package/docs/study/arms/07-governance.md +71 -0
  438. package/docs/study/arms/08-execution.md +69 -0
  439. package/docs/study/arms/09-observability.md +60 -0
  440. package/docs/study/arms/10-refinement.md +110 -0
  441. package/docs/study/btw-comparison.md +37 -0
  442. package/docs/study/feature-gap-review.md +42 -0
  443. package/docs/study/insights.md +123 -0
  444. package/docs/study/roadmap.md +72 -0
  445. package/docs/study/sources/claude-code.md +44 -0
  446. package/docs/study/sources/deepseek-harness.md +102 -0
  447. package/docs/study/sources/harness2.md +50 -0
  448. package/docs/study/sources/kimi-cli.md +42 -0
  449. package/docs/study/sources/omp.md +93 -0
  450. package/docs/study/sources/opencode.md +43 -0
  451. package/docs/study/sources/openhands.md +46 -0
  452. package/docs/study/sources/smolagents.md +40 -0
  453. package/docs/study/sources/swe-agent.md +34 -0
  454. package/docs/system-prompt-design.md +196 -0
  455. package/docs/terminal-tui.md +473 -56
  456. package/package.json +43 -13
  457. package/docs/evidence/terminal-2026-10-17/120x40-completed-transcript.ansi.gz +0 -0
  458. package/docs/evidence/terminal-2026-10-17/40x20-settings-interaction.ansi.gz +0 -0
  459. package/docs/evidence/terminal-2026-10-17/40x20-settings-keyboard.ansi.gz +0 -0
  460. package/docs/evidence/terminal-2026-10-17/40x20-welcome.ansi.gz +0 -0
  461. package/docs/evidence/terminal-2026-10-17/80x24-approval-0.ansi.gz +0 -0
  462. package/docs/evidence/terminal-2026-10-17/80x24-question.ansi.gz +0 -0
  463. package/docs/evidence/terminal-2026-10-17/verification.json +0 -130
  464. package/docs/evidence/terminal-2026-10-17-followup/120x40-completed-transcript.ansi.gz +0 -0
  465. package/docs/evidence/terminal-2026-10-17-followup/40x20-settings-interaction.ansi.gz +0 -0
  466. package/docs/evidence/terminal-2026-10-17-followup/40x20-settings-keyboard.ansi.gz +0 -0
  467. package/docs/evidence/terminal-2026-10-17-followup/40x20-welcome.ansi.gz +0 -0
  468. package/docs/evidence/terminal-2026-10-17-followup/80x24-approval-0.ansi.gz +0 -0
  469. package/docs/evidence/terminal-2026-10-17-followup/80x24-plugin-light.ansi.gz +0 -0
  470. package/docs/evidence/terminal-2026-10-17-followup/80x24-question-batch.ansi.gz +0 -0
  471. package/docs/evidence/terminal-2026-10-17-followup/80x24-question.ansi.gz +0 -0
  472. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-approval-0.ansi.gz +0 -0
  473. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-plugin-light.ansi.gz +0 -0
  474. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-question-batch.ansi.gz +0 -0
  475. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-question.ansi.gz +0 -0
  476. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/verification.json +0 -95
  477. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-approval-0.ansi.gz +0 -0
  478. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-plugin-light.ansi.gz +0 -0
  479. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-question-batch.ansi.gz +0 -0
  480. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-question.ansi.gz +0 -0
  481. package/docs/evidence/terminal-2026-10-17-followup/global-install/README.md +0 -27
  482. package/docs/evidence/terminal-2026-10-17-followup/global-install/shell-command-80x24.ansi.gz +0 -0
  483. package/docs/evidence/terminal-2026-10-17-followup/global-install/shell-command.json +0 -18
  484. package/docs/evidence/terminal-2026-10-17-followup/global-install/verification.json +0 -95
  485. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-80x24.json.gz +0 -0
  486. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-final-80x24.json.gz +0 -0
  487. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-scenario.json +0 -60
  488. package/docs/evidence/terminal-2026-10-17-followup/live-codex/README.md +0 -24
  489. package/docs/evidence/terminal-2026-10-17-followup/live-codex/complete-80x24.ansi.gz +0 -0
  490. package/docs/evidence/terminal-2026-10-17-followup/live-codex/verification.json +0 -57
  491. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-80x24-early.json.gz +0 -0
  492. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-80x24.json.gz +0 -0
  493. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-scenario.json +0 -58
  494. package/docs/evidence/terminal-2026-10-17-followup/omp-supplemental-static.json.gz +0 -0
  495. package/docs/evidence/terminal-2026-10-17-followup/rea-artifacts.json +0 -320
  496. package/docs/evidence/terminal-2026-10-17-followup/reference-comparison.json +0 -30
  497. package/docs/evidence/terminal-2026-10-17-followup/reference-comparison.md +0 -133
  498. package/docs/evidence/terminal-2026-10-17-followup/reference-source-observations.json +0 -20
  499. package/docs/evidence/terminal-2026-10-17-followup/verification.json +0 -207
  500. package/src/accounts/accounts.test.ts +0 -333
  501. package/src/accounts/accounts.ts +0 -658
  502. package/src/accounts/env.test.ts +0 -95
  503. package/src/accounts/env.ts +0 -338
  504. package/src/accounts/secrets.ts +0 -50
  505. package/src/accounts/store.ts +0 -338
  506. package/src/capabilities/api.ts +0 -75
  507. package/src/capabilities/runSnapshot.ts +0 -59
  508. package/src/capabilities/types.ts +0 -34
  509. package/src/cli.ts +0 -118
  510. package/src/core/bus.ts +0 -34
  511. package/src/core/changes.ts +0 -33
  512. package/src/core/env.ts +0 -27
  513. package/src/core/errors.ts +0 -32
  514. package/src/core/frontmatter.ts +0 -47
  515. package/src/core/fs.test.ts +0 -38
  516. package/src/core/fs.ts +0 -92
  517. package/src/core/index.ts +0 -193
  518. package/src/core/path.test.ts +0 -14
  519. package/src/core/path.ts +0 -79
  520. package/src/core/projects.ts +0 -90
  521. package/src/core/text.ts +0 -39
  522. package/src/harness.ts +0 -312
  523. package/src/hub/catalog.json +0 -123
  524. package/src/hub/cli.ts +0 -59
  525. package/src/hub/hub.test.ts +0 -205
  526. package/src/hub/hub.ts +0 -256
  527. package/src/hub/schema.ts +0 -81
  528. package/src/index.ts +0 -75
  529. package/src/mcp/connections.ts +0 -614
  530. package/src/mcp/manager.ts +0 -130
  531. package/src/mcp/oauth.ts +0 -195
  532. package/src/mcp/scopeMigration.test.ts +0 -79
  533. package/src/mcp/scopeMigration.ts +0 -204
  534. package/src/mcp/service.test.ts +0 -376
  535. package/src/mcp/service.ts +0 -549
  536. package/src/mcp/types.ts +0 -108
  537. package/src/memory/api.test.ts +0 -82
  538. package/src/memory/api.ts +0 -303
  539. package/src/memory/blocks.test.ts +0 -78
  540. package/src/memory/blocks.ts +0 -408
  541. package/src/memory/caller.ts +0 -69
  542. package/src/memory/curation.test.ts +0 -163
  543. package/src/memory/curation.ts +0 -64
  544. package/src/memory/dispatch.ts +0 -59
  545. package/src/memory/facts.test.ts +0 -41
  546. package/src/memory/facts.ts +0 -248
  547. package/src/memory/graph.ts +0 -103
  548. package/src/memory/health.test.ts +0 -130
  549. package/src/memory/health.ts +0 -74
  550. package/src/memory/maintainer.ts +0 -272
  551. package/src/memory/maintenance.test.ts +0 -176
  552. package/src/memory/maintenance.ts +0 -518
  553. package/src/memory/migrate.ts +0 -79
  554. package/src/memory/operations.ts +0 -150
  555. package/src/memory/proposals.test.ts +0 -168
  556. package/src/memory/proposals.ts +0 -584
  557. package/src/memory/recall.test.ts +0 -115
  558. package/src/memory/recall.ts +0 -278
  559. package/src/memory/references.ts +0 -77
  560. package/src/memory/runContext.ts +0 -93
  561. package/src/memory/secrets.ts +0 -6
  562. package/src/memory/store.test.ts +0 -66
  563. package/src/memory/store.ts +0 -385
  564. package/src/memory/wiki.test.ts +0 -47
  565. package/src/memory/wiki.ts +0 -422
  566. package/src/memory/wikiIndex.test.ts +0 -88
  567. package/src/memory/wikiIndex.ts +0 -116
  568. package/src/plugins/api.ts +0 -181
  569. package/src/plugins/attachments.test.ts +0 -84
  570. package/src/plugins/attachments.ts +0 -141
  571. package/src/plugins/builtin.ts +0 -82
  572. package/src/plugins/catalogue.test.ts +0 -254
  573. package/src/plugins/catalogue.ts +0 -251
  574. package/src/plugins/cli.ts +0 -184
  575. package/src/plugins/discover.ts +0 -151
  576. package/src/plugins/firstParty.test.ts +0 -143
  577. package/src/plugins/firstParty.ts +0 -129
  578. package/src/plugins/hooks.test.ts +0 -250
  579. package/src/plugins/hooks.ts +0 -239
  580. package/src/plugins/identity.ts +0 -37
  581. package/src/plugins/install.test.ts +0 -107
  582. package/src/plugins/install.ts +0 -106
  583. package/src/plugins/inventory.ts +0 -123
  584. package/src/plugins/manifest.ts +0 -76
  585. package/src/plugins/plugins.test.ts +0 -205
  586. package/src/plugins/plugins.ts +0 -189
  587. package/src/plugins/proposal.ts +0 -121
  588. package/src/plugins/runtime.test.ts +0 -40
  589. package/src/plugins/runtime.ts +0 -82
  590. package/src/plugins/trust.ts +0 -142
  591. package/src/plugins/types.ts +0 -149
  592. package/src/prompt/compile.test.ts +0 -261
  593. package/src/prompt/compile.ts +0 -732
  594. package/src/server/methods.ts +0 -349
  595. package/src/server/remote.ts +0 -77
  596. package/src/server/rpc.ts +0 -116
  597. package/src/server/serve.ts +0 -28
  598. package/src/server/server.test.ts +0 -174
  599. package/src/sessions/approvals.ts +0 -118
  600. package/src/sessions/contracts.ts +0 -336
  601. package/src/sessions/conversation.test.ts +0 -177
  602. package/src/sessions/extensionSession.test.ts +0 -74
  603. package/src/sessions/extensionUi.test.ts +0 -65
  604. package/src/sessions/extensionUi.ts +0 -102
  605. package/src/sessions/history.ts +0 -51
  606. package/src/sessions/lineageJoin.ts +0 -75
  607. package/src/sessions/policy.ts +0 -36
  608. package/src/sessions/pricing.ts +0 -60
  609. package/src/sessions/questionBatches.test.ts +0 -110
  610. package/src/sessions/reasoningSummaries.ts +0 -59
  611. package/src/sessions/registry.ts +0 -381
  612. package/src/sessions/runIndex.ts +0 -99
  613. package/src/sessions/runStore.test.ts +0 -152
  614. package/src/sessions/runStore.ts +0 -332
  615. package/src/sessions/runner.ts +0 -604
  616. package/src/sessions/runtimeResources.test.ts +0 -61
  617. package/src/sessions/sessions.test.ts +0 -549
  618. package/src/sessions/sessions.ts +0 -339
  619. package/src/skills/registry.test.ts +0 -104
  620. package/src/skills/registry.ts +0 -413
  621. package/src/terminal/accountsMenu.test.ts +0 -225
  622. package/src/terminal/accountsMenu.ts +0 -382
  623. package/src/terminal/cli.ts +0 -149
  624. package/src/terminal/client.ts +0 -74
  625. package/src/terminal/control.test.ts +0 -23
  626. package/src/terminal/control.ts +0 -23
  627. package/src/terminal/controller.ts +0 -291
  628. package/src/terminal/hubMenu.ts +0 -24
  629. package/src/terminal/launch.test.ts +0 -25
  630. package/src/terminal/launch.ts +0 -48
  631. package/src/terminal/piExtension.lifecycle.test.ts +0 -55
  632. package/src/terminal/piExtension.ts +0 -259
  633. package/src/terminal/pluginControl.test.ts +0 -146
  634. package/src/terminal/pluginMenu.ts +0 -112
  635. package/src/terminal/socket.test.ts +0 -71
  636. package/src/terminal/socket.ts +0 -232
  637. package/src/terminal/standalone.test.ts +0 -167
  638. package/src/terminal/standalone.ts +0 -153
  639. package/src/terminal/terminal.test.ts +0 -399
  640. package/src/terminal/terminals.ts +0 -553
  641. package/src/terminal/tui/application.test.ts +0 -114
  642. package/src/terminal/tui/application.ts +0 -491
  643. package/src/terminal/tui/commands.test.ts +0 -218
  644. package/src/terminal/tui/commands.ts +0 -361
  645. package/src/terminal/tui/dialogs.ts +0 -301
  646. package/src/terminal/tui/editor.test.ts +0 -84
  647. package/src/terminal/tui/editor.ts +0 -79
  648. package/src/terminal/tui/keybindings.test.ts +0 -22
  649. package/src/terminal/tui/keybindings.ts +0 -50
  650. package/src/terminal/tui/piAdapter.ts +0 -62
  651. package/src/terminal/tui/presentation.test.ts +0 -79
  652. package/src/terminal/tui/questions.test.ts +0 -41
  653. package/src/terminal/tui/questions.ts +0 -47
  654. package/src/terminal/tui/runtime.socket.test.ts +0 -104
  655. package/src/terminal/tui/runtime.test.ts +0 -215
  656. package/src/terminal/tui/runtime.ts +0 -388
  657. package/src/terminal/tui/sessionUi.ts +0 -24
  658. package/src/terminal/tui/settings.test.ts +0 -150
  659. package/src/terminal/tui/settings.ts +0 -188
  660. package/src/terminal/tui/status.test.ts +0 -70
  661. package/src/terminal/tui/status.ts +0 -109
  662. package/src/terminal/tui/theme.ts +0 -174
  663. package/src/terminal/tui/tools.test.ts +0 -145
  664. package/src/terminal/tui/tools.ts +0 -142
  665. package/src/terminal/tui/transcript.test.ts +0 -25
  666. package/src/terminal/tui/transcript.ts +0 -124
  667. package/src/terminal/tui/ui.test.ts +0 -313
  668. package/src/terminal/tui/ui.ts +0 -166
  669. package/src/terminal/tui/welcome.ts +0 -102
  670. package/src/tools/askUser.test.ts +0 -69
  671. package/src/tools/askUser.ts +0 -59
  672. package/src/tools/definitions.ts +0 -187
  673. package/src/tools/maintenance.ts +0 -24
  674. package/src/tools/memoryTools.ts +0 -22
  675. package/src/tools/pluginPropose.ts +0 -41
  676. package/src/tools/registryWrite.test.ts +0 -101
  677. package/src/tools/registryWrite.ts +0 -182
  678. package/src/tools/spawnSubagent.ts +0 -92
  679. package/src/tools/types.ts +0 -39
  680. package/src/web/safeRequest.ts +0 -171
  681. package/src/web/text.ts +0 -53
  682. package/src/web/tools.ts +0 -134
  683. package/src/web/web.test.ts +0 -141
@@ -1,30 +1,118 @@
1
1
  # Harness terminal frontend
2
2
 
3
- Status: implemented in the working tree; publication is separate. Last updated: 2026-10-17.
4
- Decision: [ADR-0001](decisions/ADR-0001-owned-terminal.md).
3
+ Status: release candidate `@xingular/harness` 4.0.0; npm publication blocked by registry authorization. Last updated: 2026-10-22.
4
+ Decision: [ADR-0001](decisions/ADR-0001-owned-terminal.md),
5
+ [ADR-0006](decisions/ADR-0006-opentui-only-terminal.md),
6
+ [ADR-0009](decisions/ADR-0009-xharness-command.md).
5
7
 
6
- ## Ownership and process boundary
8
+ ## OpenTUI terminal
9
+
10
+ OpenTUI/Solid, built from [`src/terminal/opentui/`](../src/terminal/opentui/), is the only terminal
11
+ frontend. It needs Bun 1.3.14 or newer for its build and runtime:
7
12
 
8
- Harness owns its interactive terminal application in [`src/terminal/tui/`](../src/terminal/tui/).
9
- [`TerminalApplication`](../src/terminal/tui/application.ts) owns terminal lifecycle, screen
10
- composition, focus, input dispatch, scrolling, editor mounting, dialogs and keyboard actions.
11
- It does not construct Pi's `InteractiveMode`. Pi 1.2.0 supplies the persistent agent session,
12
- model and auth runtime, native JSONL history, tool execution and rich content components.
13
+ ```sh
14
+ npm run build:tui
15
+ node dist/cli.js terminal
16
+ ```
17
+
18
+ `npm run build` builds `dist/terminal-opentui.js`; without Bun the build fails, because there is no
19
+ second frontend to fall back to. The harness passes `--conditions=browser` when it launches the
20
+ bundle so Solid resolves to its client build, not its server build. `XINGULAR_HARNESS_BUN`
21
+ overrides the Bun executable.
22
+
23
+ [`app.ts`](../src/terminal/opentui/app.ts) owns the terminal lifecycle and reuses the shared
24
+ `TerminalRuntime`, session replacement, commands, decisions, account pinning and run records. It
25
+ projects the runtime's snapshot and transcript into an OpenCode-inspired view, with a native
26
+ OpenTUI textarea for the prompt, `Ctrl+K` for the command palette, `Return` to send (or to queue behind a running reply),
27
+ `Cmd+Return` (or `Alt+Return`) to steer a running reply, and `Shift+Return` for a newline. With an
28
+ empty composer, unmodified Up recalls the latest non-empty user message from the active session.
29
+ After recall, unmodified Up/Down are available for normal editor movement and do not browse history
30
+ while the draft is non-empty. Ctrl+Up/Down remain explicit history shortcuts; Down past the newest
31
+ entry restores a blank draft. History comes from the active Pi session's saved messages, so `/new`
32
+ and `/resume` switch to that session's history. Steering needs a terminal that reports Cmd with the
33
+ kitty keyboard protocol; elsewhere `Alt+Return` steers. In the composer, `Tab` opens up to eight matching filesystem entries for the path token at the cursor, or current-folder entries when the token is empty. The list has no heading or hint row. Up/Down select; Enter or Tab inserts the selection; Escape closes the list. Directories end in `/`, and Bash mode escapes shell-special characters. Use `/effort` or Shift+Up/Down to change effort. The command palette opens above the composer under a muted (`dim`) top rule, and has no other border. Its rows align slash commands and descriptions in two columns: the command column sizes to the widest visible name, bounded to preserve description space, and both columns wrap instead of truncating. The plan-choice rule, question block's top-only divider, and `/btw` block's top rule use the same muted color as the normal composer divider. The console has no background of its own: the renderer, root surface
34
+ and transcript are transparent, so the terminal's own background shows through, while panels,
35
+ dialogs and the scrim stay opaque. The composer has no panel background: it is bounded by a top and
36
+ a bottom rule, with the working status and spinner above it and a wrapping status bar below it. Its
37
+ fixed-width left gutter shows `❯` on the first input row and leaves continuation rows blank, including
38
+ explicit newlines and soft wraps; Bash mode shows `!` on the first row instead. In plan mode,
39
+ `plan mode` is right-aligned within the top rule, followed by exactly one divider character. The status bar shows the working folder's name, the Git branch, the account, model and effort separated by spaces, and input (`↑`) and output (`↓`) token counts with each glyph adjacent to its count; `|` separates the groups. Token counts
40
+ below 1,000 show as whole numbers and larger counts use K/M/B suffixes. A leading `!`
41
+ enters Bash mode: the chevron becomes `!`, and the marker and both rules use the `bashMode` colour.
42
+ In plan mode, the marker and rules use the plan blue and `plan mode` is right-aligned within the
43
+ top rule with exactly one divider character after it; in the normal prompt, the marker matches the divider. The command body keeps the normal
44
+ text color. Every terminal animates the same star
45
+ glyphs (`·✢✳✶✻✽`) while working, with Ghostty's existing variant; there is no ASCII line fallback.
46
+ Extension dialogs, pages, custom editors, widgets, headers and footers keep using Pi's component
47
+ API through [`dialogHost.ts`](../src/terminal/opentui/dialogHost.ts): a small fake `TUI` renders
48
+ `Component.render(width)` ANSI into stacked overlays and forwards raw key sequences. Extensions
49
+ never receive an OpenTUI renderable or a second account. A theme an extension selects still colors
50
+ its own components, while the OpenTUI chrome keeps the fixed OpenCode-inspired palette. Component
51
+ UI is supported; an extension that draws only by writing raw ANSI through the TUI terminal is not.
52
+
53
+ Pages become centered dialogs. The page commands `/accounts`, `/permissions`, `/plugins`,
54
+ `/hub`, `/components`, `/settings`, `/trajectory` and `/log`, the `/model` and `/tree` pickers, and
55
+ the `select`, `confirm`, `input` and `editor` dialogs (such as `/effort` and the Thinking setting),
56
+ take 80% of the terminal, capped at 100 columns by 30 rows, on a flat panel in the console's panel
57
+ colour. A full-screen scrim dims the console behind the panel so the transcript stays faintly
58
+ visible. Centered Harness dialogs fit their rendered content, capped by the available dialog
59
+ height, with four columns of horizontal padding and two rows of vertical padding to account for
60
+ the terminal's taller-than-wide cells. They use a plain title with a muted `Esc` hint and
61
+ omit divider rules and footer hints. Shortcut behavior remains available. Searchable lists share
62
+ the same glyph, placeholder, spacing, and muted result note, with search context included on that
63
+ row. A terminal too small for a 30-column by
64
+ 12-row dialog falls back to the full-screen page chrome. A plugin's full-screen surface stays full
65
+ screen.
66
+
67
+ The frontend is verified with a real isolated PTY and a loopback provider. Run
68
+ `python3 scripts/verify-terminal.py --composer-only` for explicit-newline and soft-wrap checks of
69
+ both prompt gutters plus normal/plan/Bash mode exclusivity, `--file-completion-only` for filesystem
70
+ completion and insertion,
71
+ `--history-only` for active-session history across `/new` and `/resume`, `--help-only` for `/help` replacing the welcome screen, `--questions-only` for recommended choices,
72
+ selected-row and Continue/Submit colors, `--jump-latest-only` for scroll-away badge visibility and click-to-latest (screen-level click assertions use optional `pyte`), and choice-backed “Something else” answers, or `--thinking-only` for `/thinking` visibility toggles. The full suite covers a complete turn, `read`, `bash` approval, `ask_user_question` approval and picker, plugin overlay/widget/status
73
+ disposal, a completed run record with usage and decision events, `/help`, `/permissions`,
74
+ `/settings`, `/model`, palette selection, confirm cancel, and Ctrl+D exit. Live-provider behavior,
75
+ exact OpenCode parity and concurrent session tabs are not established.
76
+
77
+ ## Native subagents (2026-10-18)
78
+
79
+ Interactive terminal turns use the same `harness.subagents` service as SDK callers. The bridge
80
+ registers the current run's effective tools, resolved model, thinking level and pinned account
81
+ through its private control channel; a read-only terminal narrows child capabilities and broker
82
+ access. `spawn_subagent` returns immediately, `wait_subagents` joins selected children, and
83
+ `wait: true` on spawn returns an inline result. Native receipts deduplicate automatic delivery.
84
+ The terminal joins outstanding children before its final reply, projects child approvals/questions
85
+ with their original run IDs, and stops descendants when interrupted or disposed. Connected apps
86
+ need not be enabled. `TerminalPrepareInput.subagents: null` disables the capability.
87
+
88
+ Real scripted Pi execution over the actual terminal socket verifies result delivery and decision
89
+ routing. It does not establish live-provider behavior or new visual UI parity. See
90
+ [ADR-0003](decisions/ADR-0003-shared-asynchronous-subagents.md) for recovery and lifecycle details.
91
+
92
+ ## Ownership and process boundary
13
93
 
14
- The parent process still calls `Terminals.prepare()`, spawns its returned specification in a
15
- PTY or inherited terminal, and eventually calls `dispose()`. Its default command is the active
16
- Node runtime followed by the existing Harness CLI and `terminal-frontend`; it requires no global
17
- `pi` command. `TerminalAssets` remains `{ node, cli, piExtension }`, and the existing
18
- `prepare`, `send`, `state`, `input` and `dispose` contracts remain in place. The `piExtension`
19
- path remains the final prepared extension argument. The owned runtime recognizes that bridge
20
- position and loads its trusted, bundled factory inline after the selected disk extensions.
94
+ Harness owns its interactive terminal application in
95
+ [`src/terminal/opentui/`](../src/terminal/opentui/). [`app.ts`](../src/terminal/opentui/app.ts)
96
+ owns terminal lifecycle, submission, commands, decisions and run records;
97
+ [`root.tsx`](../src/terminal/opentui/root.tsx) owns composition, the transcript, the composer,
98
+ palette and dialogs. It does not construct Pi's `InteractiveMode`. Pi 1.2.0 supplies the
99
+ persistent agent session, model and auth runtime, native JSONL history, tool execution and rich
100
+ content components.
101
+
102
+ The parent process calls `Terminals.prepare()`, spawns its returned specification in a PTY or
103
+ inherited terminal, and eventually calls `dispose()`. Its command is Bun with
104
+ `--conditions=browser` and the built `dist/terminal-opentui.js`; it requires no global `pi`
105
+ command. `TerminalAssets` is `{ node, cli, piExtension, openTui }`, and the existing `prepare`,
106
+ `send`, `state`, `input` and `dispose` contracts remain in place. The `piExtension` path remains
107
+ the final prepared extension argument. The runtime recognizes that bridge position and loads its
108
+ trusted, bundled factory inline after the selected disk extensions.
21
109
 
22
110
  ```text
23
111
  Harness parent: account + compiled context + trusted resources + run writer
24
112
  | launch specification / existing session socket
25
- Harness terminal child: TerminalApplication + persistent Pi AgentSessionRuntime
113
+ Harness terminal child: OpenTUI application + persistent Pi AgentSessionRuntime
26
114
  | typed native events / plugin UI callbacks
27
- Harness screen: welcome, transcript, status band, editor, dialogs and overlays
115
+ Harness screen: transcript above the composer, with centered page dialogs and blocks
28
116
  ```
29
117
 
30
118
  [`runtime.ts`](../src/terminal/tui/runtime.ts) builds a public `AgentSessionRuntime` around
@@ -41,6 +129,172 @@ prompts. Reusing `sessions.run` for each prompt would recreate and dispose a ses
41
129
  turn and overlap the terminal controller's run lifecycle. That API remains the embedding and
42
130
  unattended execution path.
43
131
 
132
+ ## Screen layout
133
+
134
+ [`root.tsx`](../src/terminal/opentui/root.tsx) draws the terminal on OpenTUI's alternate screen.
135
+ An empty conversation shows the centered product mark and a short hint; once a message exists, a
136
+ scrollable transcript fills the space above the composer. Single-line notices can appear with the
137
+ welcome, while multiline notices such as `/help` switch to the transcript layout so their output
138
+ cannot overlap it. The composer is a single top and bottom rule, with the right-aligned `plan mode` label followed by one divider character in the top rule,
139
+ and the textarea in the middle.
140
+ The working status row shows the active verb with a soft, warm glint that feathers across it and
141
+ fades past its edges, followed by run duration and the latest completed assistant response's output
142
+ rate, formatted as `(time, tok/s)`; the spinner and metrics stay steady, and duration updates during a run.
143
+ Until response usage is available, the rate shows `— tok/s`. On settlement, the completion verb and
144
+ final run statistics stay in that row until the next run replaces them; they do not become a transcript
145
+ entry. Notifications, queue announcements, compaction-start and retry updates—including retries
146
+ while summarizing context or branches—are one-line transcript entries at the point they occur, so
147
+ subsequent chat moves them up rather than keeping them pinned at the bottom. A completed context
148
+ compaction adds a first-class card from Pi's persisted session history, showing the token count and
149
+ an expandable Markdown summary; click the card or use Ctrl+O to toggle its details.
150
+ A successful transcript-selection copy instead shows a temporary, opaque toast at the top-right of the
151
+ terminal. Interactive blocks and widgets remain docked above the composer. A wrapping status bar
152
+ below the composer shows the working folder, branch, account, model, effort and token totals. After
153
+ the input token count it shows cache hit rate as `R<percentage>%`, calculated from cache reads divided
154
+ by total input tokens. The footer shows status messages without a shortcut-hint row. Press `?` with an empty
155
+ composer to open the shortcut reference. Transcript entries include
156
+ messages, thinking, tools, notices and extension ANSI components. Image blocks returned by tools
157
+ appear as separate image-result entries immediately after their tool call, within the scrollable
158
+ transcript; they move up with newer chat. The `/settings` Show images option controls whether the
159
+ image data is rendered. Mouse-wheel scrolling and PgUp/PgDn
160
+ move the transcript without moving the composer; Ctrl+Home and Ctrl+End jump to its beginning and
161
+ end. A narrow `▕` thumb marks transcript position at the right edge; its mouse and keyboard scrolling remain native. The transcript has one blank row between each pair of entries, including assistant replies,
162
+ thinking, tools, image results, notices, summaries, custom messages, user messages, plan cards and
163
+ Bash entries. User, plan and Bash bubbles also have one blank row of internal padding above and below
164
+ their content; other entries have no internal vertical padding. Bubble padding is additional to the
165
+ inter-entry gap. Internal lines within an entry stay together. The transcript stays pinned to the
166
+ latest message until you scroll away. While scrolled away, a `↓ Jump to latest` badge overlays the
167
+ transcript's lower-right corner; clicking it returns to the newest message and hides the badge.
168
+ `Ctrl+End` remains an alternate way to jump to the end. A primary click in the transcript or empty welcome area focuses the composer. Dragging to select
169
+ transcript text copies the selected plain text when the selection is released; a simple click does
170
+ not copy. `/copy` and `Ctrl+X` continue to copy the latest assistant reply.
171
+
172
+ Mouse movement highlights the row under the pointer in the command palette, plan choices, question
173
+ dock, searchable dialogs and Harness page lists; the highlight uses the same selection style as
174
+ keyboard navigation. A primary click activates the row, and clicks on page tabs switch that page's
175
+ section. Question choices still stage their answer until the question's action is clicked. Dialogs
176
+ preserve their existing confirmation safeguards. OpenTUI enables terminal mouse-motion reporting for
177
+ hover; terminals or multiplexers that do not report motion retain keyboard navigation. ANSI-only
178
+ custom UI without a mouse handler remains keyboard-driven.
179
+
180
+ Page dialogs and blocks are absolute overlays, so the transcript stays behind them. The screen
181
+ restores the terminal's alternate-screen state when the application exits.
182
+
183
+ ### Markdown transcript
184
+
185
+ Assistant replies, plan-card bodies and Markdown image-result text share one style map. Heading
186
+ levels use the Harness palette; links are blue and underlined, and only their labels appear in the
187
+ transcript. Hovering a supported link changes the terminal pointer to a hand and shows a `Click to
188
+ open link` hint in the status bar. A primary click opens it with the system browser; only valid
189
+ HTTP and HTTPS destinations are accepted, and the launcher receives the URL as an argument without
190
+ a shell. OSC 8 metadata is emitted where available, but link activation does not depend on terminal
191
+ OSC 8 support. Inline and fenced code use a subtle panel fill with syntax colors. Emphasis, quotes,
192
+ list markers, tables, dividers and task-list markers use the existing titanium palette. Images
193
+ display their alt text and are not fetched or rendered as image files.
194
+
195
+ ## Blocks and pages
196
+
197
+ In Pi's own terminal UI, [`chrome.ts`](../src/terminal/tui/chrome.ts) gives terminal surfaces one
198
+ of two rule-based shapes, using the 2-cell composer gutter on each side and a dim hint row.
199
+
200
+ - A **block** docks at the bottom like the slash-command list above the composer. It has an amber
201
+ (`warning`) rule, a bold title row with an optional dim note at the right edge (a dialog's
202
+ countdown), the body, a hint row, and a neutral (`dim`) closing rule. It is as tall as its body.
203
+ Approvals, questions, and the `select`, `confirm`, `input` and `editor` dialogs use this shape
204
+ there. OpenTUI renders Harness-managed centered dialogs with the inset header treatment below.
205
+ - A **page** is a header row (title left, position or status right), a neutral rule, the body,
206
+ a neutral rule, and the hint row. `/settings`, `/trajectory`, `/log`, `/permissions`, and the
207
+ `/accounts`, `/plugins` and `/hub` menus are pages. Section labels inside a page are plain bold
208
+ headings, never text set into a rule.
209
+
210
+ `DialogPanel` takes a `variant` (`block` by default). `ui.select` accepts a harness-owned `page`
211
+ option, which Pi's own dialogs ignore, so the same extension code runs in either terminal. Selected
212
+ rows keep the full-width `selectedBg` highlight and `❯` marker the slash-command list uses. Both
213
+ frontends draw that field from the same muted-blue selection palette (`selection.ts`) and use
214
+ explicit high-contrast text on it instead of the accent colour, so a choice reads the same in every
215
+ list. Rules use the theme's `warning` and `dim` colors, so a custom theme restyles them.
216
+
217
+ Each page command owns a separate page and its own tab strip: `/accounts` has Accounts
218
+ and Pools; `/permissions` has Overview and Tools; `/plugins` has Plugins and Trust; `/hub` has
219
+ Catalog and Installed; `/components` has Skills, Prompts and Rules; `/settings` has the available
220
+ settings categories; `/trajectory` has Runs and Events; and `/log` has Diagnostics and Run Events.
221
+ Commands never share one cross-page tab strip. Tab and Shift+Tab move between the current page's
222
+ tabs; in centered dialogs, Left and Right move between those tabs too. Up and Down move through
223
+ rows, while PageUp/PageDown, Home and End move through rows or details. Trajectory keeps `[` and
224
+ `]` for run navigation; its Up and Down arrows select events. The `/model` scope tabs and `/tree`
225
+ filter tabs also respond to Left and Right. Every list and picker places the same `⌕ Type to
226
+ search` row immediately under its title or strip, with its result count at the right. Compact pickers
227
+ such as `/model`, `/tree`, `/resume` and `/fork` do not show a page strip. Escape clears a non-empty
228
+ search before closing. Left and right are passed to the current page and do not switch commands.
229
+
230
+ `/components` browses skills, prompts and rules in the component library. After confirmation, a skill
231
+ or rule is added to the attached Harness scope as a new variant version for future sessions; the current
232
+ terminal stays pinned to the version it started with. Prompts remain browse-only, and terminals without
233
+ a writable scope can browse but cannot add items. These changes go through the extension's private
234
+ control key, so model-issued shell commands cannot add a component.
235
+
236
+ ## Plan mode and thinking keys
237
+
238
+ Use `/plan <brief>` for one read-only planning request. A plan waits outside Pi's native follow-up
239
+ queue until the active response settles, then runs by itself. Later messages remain behind it, even
240
+ when Pi's follow-up mode is `all`. During that run the session narrows to read-only inspection
241
+ (`read`, `grep`, `find`, `ls`), web search/page reading, questions (`ask_user`, `ask_user_question`)
242
+ and recall (history and Wiki reads, `memory_facts`). Providers may mark individual calls as safe for
243
+ research; every other call is blocked before approval. Edits, writes, shell commands, memory writes,
244
+ subagents and connected-app tools remain unavailable. The plan instructions arrive as a
245
+ request-scoped prompt section, which the next ordinary request withdraws.
246
+
247
+ Each mode keeps its own model and effort for the account. Every selection the person makes (the model
248
+ picker, `/effort`, Shift+Up/Down, Ctrl+P) is saved against the mode it was made in, so Shift+Tab switches to that
249
+ mode's model and effort, and a new conversation starts on the normal mode's latest choice. A mode with no
250
+ choice of its own takes normal's, field by field. A resumed conversation keeps the model in its history,
251
+ and a saved model the account cannot use is skipped. The choices live in the account's `choices.json`,
252
+ and the App reads and writes them through `accounts.choices` and `accounts.choose`.
253
+
254
+ A bare `/plan` toggles plan mode, and Shift+Tab cycles between normal and plan mode. Normal, plan
255
+ and Bash are mutually exclusive composer modes. While plan mode is on, each submitted message is sent
256
+ as a plan request through that same queue, and the composer's top and bottom rules take the plan colour.
257
+ Commands still run as commands. Entering Bash with a leading `!` exits plan mode; Shift+Tab from Bash
258
+ switches to plan mode and keeps the draft text. Turning plan mode off returns to normal mode. The old
259
+ on/off/toggle forms are rejected; a bare `/plan` is the switch.
260
+
261
+ When a plan request ends with a complete `<proposed_plan>` block, the terminal shows it as a bordered
262
+ card at the end of the reply, with the text around the block left as ordinary assistant text. A choice
263
+ block then appears above the composer with `Plan ready`, a blank row, then `Implement "<title>"` or
264
+ `Edit the plan`, followed by a blank row and the hint. Up and Down choose, Enter confirms, and Escape
265
+ dismisses it; the block yields to the composer as soon as the draft has text.
266
+ Implement leaves plan mode, so the normal tools and the mode's own model and effort come back, and sends
267
+ `Implement the plan: <title>`; the plan itself is already in the conversation. Edit the plan stays in plan
268
+ mode and focuses the composer, so the next message revises the plan and offers a new choice. A plan run
269
+ that was interrupted, failed, or had work queued behind it is not offered.
270
+
271
+ While typing, a recognized leading slash command uses the selected theme's link color. This
272
+ includes built-in commands, loaded extension and prompt commands, and enabled skill invocations
273
+ written as `/skill:name`. Unknown slash tokens keep the normal text color.
274
+
275
+ SDK session runs receive plan instructions as a dynamic context update, leaving the stable system
276
+ prompt unchanged; their session gate refuses calls outside the read-only set. The standalone
277
+ terminal applies the same instructions and tool restrictions to each plan request. Shift+Up and
278
+ Shift+Down step the thinking level within the levels the model supports, and do not wrap. Use `/thinking` to toggle transcript thinking visibility, or `/thinking show` and `/thinking hide` to set it explicitly. This changes only whether thinking blocks appear in the transcript; it does not change model reasoning or effort, and it shares the Hide thinking setting with Ctrl+T and `/settings`.
279
+
280
+ ## Bash command mode
281
+
282
+ Typing or pasting `!` at the start of the composer enters Bash mode: the first-row prompt marker
283
+ changes from `❯` to `!`, and the `!` and the composer rules use the `bashMode` theme color while the
284
+ command body keeps the normal text color. Continuation rows keep their blank gutter. Entering Bash
285
+ exits plan mode; Shift+Tab from Bash switches to plan mode and preserves the draft. Plan mode colors
286
+ the marker and rules blue; in the normal prompt, the marker matches the divider color. Backspace on
287
+ an empty Bash body returns to the normal prompt. Submitting while a reply is active queues
288
+ the command as a standalone turn; it does not steer the current model request.
289
+
290
+ The terminal extension checks Bash policy and requests approval before using Pi's native
291
+ `executeBash`. Output streams into the transcript while the command runs, so browser-login URLs are
292
+ visible before the command finishes; the running item shows that Escape stops the command. The
293
+ native result is recorded in run activity and session history before the model is prompted to read
294
+ and explain it. This does not attach interactive stdin to the shell. SDK callers may opt into this
295
+ behavior with `SessionRunInput.initialBashCommand`; it is restricted to a new interactive user turn
296
+ and the session runner applies the same Bash gate.
297
+
44
298
  ## Reference and reproduced presentation
45
299
 
46
300
  The reference is **Oh My Pi 18.11.3**, identified from npm and GitHub on 2026-10-17; its release
@@ -55,33 +309,45 @@ not an arbitrary checkout of upstream main. The source repository is
55
309
  | Native `omp` artifact used for observation | `d518310d647d467a2c5c3f2d38e34489a761996d766395c03b37c61a2203d02b` |
56
310
 
57
311
  In the extracted `pi-tui` package, `src/theme/defaults/titanium.json` establishes the titanium
58
- palette and `src/prompt/welcome.ts` establishes the five-row Pi logo, exact diagonal RGB stops
59
- and indexed-color fallback, centered lockup and narrow-width behavior. Harness adapts these
60
- into [`theme.ts`](../src/terminal/tui/theme.ts) and [`welcome.ts`](../src/terminal/tui/welcome.ts),
61
- with its own product name, package version and existing-command tips. The status band and
62
- curved `╰─` input framing are implemented in [`status.ts`](../src/terminal/tui/status.ts) and
63
- [`editor.ts`](../src/terminal/tui/editor.ts). Startup selects the Harness titanium presentation
64
- without rewriting the user's saved theme settings. The shipped OMP light palette is also
65
- available as `light`; native rich components and the status band switch together. Missing
66
- Pi-specific color tokens use documented Harness fallbacks in `theme.ts`.
312
+ palette and its indexed-color fallbacks. Harness adapts these into
313
+ [`theme.ts`](../src/terminal/tui/theme.ts) and
314
+ [`opentui/theme.ts`](../src/terminal/opentui/theme.ts). The OpenTUI status bar shows the project name,
315
+ branch, account, model, context use and current-session input/output totals. Input totals add cache
316
+ reads and exclude cache writes; its `R<percentage>%` hit rate is cache reads divided by total input.
317
+ Token counts below 1,000 show as whole numbers; larger counts use floor-rounded K/M/B suffixes
318
+ without decimals.
319
+
320
+ The OpenTUI composer follows the observed composer of Claude Code 2.1.302, reproduced from its
321
+ visible values; no code is copied. The command palette follows the same borderless convention.
322
+ Startup selects the Harness titanium presentation without rewriting the user's saved theme
323
+ settings. The shipped OMP light palette is also available as `light`; native rich components and
324
+ the OpenTUI chrome switch together. Missing Pi-specific color tokens use documented Harness
325
+ fallbacks in `theme.ts`.
67
326
 
68
327
  The frontend exposes capabilities already present in Harness/Pi. It does not import OMP's
69
328
  agent runtime, tools, providers, MCP implementation, task system or other product features.
70
- Harness-owned composition reuses public Pi Markdown, message, tree/model selector and rich
71
- tool components. Tool diffs, expandable output, images and extension renderers therefore retain
72
- the existing Pi interpretation. This is an implementation of the requested terminal presentation;
73
- complete visual or behavioral parity with every OMP surface has not been established.
329
+ OpenTUI owns screen composition and transcript rendering. Dialogs and extensions continue to use
330
+ Pi's component API through `dialogHost.ts`. Image blocks returned by tools appear as separate
331
+ scrollable image-result entries, rendered inline when `/settings` Show images is on; Markdown
332
+ images continue to show alt text only. This is an implementation of the requested terminal
333
+ presentation; complete visual or behavioral parity with every OMP surface has not been established.
74
334
 
75
335
  Full upstream copyright and MIT permission notices are in [NOTICE.md](../NOTICE.md).
76
336
 
77
337
  ## Runtime compatibility adapter
78
338
 
79
339
  Most integration uses public Pi exports. [`piAdapter.ts`](../src/terminal/tui/piAdapter.ts)
80
- contains the remaining implementation dependencies and requires exactly Pi **1.2.0** before
81
- loading them:
340
+ contains the remaining presentation dependencies and requires exactly Pi **1.2.0** before
341
+ loading them. The shared [`runtime.ts`](../src/pi/runtime.ts) loader imports Pi first, then invokes
342
+ the same HTTP dispatcher hook as Pi's CLI before any Harness Pi runtime is used. This reapplies
343
+ the process `HTTP_PROXY`, `HTTPS_PROXY` and `NO_PROXY` settings after Pi's bundled Undici has
344
+ loaded. Account and model checks, sessions, maintenance, plugin discovery and installation,
345
+ pricing, and the standalone terminal all use this loader. It is process-wide and coalesces
346
+ concurrent initialization.
82
347
 
83
348
  | Internal dependency | Reason |
84
349
  |---|---|
350
+ | `dist/bundle/chunks/chunk-TJXZSVTD.js:configureHttpDispatcher` | Restore Pi's environment-aware HTTP proxy dispatcher after the SDK import |
85
351
  | `dist/extensions/index.js` builtin inventory | Preserve selected `llama.cpp`, `codemode`, `tool-search` and MCP builtins with the CLI's replacement semantics |
86
352
  | `dist/modes/interactive/theme/theme.js:setThemeInstance` | Keep public native rich components on the same active theme as the Harness screen |
87
353
  | `dist/core/tools/renderers/index.js:withBuiltInRenderers` | Preserve existing read/edit/bash/write formatting without replacing tool execution |
@@ -89,7 +355,46 @@ loading them:
89
355
 
90
356
  The adapter is initialized once; its global theme setter and renderer lookup are synchronous
91
357
  thereafter. A Pi dependency upgrade must update this adapter deliberately and rerun the
92
- terminal compatibility tests. These module imports do not instantiate `InteractiveMode`.
358
+ terminal compatibility tests. The dispatcher compatibility check also pins the private Pi bundle
359
+ chunk and fails with a clear error if that hook moves or disappears. A local proxy fixture test
360
+ checks that a Pi HTTP request reaches the configured proxy without contacting an external host.
361
+ These module imports do not instantiate `InteractiveMode`.
362
+
363
+ ## Attachments: images and large pastes
364
+
365
+ Images are sent to the model as image content in the same user message, not as file paths
366
+ (`TerminalRuntime.submit(text, followUp, images)` and `submitPlan(text, images)` pass Pi's
367
+ `PromptOptions.images`). [`attachments.ts`](../src/terminal/opentui/attachments.ts) holds the
368
+ draft's attachments; [`composerMarks.ts`](../src/terminal/opentui/composerMarks.ts) keeps one
369
+ virtual OpenTUI extmark on each label, so the label is drawn in the `attachment` colour and the
370
+ cursor, Backspace and Delete treat it as one unit.
371
+
372
+ - **Cmd+V, drag and drop.** The composer intercepts the terminal's bracketed paste. An empty paste
373
+ (what terminals send when the clipboard holds only an image) reads the clipboard; a paste made
374
+ only of existing image paths — escaped, quoted, `file://` or one unescaped path — attaches those
375
+ files. `Ctrl+V` (and `Alt+V`) on macOS, `Ctrl+V` elsewhere, read the clipboard directly, and a
376
+ `super+v` key from a terminal that forwards Cmd+V does the same.
377
+ - **Labels.** An image shows as `[Image #n]`. A paste of more than three lines or 800 characters
378
+ shows as `[Pasted text #n +L lines]` (or `… N chars]`). Numbering restarts after each send.
379
+ - **Deleting.** Backspace or Delete next to a label removes it whole. A word or line delete that
380
+ cuts into a label removes the rest of it, and the attachment goes with it.
381
+ - **Sending.** Pasted text is put back in place of its label; image labels stay in the text so the
382
+ model can refer to "Image #1", and the images follow in label order. Sent user messages colour
383
+ `[Image #n]` the same way. Images are resized with Pi's `resizeImage`; one that cannot be
384
+ shrunk and is over 5 MB is refused.
385
+ - **Refusals.** A model whose `input` lacks `image` refuses the attach with a notice naming the
386
+ model. Bash mode and plugin editors take no images. A slash command or Bash command sent with
387
+ images runs without them, with a warning. Alt+Up (dequeue) restores queued text and drops
388
+ queued images with a warning.
389
+
390
+ Finder-copied file paths are read before clipboard image pixels. On macOS, `.heic` and `.heif`
391
+ files are converted with `/usr/bin/sips` to private temporary PNGs, preserving the copied path
392
+ order and leaving the originals untouched; temporary files are removed when the terminal shuts
393
+ down. Clipboard image pixels go through Pi's native adapter, which reads PNG/TIFF on macOS and
394
+ normalizes TIFF to PNG. `python3 scripts/verify-terminal.py --attachments-only` checks a dropped
395
+ image path, label colour, collapsed pastes, whole-label Backspace and Alt+Backspace, and that the
396
+ loopback provider receives an image part and the expanded text. Whether a given emulator sends an
397
+ empty bracketed paste for an image-only clipboard has to be checked by hand in that emulator.
93
398
 
94
399
  ## Accounts, history and resource trust
95
400
 
@@ -122,12 +427,22 @@ second key once with `control.claim`, before plugin code loads. [`control.ts`](.
122
427
  retains it in a process-local promise shared with the bridge; it is never written to disk or
123
428
  placed in the environment. It survives `/new`, resume, fork and reload.
124
429
 
125
- The private key is required for `terminal.pending`, `terminal.approve`, `terminal.answer`,
126
- `terminal.draft`, `terminal.interrupt` and `terminal.resources`, as well as existing account and
127
- plugin mutations. A model-spawned shell with only the environment token cannot answer its own
128
- pending questions or approvals. The application renders decisions obtained from the existing
430
+ The private key is required for `terminal.policy`, `terminal.approval`, `terminal.pending`,
431
+ `terminal.approve`, `terminal.answer`, `terminal.draft`, `terminal.interrupt` and
432
+ `terminal.resources`, as well as existing account and plugin mutations. A model-spawned shell with
433
+ only the environment token cannot submit policy or approval decisions, change permissions, or
434
+ answer its own pending questions. The application renders decisions obtained from the existing
129
435
  controller and returns the person's answer through these calls.
130
436
 
437
+ Approval prompts offer **Allow once**, **Always allow this tool everywhere** when the host policy
438
+ marks the decision rememberable, and **Deny**. A tool grant covers every call with that tool name
439
+ in Pi terminal sessions using this device's local Harness state directory; for example, Bash grants
440
+ cover every Bash command. `/permissions` lists those grants and lets the person revoke them. Its
441
+ Full Permission switch approves future eligible prompts across those terminal sessions, asks for
442
+ confirmation when enabled, and is off by default. Neither choice approves an already-pending
443
+ request. Hard denials and disabled tools remain enforced; human-only requests stay manual unless
444
+ the host explicitly permits Full Permission for them. Chat approvals keep their separate profile.
445
+
131
446
  The editor sends exact draft state to `terminal.draft`; host delivery waits for that state
132
447
  instead of overwriting a draft. Interruption resolves pending socket-backed questions and
133
448
  approvals in the run registry before awaiting Pi abort. Disposal uses that order too, avoiding
@@ -136,12 +451,28 @@ clears controller readiness and stops that session's poller; the replacement's `
136
451
  restores readiness while retaining the same process control claim.
137
452
 
138
453
  The bridge exposes the shared `ask_user` batch tool alongside the existing single-question
139
- `ask_user_question` contract. Registry events project the actual batch IDs, order, summaries,
140
- choices and descriptions into the terminal inbox. The frontend stages answers locally and
141
- submits them together through protected `terminal.answers`; the registry validates the entire
142
- batch before resolving any question. Escape interrupts a pending question; cancelling optional
143
- text entry returns to the choices and preserves selections. Disappearing requests abort their
144
- open dialogs. Labels are numbered so a real choice cannot collide with a dialog action.
454
+ `ask_user_question` contract. Every question must include at least one choice and at least one
455
+ recommended choice; recommendations remain visual and never preselect. Choice-based questions also
456
+ retain a free-text “Something else” answer. A pending question appears in a flat block immediately above the
457
+ composer, not in a modal. It has only a muted top divider and separates its hint from the content by
458
+ one blank line. The block shows one batch question at a time with previous/next navigation and batch
459
+ progress, choices and descriptions, a numbered free-text answer row after the choices, and a Continue
460
+ or Skip action. Selected choices fill the whole row with subtle dark green; Continue and Submit uses
461
+ a green-filled button, while Skip remains neutral. The regular composer remains below it for a direct message to the waiting session.
462
+ Tab and Shift+Tab move focus through the available controls; Tab from a focused selected choice opens
463
+ its inline note field. In multi-select questions, Tab can open a note for each selected choice; notes
464
+ are submitted by choice label and cleared when that choice is deselected. While the block is active,
465
+ Tab takes precedence over the normal thinking and plan-mode shortcuts. Up and Down navigate choices;
466
+ Left and Right navigate the batch while choices or the action are focused. Enter selects a choice,
467
+ activates the focused action, or submits the answer or note field. Escape interrupts the pending
468
+ question. Press `x` from the choices or action to collapse the block; Tab reopens it.
469
+
470
+ Recommended choices appear first with a warning-colored marker, without changing their labels or
471
+ preselecting them; every question requires at least one recommendation. A single-choice question
472
+ allows at most one recommendation, while multi-select questions may recommend several. The frontend stages each answer locally and submits the complete
473
+ batch together through protected `terminal.answers`; a single question uses `terminal.answer`. The
474
+ registry validates answers before resolving the request. If a request disappears, its block and
475
+ staged answers are discarded.
145
476
 
146
477
  Plugin UI methods carry a generation guard, including methods a plugin retained before an
147
478
  `await`. Session replacement, reload and disposal revoke the old generation. Outgoing native
@@ -149,16 +480,81 @@ event subscriptions and custom transcript components detach before native invali
149
480
  Cleanup failures cannot prevent terminal restoration. Fatal asynchronous errors restore the
150
481
  terminal and exit with failure; startup failures and suspend/resume use the same lifecycle.
151
482
 
152
- The command registry supplies help and completion for every pinned Pi built-in command name,
153
- plus Harness commands supplied by the bridge. `/trust` opens the existing protected code-review
154
- workflow in `/plugins`; trust changes require a freshly prepared terminal. `/bug` opens a
155
- reviewable Harness issue draft after confirmation, without attaching history. `/changelog`
156
- reads bundled Harness change notes. `/reload` also applies the isolated account's edited
157
- keyboard bindings through the public TUI manager.
483
+ The command registry supplies help and completion for Harness commands, loaded extensions,
484
+ prompts and enabled skills. `/plugins` includes the protected code trust workflow. A plugin with
485
+ settings has a **Settings** row under it on the Plugins tab; Enter opens its settings as a subpage
486
+ (`Plugins › <title>`), where Enter flips an on/off setting or asks for a whole number inside the
487
+ setting's range, and Esc returns to the list. Settings are saved with `plugins.configure` and read
488
+ when the plugin next uses them, so they need no restart. The standalone
489
+ terminal no longer has separate `/login`, `/trust`, `/bug`, `/changelog`, `/share`, `/scoped-mode` or
490
+ `/import` commands. `/btw <question>` asks a short side question in a separate tool-free session. Its block puts the question after `/btw`, shows the normal animated spinner while answering, and separates the answer and hint by one blank row; it has no status labels. Escape closes the block without interrupting the main reply, and `/btw` also dismisses it. `/stop` interrupts the current reply. The `/accounts` page handles sign-in
491
+ and sign-out. `/components` browses reusable skills, prompts and rules; a confirmed skill or rule addition
492
+ creates a variant version for future sessions while the current terminal keeps its pinned version. `/reload` applies trusted resource and keybinding changes.
493
+
494
+ `/trajectory` opens the newest recorded run for the current native conversation; `/trajectory <run-id>`
495
+ opens a selected run from that conversation. Tab switches between Runs and Events; `[` and `]` change
496
+ runs, up/down selects recorded events, PageUp/PageDown scrolls event details, and `c` copies the
497
+ selected event. Active runs refresh while the overlay is open. The protected terminal socket scopes both the run list and event
498
+ reads to the current terminal and native session file.
499
+
500
+ `/log` opens a centered page dialog with separate Harness diagnostics and current-conversation
501
+ run-event views. The diagnostic file is read at its captured size in bounded socket chunks. Tab/Shift+Tab
502
+ switches views; arrows, PageUp/PageDown, Home and End scroll; Escape closes. Fetch
503
+ diagnostics retain available error stacks and safe request metadata, while the viewer redacts secrets
504
+ and URL queries and omits response bodies, prompts and message contents. Embedded hosts without a
505
+ `harness.log` still show the conversation's recorded run events.
506
+
507
+ ## Input performance profile
508
+
509
+ `npm run profile:terminal-latency` (`scripts/profile-terminal-latency.py`) types into the real
510
+ terminal in a PTY and times each key until it is visible on a virtual screen, while idle, after a
511
+ long tool history, while a reply streams, and with an approval or question waiting. It can run pure
512
+ Pi and opencode the same way for comparison; method and results are in
513
+ [EXP-0002](experiments/EXP-0002-opentui-typing-latency/results.md).
514
+ `npm run profile:terminal-input` still measures the local draft-control socket on its own.
515
+
516
+ How the frontend keeps typing fast:
517
+
518
+ - **Rendering on demand.** The renderer is not started in continuous mode, so a key is drawn as soon
519
+ as it arrives instead of waiting for the next fixed tick; `maxFps` is 120.
520
+ - **Fine-grained view.** `root.tsx` keeps the application view in a Solid store and reconciles each
521
+ update by item id, so a streamed delta updates one markdown block in place (`streaming` is passed
522
+ to `<markdown>`) and a keystroke does not redraw the transcript.
523
+ - **Coalesced background updates.** `change()` publishes runtime events at most once per frame,
524
+ 33 ms while a run is active. A person's input (keys, the composer, the question dock) publishes at
525
+ once and synchronously, in order with the composer's own events.
526
+ - **Draft read at key time.** The composer reports its text in a microtask, after all keys of one
527
+ input chunk; the root reads the composer before each key so Enter never sends a stale draft.
528
+ - **Cached derived data.** Finished messages keep their transcript items until their position or tool
529
+ results change; session statistics refresh at most every 250 ms during a run.
530
+ - **Kept connections.** Session-socket requests ask to `keep` their connection, so the two 100 ms
531
+ polls and per-key draft updates reuse a connection instead of opening one each.
532
+ - **No swallowed keys.** A character the question dock does not use moves focus to the composer and
533
+ is typed there.
158
534
 
159
535
  ## Verification and remaining limits
160
536
 
161
- Harness typecheck, **419 passing tests / two platform skips**, build and standalone proof
537
+ Release-candidate verification, 2026-10-19: clean `npm ci` and `npm run ci` passed—541 tests
538
+ (two skipped), typecheck, build and standalone proof. In the sibling App, typecheck, layer check and
539
+ sidecar build passed; its renderer tests passed (561), but one sidecar screenshot assertion and two
540
+ Rust tests failed in the broader in-progress App worktree. Those failures do not touch the Harness
541
+ release files; the App changes were not included in this package.
542
+
543
+ OpenTUI verification, 2026-10-20: the OpenTUI unit tests cover the transcript model, palette,
544
+ Bash mode, dialog geometry, composer, theme and component host. Targeted PTY probes against the
545
+ production bundle cover centered page dialogs at 40×20, 80×24 and 120×40, palette ranking, and
546
+ Bash mode through its approval gate; see
547
+ [docs/evidence/terminal-2026-10-20-console-tui](evidence/terminal-2026-10-20-console-tui/README.md).
548
+ The full `scripts/verify-terminal.py` run under OpenTUI stops at `/settings` because the verifier
549
+ sends the command and Return in one burst; the targeted probes send them separately. Run
550
+ `python3 scripts/verify-terminal.py --sizes 80x24 --click-focus-only` to check composer focus from
551
+ the empty welcome area, transcript text and blank transcript space in an isolated PTY.
552
+
553
+ Earlier fullscreen-layout verification, 2026-10-18, covered the removed Pi frontend's dock,
554
+ notice clipping, regular flow and exit copy. It is retained as history in
555
+ [docs/evidence/terminal-2026-10-18-fullscreen](evidence/terminal-2026-10-18-fullscreen/verification.json).
556
+
557
+ Earlier verification, before the fullscreen layout: Harness typecheck, **419 passing tests / two platform skips**, build and standalone proof
162
558
  passed on 2026-10-17. A final cleanup-order adjustment was rechecked with all **91 frontend
163
559
  tests**, typecheck, build and standalone proof. Coverage includes the real isolated persistent SDK/socket boundary,
164
560
  exact history scope and symlink rejection, resource-trust refusal before new/reload, event and
@@ -191,7 +587,7 @@ Already-running sessions need to exit and relaunch to load the replacement.
191
587
  A direct REA comparison of the pinned OMP executable and Harness at 80×24 captures startup and
192
588
  settings without output truncation; both exit 0. The [readable comparison](evidence/terminal-2026-10-17-followup/reference-comparison.md)
193
589
  retains exact frame/evidence IDs. It established matching centered welcome/composer geometry,
194
- rounded settings framing and the need for flat settings rows at 80 columns; the latter was
590
+ rounded settings framing (since replaced by [pages](#blocks-and-pages)) and the need for flat settings rows at 80 columns; the latter was
195
591
  corrected using the shipped SettingsList's minimum editable-pane width. Product lockups, tips,
196
592
  capability tabs, setting names, paths and unavailable-model guidance differ deliberately.
197
593
  This is bounded visual review, not proof of equivalence for every OMP surface.
@@ -210,11 +606,12 @@ a successful response or tool execution. Harness persisted the failed run and re
210
606
  terminal; the source sign-in file was unchanged and the disposable credentials were deleted.
211
607
  The [live report and capture](evidence/terminal-2026-10-17-followup/live-codex/README.md) retain
212
608
  this quota failure explicitly. Successful live streaming/tool acceptance remains open until
213
- account capacity is available. GitHub gist publication, actual OS clipboard/image transfer,
214
- Windows behavior and every terminal emulator remain unverified. Rich image/diff rendering and clipboard adapters have
215
- focused compatibility tests; that does not establish OS interaction. These working-tree changes
216
- are not a published release and the complete plan's acceptance remains open while required
217
- integration/provider evidence is outstanding.
609
+ account capacity is available. GitHub gist publication, actual OS clipboard pixel transfer,
610
+ Windows behavior and every terminal emulator remain unverified. HEIC/HEIF file staging has focused
611
+ conversion tests; that does not establish Finder or Warp OS interaction. Rich image/diff rendering
612
+ and clipboard adapters have focused compatibility tests; that does not establish OS interaction. These changes shipped in
613
+ `@xingular/harness` 2.0.0 (commit `44471bc`), while the complete plan's acceptance remains
614
+ open pending the required integration and provider evidence.
218
615
 
219
616
  To reproduce the controlled scenario after building:
220
617
 
@@ -252,3 +649,23 @@ inherit that retained ledger.
252
649
  - The portable OMP/Harness runtime evidence IDs and selected frame numbers are recorded in
253
650
  the readable comparison and manifest linked above. An earlier OMP capture sent input before
254
651
  startup completed; it is retained as incomplete evidence and excluded from the comparison.
652
+
653
+ ## Agent-managed session names
654
+
655
+ Agents can use `session_name({ name: string })` to name meaningful work early and revise
656
+ its name when the objective changes. Names submitted by agents are short imperative
657
+ sentences with at most six words. The agent may revise a manual name; `/name` remains
658
+ available and manual names have no new word limit. Pi stores the name in native history,
659
+ so resuming the same conversation restores it without another model request.
660
+
661
+ The working line shows `Working (2m, 50 tok/s) – Add web browser integrations`; the name
662
+ also stays on the completion line. Unnamed sessions have no separator, and narrow terminals
663
+ truncate trailing text. Renaming refreshes the line through Pi's existing metadata event.
664
+
665
+ ## `/doctor`
666
+
667
+ Checks accounts/models, tools, MCP, plugins/skills, variant/prompt validity, runtime assets, storage
668
+ and startup recovery. Every finding says whether it is local readiness or live verification.
669
+ `r` refreshes, `t` retries one local finding, `l` selects live checks, `c` cancels, arrows scroll,
670
+ and Escape closes/cancels. Live checks show their costs and isolated resources before confirmation.
671
+ Providers without diagnostic callbacks are reported unverified. See [Doctor](doctor.md).