@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,74 +0,0 @@
1
- // Health checks over the whole Wiki. They report problems with a route to the affected
2
- // entries and never delete anything.
3
- import { charCount } from '../core/text'
4
- import * as registry from '../skills/registry'
5
- import * as blocks from './blocks'
6
- import * as facts from './facts'
7
- import { lastOperationAt } from './operations'
8
- import * as store from './store'
9
-
10
- export interface HealthReport {
11
- brokenLinks: { pageId: string; targetId: string }[]
12
- orphanPages: string[]
13
- missingEvidence: string[]
14
- contradictions: { fromId: string; toId: string }[]
15
- duplicateIds: string[]
16
- /** Volatile facts that have not been observed for a while and may no longer be true. */
17
- staleFacts: string[]
18
- /** Groups of pages whose titles differ only by a run id, a number, or punctuation. */
19
- similarTitles: string[][]
20
- /** Memory blocks at 90% of their limit or more. */
21
- fullBlocks: string[]
22
- lastMaintenanceAt: string | null
23
- }
24
-
25
- const IGNORED_WORDS = new Set(['the', 'a', 'an', 'in', 'of', 'run'])
26
-
27
- /** A title without the parts that make near-duplicates look different: case, punctuation, numbers, and id-like words. */
28
- function titleKey(title: string): string {
29
- return title.toLowerCase().split(/[^\p{Alphabetic}\p{N}]+/u).filter((word) => word && !/[0-9]/.test(word) && !IGNORED_WORDS.has(word)).join(' ')
30
- }
31
-
32
- export function check(root: string): HealthReport {
33
- const wiki = store.wikiDir(root)
34
- const pages = store.loadPages(wiki)
35
- const memories = facts.loadMemories(wiki)
36
- const sourceIds = new Set(store.listSources(wiki).map((source) => source.id))
37
- const registryIds = registry.list(root).map((item) => item.id)
38
-
39
- // Every page and fact; `standalone` ones need neither links nor sources.
40
- const entries = [
41
- ...pages.map((page) => ({ id: page.frontmatter.id, links: page.frontmatter.links, sources: page.frontmatter.sourceIds, standalone: page.frontmatter.id === 'home' || page.frontmatter.type === 'project' || store.isSkeleton(page.location) })),
42
- ...memories.map((memory) => ({ id: memory.front.id, links: memory.front.links, sources: memory.front.sourceIds, standalone: true }))
43
- ]
44
- const seen = new Set<string>()
45
- const duplicateIds = entries.filter((entry) => seen.size === seen.add(entry.id).size).map((entry) => entry.id)
46
- const known = new Set([...entries.map((entry) => entry.id), ...sourceIds, ...registryIds])
47
- const linked = new Set(entries.flatMap((entry) => entry.links.map((link) => link.toId)))
48
- const validEvidence = (id: string): boolean => sourceIds.has(id) || store.isExternalEvidence(id)
49
-
50
- // Pages in one namespace whose titles reduce to the same key, in namespace then key order.
51
- const groups = new Map<string, { namespace: string; key: string; ids: string[] }>()
52
- for (const page of pages) {
53
- if (store.isSkeleton(page.location) || page.frontmatter.type === 'project') continue
54
- const key = titleKey(page.frontmatter.title)
55
- if (!key) continue
56
- const name = `${page.location.namespace}\u0000${key}`
57
- if (!groups.has(name)) groups.set(name, { namespace: page.location.namespace, key, ids: [] })
58
- groups.get(name)!.ids.push(page.frontmatter.id)
59
- }
60
- const ordered = [...groups.values()].sort((left, right) => (left.namespace === right.namespace ? (left.key < right.key ? -1 : left.key > right.key ? 1 : 0) : left.namespace < right.namespace ? -1 : 1))
61
-
62
- return {
63
- brokenLinks: entries.flatMap((entry) => entry.links.filter((link) => !known.has(link.toId)).map((link) => ({ pageId: entry.id, targetId: link.toId }))),
64
- // Home, project overviews, and facts stand on their own; other pages should be linked.
65
- orphanPages: entries.filter((entry) => !entry.standalone && !entry.links.length && !linked.has(entry.id)).map((entry) => entry.id),
66
- missingEvidence: entries.filter((entry) => (!entry.standalone && !entry.sources.length) || entry.sources.some((id) => !validEvidence(id))).map((entry) => entry.id),
67
- contradictions: entries.flatMap((entry) => entry.links.filter((link) => link.type === 'contradicts').map((link) => ({ fromId: entry.id, toId: link.toId }))),
68
- duplicateIds,
69
- staleFacts: memories.filter((memory) => facts.isStale(memory.front)).map((memory) => memory.front.id),
70
- similarTitles: ordered.filter((group) => group.ids.length > 1).map((group) => group.ids),
71
- fullBlocks: blocks.loadAll(wiki).filter((block) => block.front.limit > 0 && charCount(block.body) * 100 >= block.front.limit * 90).map((block) => block.id),
72
- lastMaintenanceAt: lastOperationAt(wiki)
73
- }
74
- }
@@ -1,272 +0,0 @@
1
- // Sleep-time consolidation: a Pi session that reads new evidence (an imported source or a
2
- // settled run) or a set of full memory blocks, and proposes changes. It has no file or shell
3
- // tools, only proposal tools, so every change goes back to the proposal check, which looks each
4
- // quoted excerpt up in the evidence before anything is written.
5
- import type { ModelRuntime } from '@earendil-works/pi-coding-agent'
6
-
7
- import type { AccountContext } from '../accounts/env'
8
- import { HarnessError } from '../core/errors'
9
- import { MEMORY_KINDS } from './facts'
10
- import { LINK_TYPES, PAGE_TYPES } from './store'
11
-
12
- export interface ExistingPage {
13
- id: string
14
- title: string
15
- type: string
16
- path?: string
17
- summary: string
18
- /** The page's current text, for the few pages closest to the evidence. */
19
- body?: string
20
- }
21
-
22
- export interface ExistingMemory {
23
- id: string
24
- title: string
25
- kind: string
26
- namespace: string
27
- body: string
28
- }
29
-
30
- /** A memory block attached to the run, in full. */
31
- export interface ExistingBlock {
32
- id: string
33
- label: string
34
- description: string
35
- limit: number
36
- body: string
37
- }
38
-
39
- export type MaintenanceTrigger = { kind: 'ingest'; sourceId: string; sourceName: string; text: string } | { kind: 'run'; runId: string; transcript: string } | { kind: 'consolidate' }
40
-
41
- export interface MaintenanceRequest {
42
- jobId: string
43
- /** Where new pages go by default: /library or /projects/<slug>. */
44
- namespace: string
45
- trigger: MaintenanceTrigger
46
- pages: ExistingPage[]
47
- memories?: ExistingMemory[]
48
- blocks?: ExistingBlock[]
49
- namespaces?: { namespace: string; label: string }[]
50
- index: string
51
- }
52
-
53
- /** What the session proposed, as its tools received it. Nothing here has been checked yet. */
54
- export interface MaintenanceResult {
55
- pages: unknown[]
56
- memories: unknown[]
57
- blocks: unknown[]
58
- flags: unknown[]
59
- }
60
-
61
- const EVIDENCE_RULE = `Every change must carry sourceRefs with an excerpt: a short passage (at least a few words) copied
62
- exactly from the evidence. The host looks the excerpt up in the evidence and discards any change whose
63
- excerpt it cannot find, so never paraphrase an excerpt and never cite something the evidence does not say.`
64
-
65
- const runInstructions = (product: string): string => `You consolidate memory for ${product} after a run has finished ("sleep-time" work).
66
- You are given the run's transcript, the memory blocks that were in its context, the facts that apply,
67
- and related Wiki pages. Decide what is worth keeping for future work, then:
68
- - rethink_block: rewrite a memory block when the run taught something that belongs in it (see each
69
- block's description). Give the complete new content, merged with what is already there. Remove
70
- what the run showed to be wrong or finished. Stay within the block's limit.
71
- - propose_memory: record a short standing fact, preference, decision, or piece of feedback. Update
72
- an existing fact by id, or replace one with supersedes. Use low confidence when unsure.
73
- - propose_page: update a page that ALREADY EXISTS, by its id, with its complete new body (merge with
74
- the current text shown to you; never drop established content unless the evidence supersedes it).
75
- You cannot create pages: one run is an episode, not a page. What a run merely observed (a tool
76
- result, a status, a list that will change) is not durable knowledge; leave it out.
77
- - flag_claim: send an uncertain, contradictory, or sensitive claim to the review inbox instead.
78
- ${EVIDENCE_RULE}
79
- Use {"kind":"run","ref":"<the run id>","excerpt":"…"}.
80
- Skip small talk and transient details. Most runs need few changes; it is fine to change nothing.`
81
-
82
- const ingestInstructions = (product: string): string => `You maintain ${product}'s global knowledge Wiki (Karpathy-style LLM Wiki).
83
- Raw sources are immutable evidence; Wiki pages are durable, interlinked Markdown syntheses, one per
84
- entity, concept, or decision, updated in place. The Wiki is one corpus: the Library (/library) and one
85
- namespace per project (/projects/<name>). Facts are short typed statements.
86
- Read the imported source and decide what durable knowledge it adds. Then:
87
- - propose_page once per page to create or update. To update, pass the existing page id and the
88
- complete new body (merge with what the page already says; never drop established content unless
89
- the source supersedes it, and say so). Prefer updating an existing page over creating a near
90
- duplicate. New pages go to the job's namespace unless they clearly belong elsewhere.
91
- - propose_memory for a short standing fact, preference, decision, or piece of feedback. Use namespace
92
- "/" when it applies everywhere.
93
- - Link related pages with typed links (references, depends_on, supersedes, contradicts,
94
- produced_by, uses) using existing page ids or ids you propose.
95
- - flag_claim for a claim that is uncertain, contradicts an existing page, or contains secrets or
96
- personal data that should not be stored.
97
- ${EVIDENCE_RULE}
98
- Use {"kind":"source","ref":"<the source id>","excerpt":"…"}.
99
- Prefer few, well-structured pages. Page ids are short kebab-case slugs. It is fine to propose nothing.`
100
-
101
- const consolidateInstructions = (product: string): string => `You tidy ${product}'s memory blocks. Each block below is close to its
102
- character limit. For each one, call rethink_block with a shorter version that keeps everything still
103
- true and useful: merge repeats, drop what is finished or superseded, and tighten the wording. Do not
104
- add anything that is not already in the block. The new content must be shorter than the current one.`
105
-
106
- export function instructions(kind: MaintenanceTrigger['kind'], product: string): string {
107
- return kind === 'run' ? runInstructions(product) : kind === 'ingest' ? ingestInstructions(product) : consolidateInstructions(product)
108
- }
109
-
110
- /** The proposal tools each kind of job gets. */
111
- export function toolNames(kind: MaintenanceTrigger['kind']): string[] {
112
- if (kind === 'consolidate') return ['rethink_block']
113
- if (kind === 'run') return ['rethink_block', 'propose_memory', 'propose_page', 'flag_claim']
114
- return ['propose_page', 'propose_memory', 'flag_claim']
115
- }
116
-
117
- export function prompt(request: MaintenanceRequest): string {
118
- const blocks = request.blocks?.length
119
- ? request.blocks.map((block) => `<block id="${block.id}" label="${block.label}" chars="${Array.from(block.body).length}/${block.limit}">\n${block.description}\n---\n${block.body.trim() || '(empty)'}\n</block>`).join('\n\n')
120
- : '(none)'
121
- if (request.trigger.kind === 'consolidate') return `Memory blocks to condense:\n\n${blocks}`
122
- const existing = request.pages.length ? request.pages.map((page) => `- ${page.id} (${page.type}${page.path ? `, ${page.path}` : ''}): ${page.title} — ${page.summary}`).join('\n') : '(no pages yet)'
123
- const bodies = request.pages.filter((page) => page.body?.trim()).map((page) => `<page id="${page.id}" title="${page.title}">\n${page.body}\n</page>`).join('\n\n')
124
- const memories = request.memories?.length ? request.memories.map((memory) => `- ${memory.id} [${memory.kind}, ${memory.namespace}] ${memory.title}: ${memory.body}`).join('\n') : '(none)'
125
- const namespaces = ['/library', ...(request.namespaces ?? []).map((namespace) => `${namespace.namespace} (${namespace.label})`)].join(', ')
126
- const evidence = request.trigger.kind === 'ingest' ? `Imported source ${request.trigger.sourceId} ("${request.trigger.sourceName}"):\n\n${request.trigger.text}` : `Settled run ${request.trigger.runId} transcript:\n\n${request.trigger.transcript}`
127
- return [
128
- `Namespace for this job: ${request.namespace}`,
129
- `Namespaces: ${namespaces}`,
130
- ...(request.trigger.kind === 'run' ? [`Memory blocks in this run's context:\n\n${blocks}`] : []),
131
- `Current index:\n${request.index}`,
132
- `Relevant pages:\n${existing}`,
133
- ...(bodies ? [`Current text of the closest pages:\n\n${bodies}`] : []),
134
- `Facts:\n${memories}`,
135
- `New evidence:\n${evidence}`
136
- ].join('\n\n')
137
- }
138
-
139
- export interface MaintainerSession {
140
- prompt(text: string): Promise<void>
141
- dispose(): void
142
- /** Assistant error text, if the provider failed. */
143
- error(): string | null
144
- }
145
-
146
- type Collector = { page: (proposal: unknown) => string; memory: (proposal: unknown) => string; block: (proposal: unknown) => string; flag: (flag: unknown) => string }
147
-
148
- export type MaintainerFactory = (input: {
149
- cwd: string
150
- /** Which job this is; it decides the instructions and the tools. */
151
- kind: MaintenanceTrigger['kind']
152
- product: string
153
- account: AccountContext
154
- runtime: () => Promise<ModelRuntime>
155
- collect: Collector
156
- }) => Promise<MaintainerSession>
157
-
158
- export const piMaintainerFactory: MaintainerFactory = async ({ cwd, kind, product, account, runtime, collect }) => {
159
- const pi = await import('@earendil-works/pi-coding-agent')
160
- const { Type } = await import('typebox')
161
- const agentDir = account.configDir
162
- const resourceLoader = new pi.DefaultResourceLoader({ cwd, agentDir, noExtensions: true, noSkills: true, noPromptTemplates: true, noContextFiles: true, appendSystemPromptOverride: (base) => [...base, instructions(kind, product)] })
163
- await resourceLoader.reload()
164
- const sourceRefs = Type.Array(
165
- Type.Object({
166
- kind: Type.Union([Type.Literal('source'), Type.Literal('run'), Type.Literal('url')]),
167
- ref: Type.String(),
168
- excerpt: Type.Optional(Type.String({ description: 'A passage copied exactly from the evidence' }))
169
- })
170
- )
171
- const reply = (text: string) => ({ content: [{ type: 'text' as const, text }], details: {} })
172
- const tools = [
173
- pi.defineTool({
174
- name: 'rethink_block',
175
- label: 'Rewrite block',
176
- description: 'Rewrite one memory block with its complete new content. The host checks the excerpt and the block limit before anything is written.',
177
- parameters: Type.Object({ block: Type.String({ description: 'The block id, as given in <block id="…">' }), body: Type.String({ description: 'The complete new content of the block' }), sourceRefs: Type.Optional(sourceRefs) }),
178
- execute: async (_id, input) => reply(collect.block({ sourceRefs: [], ...(input as object) }))
179
- }),
180
- pi.defineTool({
181
- name: 'propose_page',
182
- label: 'Propose page',
183
- description: 'Create or update one Wiki page. The host validates it before anything is written.',
184
- parameters: Type.Object({
185
- id: Type.Optional(Type.String({ description: 'Existing page id to update, or a new kebab-case id' })),
186
- title: Type.String(),
187
- type: Type.Union(PAGE_TYPES.map((value) => Type.Literal(value))),
188
- body: Type.String({ description: 'Complete Markdown body' }),
189
- namespace: Type.Optional(Type.String({ description: 'For a new page: /library or /projects/<name>; defaults to the job namespace' })),
190
- sourceRefs,
191
- links: Type.Array(Type.Object({ toId: Type.String(), type: Type.Union(LINK_TYPES.map((value) => Type.Literal(value))) }))
192
- }),
193
- execute: async (_id, input) => reply(collect.page(input))
194
- }),
195
- pi.defineTool({
196
- name: 'propose_memory',
197
- label: 'Propose fact',
198
- description: 'Create or update one fact: a short standing statement agents can look up. The host validates it before anything is written.',
199
- parameters: Type.Object({
200
- id: Type.Optional(Type.String({ description: 'Existing fact id to update, or a new kebab-case id' })),
201
- title: Type.String(),
202
- kind: Type.Union(MEMORY_KINDS.map((value) => Type.Literal(value))),
203
- body: Type.String({ description: 'One to a few sentences' }),
204
- namespace: Type.Optional(Type.String({ description: '/ for everywhere, or /projects/<name>' })),
205
- confidence: Type.Optional(Type.Union([Type.Literal('high'), Type.Literal('medium'), Type.Literal('low')])),
206
- supersedes: Type.Optional(Type.String({ description: 'Id of the fact this replaces' })),
207
- sourceRefs
208
- }),
209
- execute: async (_id, input) => reply(collect.memory(input))
210
- }),
211
- pi.defineTool({
212
- name: 'flag_claim',
213
- label: 'Flag claim',
214
- description: 'Send an uncited, contradictory, uncertain, or sensitive claim to the review inbox instead of the Wiki.',
215
- parameters: Type.Object({ claim: Type.String(), kind: Type.Union([Type.Literal('uncited'), Type.Literal('contradiction'), Type.Literal('low_confidence'), Type.Literal('sensitive')]), reason: Type.String() }),
216
- execute: async (_id, input) => reply(collect.flag(input))
217
- })
218
- ]
219
- const allowed = toolNames(kind)
220
- const { session } = await pi.createAgentSession({
221
- cwd,
222
- agentDir,
223
- modelRuntime: await runtime(),
224
- tools: allowed,
225
- customTools: tools.filter((tool) => allowed.includes((tool as { name: string }).name)) as never,
226
- resourceLoader,
227
- sessionManager: pi.SessionManager.inMemory(cwd)
228
- })
229
- let lastError: string | null = null
230
- session.subscribe((event) => {
231
- if (event.type !== 'message_end') return
232
- const message = event.message as { role?: string; stopReason?: string; errorMessage?: string }
233
- if (message.role === 'assistant' && message.stopReason === 'error') lastError = message.errorMessage ?? 'Provider error'
234
- })
235
- return { prompt: (text) => session.prompt(text), dispose: () => session.dispose(), error: () => lastError }
236
- }
237
-
238
- /** Runs one job's session and returns what it proposed. Nothing is written here. */
239
- export async function runMaintenance(request: MaintenanceRequest, input: Omit<Parameters<MaintainerFactory>[0], 'kind' | 'collect'>, factory: MaintainerFactory = piMaintainerFactory): Promise<MaintenanceResult> {
240
- const result: MaintenanceResult = { pages: [], memories: [], blocks: [], flags: [] }
241
- const titled = (proposal: unknown): string => String((proposal as { title?: unknown } | null)?.title ?? '')
242
- const session = await factory({
243
- ...input,
244
- kind: request.trigger.kind,
245
- collect: {
246
- page: (proposal) => {
247
- result.pages.push(proposal)
248
- return `Proposed "${titled(proposal)}". The host will validate it.`
249
- },
250
- memory: (proposal) => {
251
- result.memories.push(proposal)
252
- return `Proposed memory "${titled(proposal)}". The host will validate it.`
253
- },
254
- block: (proposal) => {
255
- result.blocks.push(proposal)
256
- return `Proposed a rewrite of ${String((proposal as { block?: unknown } | null)?.block ?? '')}. The host will validate it.`
257
- },
258
- flag: (flag) => {
259
- result.flags.push(flag)
260
- return 'Sent to the review inbox.'
261
- }
262
- }
263
- })
264
- try {
265
- await session.prompt(prompt(request))
266
- const error = session.error()
267
- if (error) throw new HarnessError('provider_error', error)
268
- } finally {
269
- session.dispose()
270
- }
271
- return result
272
- }
@@ -1,176 +0,0 @@
1
- import { mkdtempSync, readFileSync, writeFileSync } from 'node:fs'
2
- import { tmpdir } from 'node:os'
3
- import { join } from 'node:path'
4
- import { afterEach, describe, expect, it } from 'vitest'
5
-
6
- import { memorySecretStore } from '../accounts/secrets'
7
- import { writeJson } from '../core/fs'
8
- import type { Notice } from '../core/bus'
9
- import { createHarness, type Harness } from '../harness'
10
- import type { PiSessionLike } from '../sessions/runner'
11
- import * as blocks from './blocks'
12
- import { findMemory } from './facts'
13
- import { prompt, runMaintenance, toolNames, type MaintainerFactory, type MaintenanceRequest } from './maintainer'
14
- import { chatUpdatesPaused, fullBlocks } from './maintenance'
15
- import { listInbox } from './operations'
16
- import { wikiDir } from './store'
17
-
18
- const request: MaintenanceRequest = { jobId: 'job-1', namespace: '/library', trigger: { kind: 'ingest', sourceId: 'src-1', sourceName: 'notes.md', text: 'We chose Tauri.' }, pages: [], index: '# Index' }
19
- const input = { cwd: '/tmp', product: 'Xingular Agent', account: { id: 'a', provider: 'pi' as const, label: 'A', env: {}, configDir: '/tmp', sharing: [] }, runtime: async () => ({}) as never }
20
-
21
- describe('the maintainer session', () => {
22
- it('collects proposals and flags without writing anything itself', async () => {
23
- let prompted = ''
24
- const factory: MaintainerFactory = async ({ collect }) => ({
25
- prompt: async (text) => {
26
- prompted = text
27
- collect.page({ title: 'Use Tauri', type: 'decision', body: 'We use Tauri.', sourceRefs: [{ kind: 'source', ref: 'src-1' }], links: [] })
28
- collect.memory({ title: 'Prefers Tauri', kind: 'preference', body: 'Use Tauri for desktop apps.', namespace: '/', sourceRefs: [{ kind: 'source', ref: 'src-1' }] })
29
- collect.flag({ claim: 'Electron is slow', kind: 'uncited', reason: 'No source' })
30
- },
31
- dispose: () => undefined,
32
- error: () => null
33
- })
34
- const result = await runMaintenance(request, input, factory)
35
- expect(prompted).toContain('src-1')
36
- expect(prompted).toContain('Namespace for this job: /library')
37
- expect(result.pages).toHaveLength(1)
38
- expect(result.memories[0]).toMatchObject({ kind: 'preference', namespace: '/' })
39
- expect(result.flags[0]).toMatchObject({ kind: 'uncited' })
40
- })
41
-
42
- it('gives a run its blocks and page bodies, and each job only its tools', async () => {
43
- const block = { id: 'blocks/shared/user', label: 'user', description: 'About the user.', limit: 2000, body: 'Likes pnpm.' }
44
- const run: MaintenanceRequest = { ...request, trigger: { kind: 'run', runId: 'run-1', transcript: 'User: hi\nAssistant: hello' }, pages: [{ id: 'shell', title: 'Shell', type: 'decision', summary: 'Tauri', body: 'We use Tauri.' }], blocks: [block] }
45
- const text = prompt(run)
46
- expect(text).toContain('<block id="blocks/shared/user" label="user" chars="11/2000">')
47
- expect(text).toContain('<page id="shell" title="Shell">\nWe use Tauri.')
48
- expect(text).toContain('Settled run run-1 transcript')
49
- expect(prompt({ ...request, trigger: { kind: 'consolidate' }, blocks: [block] })).toBe('Memory blocks to condense:\n\n<block id="blocks/shared/user" label="user" chars="11/2000">\nAbout the user.\n---\nLikes pnpm.\n</block>')
50
- expect(toolNames('run')).toEqual(['rethink_block', 'propose_memory', 'propose_page', 'flag_claim'])
51
- expect(toolNames('ingest')).not.toContain('rethink_block')
52
- expect(toolNames('consolidate')).toEqual(['rethink_block'])
53
- })
54
-
55
- it('reports provider failures', async () => {
56
- const factory: MaintainerFactory = async () => ({ prompt: async () => undefined, dispose: () => undefined, error: () => 'quota exceeded' })
57
- await expect(runMaintenance(request, input, factory)).rejects.toMatchObject({ code: 'provider_error' })
58
- })
59
- })
60
-
61
- const open: Harness[] = []
62
- afterEach(async () => {
63
- for (const harness of open.splice(0)) await harness.close()
64
- })
65
-
66
- function setup(factory: MaintainerFactory) {
67
- const reply: PiSessionLike = {
68
- sessionId: 'native',
69
- subscribe: (listener) => {
70
- emit = listener as never
71
- return () => undefined
72
- },
73
- prompt: async () => emit({ type: 'message_end', message: { role: 'assistant', content: [{ type: 'text', text: 'We decided to use Tauri. I prefer small commits.' }] } }),
74
- sendCustomMessage: async () => undefined,
75
- abort: async () => undefined,
76
- dispose: () => undefined
77
- }
78
- let emit: (event: unknown) => void = () => undefined
79
- const harness = createHarness({ dataRoot: mkdtempSync(join(tmpdir(), 'harness-maint-data-')), stateDir: mkdtempSync(join(tmpdir(), 'harness-maint-state-')), secrets: memorySecretStore(), sessionFactory: async () => reply, maintainerFactory: factory })
80
- open.push(harness)
81
- harness.accounts.create('Main', 'apiKey')
82
- const notices: Notice[] = []
83
- harness.bus.on((notice) => void notices.push(notice))
84
- const turn = (id: string) => harness.sessions.run({ run: { id, sessionId: 'nora' }, cwd: harness.env.root, sessionDir: join(harness.env.root, 'history'), text: 'Which shell do we use?', caller: { agentId: 'nora', agentName: 'Nora', actor: 'Chat' }, tools: { allow: [] } })
85
- return { harness, notices, turn, wiki: wikiDir(harness.env.root) }
86
- }
87
-
88
- describe('the memory lifecycle', () => {
89
- it('a settled run is consolidated: quoted changes apply, invented ones wait, and the session never writes', async () => {
90
- let seen: { kind: string; text: string } | null = null
91
- const { harness, notices, turn, wiki } = setup(async ({ kind, collect }) => ({
92
- prompt: async (text) => {
93
- seen = { kind, text }
94
- collect.memory({ title: 'Small commits', kind: 'preference', body: 'Prefer small commits.', confidence: 'high', sourceRefs: [{ kind: 'run', ref: 'run-1', excerpt: 'I prefer small commits' }] })
95
- collect.memory({ title: 'Invented', kind: 'fact', body: 'Never said.', confidence: 'high', sourceRefs: [{ kind: 'run', ref: 'run-1', excerpt: 'something never said at all' }] })
96
- collect.block({ block: 'blocks/agents/nora/notes', body: 'The shell is Tauri.', sourceRefs: [{ kind: 'run', ref: 'run-1', excerpt: 'We decided to use Tauri' }] })
97
- collect.page({ title: 'A new page', type: 'concept', body: 'From one run.', sourceRefs: [{ kind: 'run', ref: 'run-1', excerpt: 'We decided to use Tauri' }], links: [] })
98
- },
99
- dispose: () => undefined,
100
- error: () => null
101
- }))
102
- await turn('run-1')
103
- await new Promise((resolve) => setTimeout(resolve, 30))
104
- await harness.maintenance.settled()
105
- expect(seen!.kind).toBe('run')
106
- expect(seen!.text).toContain('Settled run run-1 transcript:\n\nUser: Which shell do we use?\nAssistant: We decided to use Tauri.')
107
- expect(seen!.text).toContain('<block id="blocks/agents/nora/notes" label="notes"')
108
- expect(findMemory(wiki, 'small-commits').front).toMatchObject({ namespace: '/', sourceIds: ['run:run-1'] })
109
- expect(() => findMemory(wiki, 'invented')).toThrow()
110
- expect(blocks.find(wiki, 'blocks/agents/nora/notes').body).toBe('The shell is Tauri.')
111
- // One run is an episode: it never becomes a page by itself.
112
- expect(listInbox(wiki).map((item) => item.kind).sort()).toEqual(['applied', 'unresolved', 'unresolved'])
113
- expect(notices.some((notice) => notice.type === 'wiki.maintenance' && String(notice.detail).includes('2 parked'))).toBe(true)
114
- expect(readFileSync(join(wiki, 'log.md'), 'utf8')).toContain('Sleep-time · run run-1')
115
- // A person can undo the whole consolidation as one operation.
116
- harness.maintenance.undoOperation(listInbox(wiki).find((item) => item.operationId)!.operationId!)
117
- expect(blocks.find(wiki, 'blocks/agents/nora/notes').body).toBe('')
118
- })
119
-
120
- it('skips a run that settings exclude, and a paused conversation', async () => {
121
- let jobs = 0
122
- const { harness, turn } = setup(async () => ({ prompt: async () => void (jobs += 1), dispose: () => undefined, error: () => null }))
123
- writeJson(join(harness.env.root, 'config/settings.json'), { excludedSourceIds: ['run-1'] })
124
- await turn('run-1')
125
- await new Promise((resolve) => setTimeout(resolve, 30))
126
- await harness.maintenance.settled()
127
- writeJson(join(harness.env.root, 'config/settings.json'), { autoMaintenanceChat: false })
128
- await turn('run-2')
129
- await new Promise((resolve) => setTimeout(resolve, 30))
130
- await harness.maintenance.settled()
131
- expect(jobs).toBe(0)
132
- expect([chatUpdatesPaused({}), chatUpdatesPaused({ autoMaintenanceChat: true }), chatUpdatesPaused({ autoMaintenanceChat: false })]).toEqual([false, false, true])
133
- })
134
-
135
- it('an imported source is read once and its proposals are checked against its text', async () => {
136
- const { harness, wiki } = setup(async ({ kind, collect }) => ({
137
- prompt: async () => {
138
- expect(kind).toBe('ingest')
139
- const source = (await import('./store')).listSources(wiki)[0]
140
- collect.page({ id: 'shell', title: 'Shell', type: 'decision', body: 'We use Tauri.', sourceRefs: [{ kind: 'source', ref: source.id, excerpt: 'we chose Tauri for the shell' }], links: [] })
141
- collect.page({ id: 'rumor', title: 'Rumor', type: 'concept', body: 'Not in the source.', sourceRefs: [{ kind: 'source', ref: source.id, excerpt: 'Electron is faster than everything' }], links: [] })
142
- },
143
- dispose: () => undefined,
144
- error: () => null
145
- }))
146
- harness.maintenance.ingest('notes.md', Buffer.from('After the review we chose Tauri for the shell.'))
147
- await harness.maintenance.settled()
148
- expect(readFileSync(join(wiki, 'library/shell.md'), 'utf8')).toContain('We use Tauri.')
149
- const parked = listInbox(wiki).find((item) => item.payload !== undefined)!
150
- expect(parked.title).toContain('Rumor')
151
- // The user is the authority when they accept what was parked.
152
- expect(harness.maintenance.acceptInboxItem(parked.id)).toContain('created')
153
- expect(readFileSync(join(wiki, 'library/rumor.md'), 'utf8')).toContain('user:accepted')
154
- })
155
-
156
- it('condenses a block that is close to its limit once nothing else is happening, and only to something shorter', async () => {
157
- const harness = createHarness({
158
- dataRoot: mkdtempSync(join(tmpdir(), 'harness-maint-data-')),
159
- stateDir: mkdtempSync(join(tmpdir(), 'harness-maint-state-')),
160
- secrets: memorySecretStore(),
161
- idleMs: 20,
162
- maintainerFactory: async ({ kind, collect }) => ({ prompt: async () => void (kind === 'consolidate' && collect.block({ block: 'blocks/shared/user', body: 'Uses pnpm.' })), dispose: () => undefined, error: () => null })
163
- })
164
- open.push(harness)
165
- harness.accounts.create('Main', 'apiKey')
166
- const wiki = wikiDir(harness.env.root)
167
- const user = blocks.ensureUser(wiki)
168
- writeFileSync(user.path, blocks.serializeBlock({ ...user.front, limit: 60 }, 'Likes pnpm. Likes pnpm a lot. Uses pnpm everywhere, always.'))
169
- expect(fullBlocks(wiki, new Set())).toEqual(['blocks/shared/user'])
170
- await new Promise((resolve) => setTimeout(resolve, 120))
171
- await harness.maintenance.settled()
172
- expect(blocks.find(wiki, 'blocks/shared/user').body).toBe('Uses pnpm.')
173
- const tried = new Set<string>()
174
- expect(fullBlocks(wiki, tried)).toEqual([])
175
- })
176
- })