@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,207 +0,0 @@
1
- {
2
- "passed": true,
3
- "implementation": "production standalone CLI + real Pi SDK + loopback OpenAI SSE transport",
4
- "cli": "/Users/tanny/Documents/Projects/Xingular/Xingular Agent/Harness/dist/cli.js",
5
- "cliSha256": "2f5df943661a1e89440d0e81d59cd4a5bdb7aaf087a2a930e232b6743d5db093",
6
- "verifierSha256": "6b7652f0093b12a37bd975fcffa7accc0f34d627022397b7e45923be270abc85",
7
- "provider": "controlled loopback OpenAI-compatible streaming transport; no external model requests or user credentials",
8
- "requestCount": 39,
9
- "profiles": [
10
- {
11
- "size": "40x20",
12
- "checks": [
13
- "welcome and real configured model",
14
- "actual settings tabs, section focus, keyboard search/control and Escape return",
15
- "command autocomplete and real accounts selector",
16
- "suspend/resume restores cooked/raw terminal modes and command input",
17
- "Unicode, real streaming/thinking/read/bash/approval/question, expansion, resizing and scrolling",
18
- "trusted plugin custom overlay, widget, status and disposal",
19
- "grouped question progress and atomic choice/text answers through real registry",
20
- "approval deny and Escape cancellation prevent actual tool execution",
21
- "question Escape cancellation settles pending tools and interrupts run",
22
- "new session, explicit scoped resume and session naming",
23
- "actual stream cancellation and interrupted run record",
24
- "explicit account switching, process restart and real run on newly pinned account",
25
- "fatal asynchronous plugin failure exits 1 and restores terminal modes",
26
- "plugin startup failure exits 1 and restores terminal modes"
27
- ],
28
- "persistedRunCount": 7,
29
- "exitCode": 0,
30
- "termiosRestored": true,
31
- "bracketedPasteDisabled": true,
32
- "cursorShown": true,
33
- "fatalCleanup": {
34
- "exitCode": 1,
35
- "termiosRestored": true,
36
- "bracketedPasteDisabled": true,
37
- "cursorShown": true
38
- },
39
- "startupCleanup": {
40
- "exitCode": 1,
41
- "termiosRestored": true,
42
- "bracketedPasteDisabled": true,
43
- "cursorShown": true
44
- }
45
- },
46
- {
47
- "size": "80x24",
48
- "checks": [
49
- "welcome and real configured model",
50
- "actual settings tabs, section focus, keyboard search/control and Escape return",
51
- "command autocomplete and real accounts selector",
52
- "suspend/resume restores cooked/raw terminal modes and command input",
53
- "Unicode, real streaming/thinking/read/bash/approval/question, expansion, resizing and scrolling",
54
- "trusted plugin custom overlay, widget, status and disposal",
55
- "grouped question progress and atomic choice/text answers through real registry",
56
- "approval deny and Escape cancellation prevent actual tool execution",
57
- "question Escape cancellation settles pending tools and interrupts run",
58
- "new session, explicit scoped resume and session naming",
59
- "actual stream cancellation and interrupted run record",
60
- "explicit account switching, process restart and real run on newly pinned account",
61
- "fatal asynchronous plugin failure exits 1 and restores terminal modes",
62
- "plugin startup failure exits 1 and restores terminal modes"
63
- ],
64
- "persistedRunCount": 7,
65
- "exitCode": 0,
66
- "termiosRestored": true,
67
- "bracketedPasteDisabled": true,
68
- "cursorShown": true,
69
- "fatalCleanup": {
70
- "exitCode": 1,
71
- "termiosRestored": true,
72
- "bracketedPasteDisabled": true,
73
- "cursorShown": true
74
- },
75
- "startupCleanup": {
76
- "exitCode": 1,
77
- "termiosRestored": true,
78
- "bracketedPasteDisabled": true,
79
- "cursorShown": true
80
- }
81
- },
82
- {
83
- "size": "120x40",
84
- "checks": [
85
- "welcome and real configured model",
86
- "actual settings tabs, section focus, keyboard search/control and Escape return",
87
- "command autocomplete and real accounts selector",
88
- "suspend/resume restores cooked/raw terminal modes and command input",
89
- "Unicode, real streaming/thinking/read/bash/approval/question, expansion, resizing and scrolling",
90
- "trusted plugin custom overlay, widget, status and disposal",
91
- "grouped question progress and atomic choice/text answers through real registry",
92
- "approval deny and Escape cancellation prevent actual tool execution",
93
- "question Escape cancellation settles pending tools and interrupts run",
94
- "new session, explicit scoped resume and session naming",
95
- "actual stream cancellation and interrupted run record",
96
- "explicit account switching, process restart and real run on newly pinned account",
97
- "fatal asynchronous plugin failure exits 1 and restores terminal modes",
98
- "plugin startup failure exits 1 and restores terminal modes"
99
- ],
100
- "persistedRunCount": 7,
101
- "exitCode": 0,
102
- "termiosRestored": true,
103
- "bracketedPasteDisabled": true,
104
- "cursorShown": true,
105
- "fatalCleanup": {
106
- "exitCode": 1,
107
- "termiosRestored": true,
108
- "bracketedPasteDisabled": true,
109
- "cursorShown": true
110
- },
111
- "startupCleanup": {
112
- "exitCode": 1,
113
- "termiosRestored": true,
114
- "bracketedPasteDisabled": true,
115
- "cursorShown": true
116
- }
117
- }
118
- ],
119
- "captures": [
120
- {
121
- "file": "40x20-welcome.ansi.gz",
122
- "kind": "actual PTY cumulative raw ANSI stream",
123
- "columns": 40,
124
- "rows": 20,
125
- "rawBytes": 3085,
126
- "rawSha256": "5ad9d6b7743730c00331865a713ade17a96d8a82254073eff8f7123f78ba0dfd",
127
- "archiveBytes": 647,
128
- "archiveSha256": "4e1d09e9e2b8ab6dd716c27342cb427e6d327b4517b2d5a1f9d6abe507ae6150"
129
- },
130
- {
131
- "file": "40x20-settings-interaction.ansi.gz",
132
- "kind": "actual PTY cumulative raw ANSI stream",
133
- "columns": 40,
134
- "rows": 20,
135
- "rawBytes": 10579,
136
- "rawSha256": "6e8cb197fd6444abd5b34500d14d36def96d945f6ffe75b70c107511a2fc6f92",
137
- "archiveBytes": 1250,
138
- "archiveSha256": "33227bf1354591624311e69f016862cea964aeb0d2cf6af0274bc8c49b6aa39c"
139
- },
140
- {
141
- "file": "40x20-settings-keyboard.ansi.gz",
142
- "kind": "actual PTY cumulative raw ANSI stream",
143
- "columns": 40,
144
- "rows": 20,
145
- "rawBytes": 12779,
146
- "rawSha256": "6071b778e316c86fdc6976ac024faffcf75221ba1043dfbd524e32cfcdff5e79",
147
- "archiveBytes": 1387,
148
- "archiveSha256": "722b555638b343520b7896527fb9287c71a2a9ba55e9a2f7c1ea573058db3a22"
149
- },
150
- {
151
- "file": "80x24-approval-0.ansi.gz",
152
- "kind": "actual PTY cumulative raw ANSI stream",
153
- "columns": 80,
154
- "rows": 24,
155
- "rawBytes": 63082,
156
- "rawSha256": "d182c53020bc8f9dae3b3f910ab78bbccae229b41fb927983b26b9352e13c7d1",
157
- "archiveBytes": 5420,
158
- "archiveSha256": "c00dd2d226ff8d0d8455311b903791dff1a4fc2b9fc4921ffc08837290570c99"
159
- },
160
- {
161
- "file": "80x24-question.ansi.gz",
162
- "kind": "actual PTY cumulative raw ANSI stream",
163
- "columns": 80,
164
- "rows": 24,
165
- "rawBytes": 73627,
166
- "rawSha256": "50c7fc4da8748ddcd2868007cf944e2294a9d55d035c60ad30cbe8820068682e",
167
- "archiveBytes": 5834,
168
- "archiveSha256": "d5371974389a6f99758d3d4e3bc820a69a48aa05fe344b3d0f4d3143cdd44298"
169
- },
170
- {
171
- "file": "80x24-plugin-light.ansi.gz",
172
- "kind": "actual PTY cumulative raw ANSI stream",
173
- "columns": 120,
174
- "rows": 30,
175
- "rawBytes": 118891,
176
- "rawSha256": "089d74da63cf763e1a06faf0264966d5b8d788518eda880ed91fb556fe844ab5",
177
- "archiveBytes": 7618,
178
- "archiveSha256": "55fe9f7742387b7e10692711daef697fe1f55af76486554c40290eb039c4a1fa"
179
- },
180
- {
181
- "file": "80x24-question-batch.ansi.gz",
182
- "kind": "actual PTY cumulative raw ANSI stream",
183
- "columns": 120,
184
- "rows": 30,
185
- "rawBytes": 169983,
186
- "rawSha256": "aee0560c4fb6bb878d187827ab8c40ceee81dda1022a98f663f8bb079e9bc2f6",
187
- "archiveBytes": 8742,
188
- "archiveSha256": "11ae7c4c7b3991014dbef17d126608104661c0776198e51e519ba35ad557dd35"
189
- },
190
- {
191
- "file": "120x40-completed-transcript.ansi.gz",
192
- "kind": "actual PTY cumulative raw ANSI stream",
193
- "columns": 120,
194
- "rows": 40,
195
- "rawBytes": 140149,
196
- "rawSha256": "abdbba2e7db4a94d25b82826539e1acbb9e59be7bb9d15167eeeee8f3838644d",
197
- "archiveBytes": 7935,
198
- "archiveSha256": "2f79e0637ed13a1fbf69d237eb2e644939fd4e3bb5cb257e5b6910fb19981012"
199
- }
200
- ],
201
- "limits": [
202
- "The AgentSession, frontend, native tools, authorization and run writer are production code.",
203
- "The controlled local transport supplies deterministic model responses and usage fixtures.",
204
- "These functional checks do not establish external provider OAuth/service availability or visual equivalence to OMP.",
205
- "Each compressed capture is a cumulative actual ANSI stream from PTY startup through the named interaction. Replay at its recorded dimensions."
206
- ]
207
- }
@@ -1,333 +0,0 @@
1
- import { existsSync, lstatSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, readlinkSync, rmdirSync, statSync, writeFileSync } from 'node:fs'
2
- import { homedir, tmpdir } from 'node:os'
3
- import { join } from 'node:path'
4
- import { expect, test } from 'vitest'
5
- import type { ModelRuntime } from '@earendil-works/pi-coding-agent'
6
-
7
- import { Bus, type Notice } from '../core/bus'
8
- import { Accounts, classifyMessage } from './accounts'
9
- import { assertIsolated, configDir, ensureHome, ensureSharedDir, launchEnv, nativeConfig, sharedDir } from './env'
10
- import { fileSecretStore, memorySecretStore } from './secrets'
11
- import { addAccount, audit, deriveHealth, emptyState, loadRegistry, loadState, resolve, saveRegistry, updateState, type Issue } from './store'
12
-
13
- const temp = () => mkdtempSync(join(tmpdir(), 'harness-accounts-'))
14
- const ago = (ms: number): string => new Date(Date.now() - ms).toISOString()
15
- const HOUR = 3_600_000
16
-
17
- function service(dir = temp()) {
18
- const secrets = memorySecretStore()
19
- const notices: Notice[] = []
20
- const bus = new Bus()
21
- bus.on((notice) => void notices.push(notice))
22
- return { dir, secrets, notices, accounts: new Accounts({ dir, secrets, bus }) }
23
- }
24
-
25
- function loginService(login: (interaction: {
26
- signal: AbortSignal
27
- notify: (notification: Record<string, unknown>) => void
28
- prompt: (prompt: { type: string; message: string; placeholder?: string; options?: unknown; signal?: AbortSignal }) => Promise<string>
29
- }) => Promise<void>) {
30
- const dir = temp()
31
- const secrets = memorySecretStore()
32
- const notices: Notice[] = []
33
- const bus = new Bus()
34
- bus.on((notice) => void notices.push(notice))
35
- let loginOptions: { getDeviceId?: () => string } | undefined
36
- let loginCalls = 0
37
- const runtime = {
38
- login: (_provider: string, _method: string, interaction: Parameters<typeof login>[0], options?: { getDeviceId?: () => string }) => {
39
- loginCalls += 1
40
- loginOptions = options
41
- return login(interaction)
42
- }
43
- }
44
- class LoginAccounts extends Accounts {
45
- override runtime(account: Parameters<Accounts['runtime']>[0]): Promise<ModelRuntime> {
46
- void account
47
- return Promise.resolve(runtime as unknown as ModelRuntime)
48
- }
49
- }
50
- const accounts = new LoginAccounts({ dir, secrets, bus })
51
- const account = accounts.create('Login test', 'subscription').accounts[0]
52
- return { accounts, account, notices, loginOptions: () => loginOptions, loginCalls: () => loginCalls }
53
- }
54
-
55
- async function waitFor(predicate: () => boolean): Promise<void> {
56
- for (let attempt = 0; attempt < 100; attempt++) {
57
- if (predicate()) return
58
- await new Promise((resolve) => setTimeout(resolve, 5))
59
- }
60
- throw new Error('Timed out waiting for the account operation.')
61
- }
62
-
63
- test('OpenAI login uses one persisted Harness installation device ID across accounts', async () => {
64
- const { accounts, account, loginOptions, loginCalls } = loginService(async () => {})
65
- const deviceId = await accounts.installationDeviceId()
66
- const second = accounts.create('Second account', 'subscription').accounts.find((item) => item.id !== account.id)!
67
-
68
- await accounts.loginStart(account.id, 'openai', 'oauth')
69
- await waitFor(() => loginCalls() === 1)
70
- expect(loginOptions()?.getDeviceId?.()).toBe(deviceId)
71
-
72
- await accounts.loginStart(second.id, 'openai', 'oauth')
73
- await waitFor(() => loginCalls() === 2)
74
- expect(loginOptions()?.getDeviceId?.()).toBe(deviceId)
75
- expect(JSON.parse(readFileSync(join(sharedDir(accounts.dir), 'settings.json'), 'utf8')).deviceId).toBe(deviceId)
76
- expect(deviceId).toMatch(/^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i)
77
- })
78
-
79
- test('device-code sign-in progress survives listener detachment and is available from status', async () => {
80
- const { accounts, account, notices } = loginService((interaction) => new Promise<void>((_resolve, reject) => {
81
- interaction.notify({ type: 'device_code', userCode: 'ABCD-EFGH', verificationUri: 'https://example.test/device' })
82
- interaction.signal.addEventListener('abort', () => reject(new Error('aborted')), { once: true })
83
- }))
84
-
85
- const { loginId } = await accounts.loginStart(account.id, 'openai-codex', 'oauth')
86
- await waitFor(() => (accounts.loginStatus(account.id)?.events.length ?? 0) > 0)
87
- const detached = accounts.loginStatus(account.id)
88
- expect(detached).toMatchObject({ loginId, status: 'running', events: [{ type: 'device_code', userCode: 'ABCD-EFGH' }] })
89
- expect(notices.find((notice) => notice.type === 'accounts.loginEvent')).toMatchObject({ revision: 1, loginId })
90
-
91
- // Asking again models a renderer returning to Accounts while the Harness stays alive.
92
- expect(accounts.loginStatus(account.id)).toEqual(detached)
93
- accounts.loginCancel(account.id, loginId)
94
- await waitFor(() => accounts.loginStatus(account.id)?.status === 'cancelled')
95
- const ended = accounts.loginStatus(account.id)
96
- expect(ended).toMatchObject({ loginId, status: 'cancelled', events: [], prompt: null, success: false })
97
- expect(JSON.stringify(ended)).not.toContain('ABCD-EFGH')
98
- })
99
-
100
- test('login status exposes the active prompt but never retains its response after completion', async () => {
101
- const { accounts, account, notices } = loginService(async (interaction) => {
102
- const value = await interaction.prompt({ type: 'secret', message: 'Enter the one-time value' })
103
- expect(value).toBe('private-response')
104
- })
105
-
106
- const { loginId } = await accounts.loginStart(account.id, 'provider-with-prompt', 'oauth')
107
- await waitFor(() => accounts.loginStatus(account.id)?.prompt !== null)
108
- const waiting = accounts.loginStatus(account.id)
109
- expect(waiting).toMatchObject({ loginId, status: 'running', prompt: { type: 'prompt', prompt: { type: 'secret' } } })
110
- const promptId = String(waiting?.prompt?.promptId)
111
- accounts.loginRespond(loginId, promptId, 'private-response')
112
- await waitFor(() => accounts.loginStatus(account.id)?.status === 'completed')
113
- const ended = accounts.loginStatus(account.id)
114
- expect(ended).toMatchObject({ loginId, status: 'completed', success: true, events: [], prompt: null })
115
- expect(JSON.stringify(ended)).not.toContain('private-response')
116
- expect(notices.filter((notice) => notice.type === 'accounts.loginEvent' || notice.type === 'accounts.login').map((notice) => notice.revision)).toEqual([1, 2, 3])
117
- })
118
-
119
- test('health reflects sign-in, errors and limits', () => {
120
- const state = { ...emptyState(), signedIn: true }
121
- expect(deriveHealth(state)).toBe('ok')
122
- state.limits.push({ id: '5h', label: '', usedPercent: 100, resetsAt: ago(-HOUR) })
123
- expect(deriveHealth(state)).toBe('limited')
124
- state.limits[0].resetsAt = ago(HOUR)
125
- expect(deriveHealth(state)).toBe('ok')
126
- state.lastError = { category: 'auth_expired', message: '', at: '', resetsAt: null }
127
- expect(deriveHealth(state)).toBe('auth_expired')
128
- state.lastError = null
129
- state.signedIn = false
130
- expect(deriveHealth(state)).toBe('signed_out')
131
- })
132
-
133
- test('a limit error without a reset time expires', () => {
134
- const issue = (at: number, resetsAt: number | null): Issue => ({ category: 'quota', message: 'usage limit', at: ago(at), resetsAt: resetsAt === null ? null : ago(-resetsAt) })
135
- const state = { ...emptyState(), signedIn: true }
136
- expect(deriveHealth({ ...state, lastError: issue(5 * 60_000, null) })).toBe('limited')
137
- expect(deriveHealth({ ...state, lastError: issue(96 * HOUR, null) })).toBe('ok')
138
- expect(deriveHealth({ ...state, lastError: issue(96 * HOUR, HOUR) })).toBe('limited')
139
- })
140
-
141
- test('resolve prefers explicit, then pool, then default, and never skips silently', () => {
142
- const dir = temp()
143
- expect(() => resolve(dir)).toThrow('Add a Pi account first.')
144
- const first = addAccount(dir, 'A', 'subscription')
145
- const second = addAccount(dir, 'B', 'subscription')
146
- expect(resolve(dir).id).toBe(first.id)
147
- expect(resolve(dir, second.id).id).toBe(second.id)
148
- // An account of a provider the harness no longer runs is kept in the file and never chosen.
149
- const registry = loadRegistry(dir)
150
- registry.accounts.push({ id: 'legacy', provider: 'codex', label: 'Old', authKind: 'subscription', createdAt: '' })
151
- registry.pools.push({ id: 'p', provider: 'pi', label: 'Work', accountIds: [first.id, second.id] })
152
- saveRegistry(dir, registry)
153
- expect(() => resolve(dir, 'legacy')).toThrow('another provider')
154
- expect(loadRegistry(dir).accounts).toHaveLength(3)
155
-
156
- updateState(dir, first.id, (state) => void (state.signedIn = false))
157
- expect(resolve(dir, null, 'p').id).toBe(second.id)
158
- updateState(dir, second.id, (state) => void (state.lastError = { category: 'auth_expired', message: '', at: '', resetsAt: null }))
159
- expect(() => resolve(dir, null, 'p')).toThrow('Every account in Work is unavailable.')
160
- })
161
-
162
- function walk(dir: string): string[] {
163
- return readdirSync(dir).flatMap((name) => (statSync(join(dir, name)).isDirectory() ? walk(join(dir, name)) : [join(dir, name)]))
164
- }
165
-
166
- test('audit and state never hold secrets', async () => {
167
- const { dir, accounts } = service()
168
- audit(dir, 'a', 'login.failed', 'token sk-ant-api03-abcdefghijklmnopqrstuvwxyz0123456789 rejected')
169
- const text = readFileSync(join(dir, 'audit.jsonl'), 'utf8')
170
- expect(text).not.toContain('abcdefghijklmnop')
171
- expect(text).toContain('[redacted]')
172
-
173
- const account = addAccount(dir, 'A', 'apiKey')
174
- await accounts.writeCredential(account.id, 'anthropic', { type: 'api_key', key: 'sk-secret-value' })
175
- expect((await accounts.readCredential(account.id, 'anthropic'))?.key).toBe('sk-secret-value')
176
- for (const file of walk(dir)) expect(readFileSync(file, 'utf8')).not.toContain('sk-secret-value')
177
- expect((await accounts.listCredentials(account.id))[0].type).toBe('api_key')
178
- await expect(accounts.writeCredential(account.id, '../x', null)).rejects.toThrow('Invalid provider name.')
179
- })
180
-
181
- test('a failed terminal credential launch can retry without a stale reference count', async () => {
182
- const { dir, accounts } = service()
183
- const account = addAccount(dir, 'A', 'apiKey')
184
- ensureHome(dir, account)
185
- await accounts.writeCredential(account.id, 'openai', { type: 'api_key', key: 'probe' })
186
- const auth = join(configDir(dir, account), 'auth.json')
187
- mkdirSync(auth)
188
- await expect(accounts.terminalBegin(account)).rejects.toThrow()
189
- rmdirSync(auth)
190
- await accounts.terminalBegin(account)
191
- expect(statSync(auth).isFile()).toBe(true)
192
- expect(statSync(auth).mode & 0o777).toBe(0o600)
193
- await accounts.terminalEnd(account)
194
- expect(existsSync(auth)).toBe(false)
195
- })
196
-
197
- test('a terminal round-trips credentials through auth.json', async () => {
198
- const { dir, accounts } = service()
199
- const account = addAccount(dir, 'A', 'apiKey')
200
- ensureHome(dir, account)
201
- await accounts.writeCredential(account.id, 'openai', { type: 'api_key', key: 'k1' })
202
- await accounts.terminalBegin(account)
203
- const auth = join(configDir(dir, account), 'auth.json')
204
- expect(readFileSync(auth, 'utf8')).toContain('k1')
205
- writeFileSync(auth, JSON.stringify({ anthropic: { type: 'oauth', access: 'a', refresh: 'r', expires: 1 } }))
206
- await accounts.terminalEnd(account)
207
- expect(existsSync(auth)).toBe(false)
208
- expect(loadState(dir, account.id).piProviders).toEqual(['anthropic'])
209
- expect((await accounts.readCredential(account.id, 'anthropic'))?.refresh).toBe('r')
210
- })
211
-
212
- test('creating, renaming and removing an account is audited and announced', async () => {
213
- const { dir, accounts, secrets, notices } = service()
214
- const created = accounts.create(' Work ', 'apiKey').accounts[0]
215
- expect([created.label, created.isDefault, created.state.health]).toEqual(['Work', true, 'unknown'])
216
- expect(lstatSync(join(configDir(dir, created), 'skills')).isSymbolicLink()).toBe(true)
217
- await accounts.writeCredential(created.id, 'openai', { type: 'api_key', key: 'k' })
218
- expect(() => accounts.create('', 'apiKey')).toThrow()
219
- expect(() => accounts.create('x', 'password')).toThrow('Unknown sign-in type.')
220
- accounts.rename(created.id, 'Home')
221
- await accounts.remove(created.id)
222
- expect(accounts.overview().accounts).toEqual([])
223
- expect(existsSync(join(dir, created.id))).toBe(false)
224
- expect(secrets.values.size).toBe(0)
225
- expect(notices.filter((notice) => notice.type === 'accounts.changed').length).toBeGreaterThanOrEqual(3)
226
- expect(readFileSync(join(dir, 'audit.jsonl'), 'utf8')).toContain('account.deleted')
227
- })
228
-
229
- test('run events move an account between healthy and limited', () => {
230
- const { dir, accounts, notices } = service()
231
- const account = addAccount(dir, 'A', 'subscription')
232
- const event = (type: string, payload: unknown) => ({ id: 'e', runId: 'r', sessionId: 's', sequence: 0, timestamp: '', type: type as never, payload })
233
- accounts.onRunEvent(event('account.status', { accountId: account.id, category: 'quota', message: 'usage limit reached for sk-abcdefghijklmnopqrstuvwxyz012345' }), null)
234
- const limited = loadState(dir, account.id)
235
- expect(limited.health).toBe('limited')
236
- expect(limited.lastError?.message).toContain('[redacted]')
237
- expect(notices.at(-1)).toMatchObject({ type: 'accounts.changed', health: 'limited', previous: 'unknown' })
238
- // A finished run proves the sign-in works, but a limit error stays until it resets.
239
- accounts.onRunEvent(event('completed', {}), { accountId: account.id } as never)
240
- expect(loadState(dir, account.id)).toMatchObject({ signedIn: true, health: 'limited' })
241
- accounts.onRunEvent(event('account.status', { accountId: account.id, category: 'auth_expired', message: '401' }), null)
242
- expect(loadState(dir, account.id)).toMatchObject({ signedIn: false, health: 'auth_expired' })
243
- accounts.onRunEvent(event('completed', {}), { accountId: account.id } as never)
244
- expect(loadState(dir, account.id).health).toBe('ok')
245
- })
246
-
247
- test('provider errors are classified', () => {
248
- expect(classifyMessage('401 Unauthorized')).toBe('auth_expired')
249
- expect(classifyMessage('You have hit your usage limit')).toBe('quota')
250
- expect(classifyMessage('429 Too Many Requests')).toBe('rate_limited')
251
- expect(classifyMessage('fetch failed')).toBe('network')
252
- expect(classifyMessage('the model said no')).toBeNull()
253
- })
254
-
255
- test('a rejected OAuth refresh requests reauthentication and keeps the credential', async () => {
256
- const { dir, accounts } = service()
257
- const account = accounts.create('OpenAI', 'subscription').accounts[0]
258
- await accounts.writeCredential(account.id, 'openai', { type: 'oauth', access: 'old-access', refresh: 'old-refresh', expires: 0 })
259
- accounts.runtime = async () => ({
260
- listCredentials: async () => [{ providerId: 'openai', type: 'oauth' }],
261
- getAvailable: async () => { throw new Error('OAuth refresh failed for openai: OpenAI OAuth token request failed (400): {"error":"invalid_grant"}') }
262
- } as unknown as ModelRuntime)
263
-
264
- await accounts.refreshOne(account)
265
-
266
- expect(loadState(dir, account.id)).toMatchObject({ health: 'auth_expired', lastError: { category: 'auth_expired' } })
267
- expect(await accounts.readCredential(account.id, 'openai')).toMatchObject({ refresh: 'old-refresh' })
268
- })
269
-
270
- test('native config lists what is shared and what exists', () => {
271
- const dir = temp()
272
- const before = nativeConfig(dir)
273
- expect(before.entries.some((entry) => entry.name === 'extensions' && entry.directory)).toBe(true)
274
- expect(before.entries.every((entry) => !entry.present)).toBe(true)
275
- expect(existsSync(before.path)).toBe(false)
276
- writeFileSync(join(ensureSharedDir(dir), 'AGENTS.md'), 'x')
277
- expect(nativeConfig(dir).entries.find((entry) => entry.name === 'AGENTS.md')?.present).toBe(true)
278
- })
279
-
280
- test('launch env isolates and strips inherited credentials', () => {
281
- const dir = temp()
282
- const env = launchEnv(dir, { id: 'acc1' }, { SOMEVENDOR_API_KEY: 'leak', PATH: '/bin' })
283
- expect(env.PI_CODING_AGENT_DIR?.startsWith(dir)).toBe(true)
284
- expect(env).toMatchObject({ SOMEVENDOR_API_KEY: null, CLAUDE_CONFIG_DIR: null, CODEX_HOME: null })
285
- expect('PATH' in env).toBe(false)
286
- })
287
-
288
- test('accounts share config but not credentials', () => {
289
- const dir = temp()
290
- const first = ensureHome(dir, { id: 'acc1' })
291
- const second = ensureHome(dir, { id: 'acc2' })
292
- writeFileSync(join(first, 'settings.json'), '{"theme":"dark"}\n')
293
- mkdirSync(join(first, 'skills/review'), { recursive: true })
294
- writeFileSync(join(first, 'auth.json'), '{}')
295
- expect(readFileSync(join(second, 'settings.json'), 'utf8')).toBe('{"theme":"dark"}\n')
296
- expect(statSync(join(second, 'skills/review')).isDirectory()).toBe(true)
297
- expect(existsSync(join(second, 'auth.json'))).toBe(false)
298
- expect(lstatSync(join(first, 'auth.json')).isSymbolicLink()).toBe(false)
299
- expect(readlinkSync(join(first, 'skills'))).toBe(join(sharedDir(dir), 'skills'))
300
- })
301
-
302
- test('existing account config moves into the shared folder, newest wins', async () => {
303
- const dir = temp()
304
- for (const id of ['acc1', 'acc2']) {
305
- mkdirSync(configDir(dir, { id }), { recursive: true })
306
- writeFileSync(join(configDir(dir, { id }), 'settings.json'), `{"from":"${id}"}`)
307
- await new Promise((resolve) => setTimeout(resolve, 20))
308
- }
309
- ensureHome(dir, { id: 'acc1' })
310
- // acc2's settings are newer than the shared copy acc1 just moved in, so they win.
311
- const second = ensureHome(dir, { id: 'acc2' })
312
- expect(readFileSync(join(sharedDir(dir), 'settings.json'), 'utf8')).toBe('{"from":"acc2"}')
313
- expect(readdirSync(sharedDir(dir)).some((name) => name.startsWith('settings.json.xagent-backup-'))).toBe(true)
314
- expect(lstatSync(join(second, 'settings.json')).isSymbolicLink()).toBe(true)
315
- })
316
-
317
- test('refuses default tool directories', () => {
318
- const dir = temp()
319
- for (const name of ['.codex', '.claude', '.pi/agent']) expect(() => assertIsolated(dir, join(homedir(), name))).toThrow()
320
- expect(() => assertIsolated(dir, '/tmp/elsewhere')).toThrow()
321
- expect(() => assertIsolated(dir, join(dir, 'a/home/pi'))).not.toThrow()
322
- })
323
-
324
- test('a file secret store keeps secrets owner-only', async () => {
325
- const path = join(temp(), 'nested/secrets.json')
326
- const secrets = fileSecretStore(path)
327
- expect(await secrets.get('a/b')).toBeNull()
328
- await secrets.set('a/b', 'value')
329
- expect(await secrets.get('a/b')).toBe('value')
330
- expect(statSync(path).mode & 0o777).toBe(0o600)
331
- await secrets.delete('a/b')
332
- expect(await secrets.get('a/b')).toBeNull()
333
- })