@selesai/code 0.13.39 → 0.14.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 (1401) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/dist/bun/runtime-setup.js +4 -1
  3. package/dist/cli/args.d.ts +3 -1
  4. package/dist/cli/args.js +76 -33
  5. package/dist/cli/auth-check.d.ts +18 -0
  6. package/dist/cli/auth-check.js +49 -0
  7. package/dist/cli/credential-print.d.ts +5 -15
  8. package/dist/cli/credential-print.js +42 -82
  9. package/dist/cli/file-processor.d.ts +1 -1
  10. package/dist/cli/file-processor.js +2 -1
  11. package/dist/cli/list-models.d.ts +1 -1
  12. package/dist/cli/list-models.js +2 -2
  13. package/dist/cli/startup-ui.js +38 -30
  14. package/dist/config.d.ts +35 -6
  15. package/dist/config.js +95 -17
  16. package/dist/core/agent-session-custom-tools.test.js +64 -0
  17. package/dist/core/agent-session-length-continuation.test.js +7 -3
  18. package/dist/core/agent-session-runtime.js +2 -2
  19. package/dist/core/agent-session-services.d.ts +1 -0
  20. package/dist/core/agent-session-services.js +14 -0
  21. package/dist/core/agent-session.d.ts +180 -40
  22. package/dist/core/agent-session.js +1061 -485
  23. package/dist/core/auth-storage.d.ts +25 -15
  24. package/dist/core/auth-storage.js +242 -66
  25. package/dist/core/bash-executor.js +42 -52
  26. package/dist/core/bug-report.js +1 -1
  27. package/dist/core/cache-warmer.d.ts +1 -0
  28. package/dist/core/cache-warmer.js +15 -1
  29. package/dist/core/compaction/branch-summarization.js +3 -0
  30. package/dist/core/compaction/compaction.d.ts +3 -1
  31. package/dist/core/compaction/compaction.js +156 -79
  32. package/dist/core/compaction/utils.d.ts +2 -1
  33. package/dist/core/compaction/utils.js +25 -18
  34. package/dist/core/crash-log.d.ts +5 -0
  35. package/dist/core/crash-log.js +69 -0
  36. package/dist/core/defaults.d.ts +1 -1
  37. package/dist/core/defaults.js +1 -1
  38. package/dist/core/export-html/template.css +10 -0
  39. package/dist/core/export-html/template.js +72 -18
  40. package/dist/core/export-html/tool-renderer.d.ts +3 -3
  41. package/dist/core/export-html/tool-renderer.js +5 -3
  42. package/dist/core/extensions/index.d.ts +2 -2
  43. package/dist/core/extensions/index.js +1 -1
  44. package/dist/core/extensions/loader.js +138 -55
  45. package/dist/core/extensions/runner.d.ts +38 -5
  46. package/dist/core/extensions/runner.js +220 -7
  47. package/dist/core/extensions/types.d.ts +438 -51
  48. package/dist/core/extensions/types.js +3 -0
  49. package/dist/core/extensions/virtual-modules.js +6 -0
  50. package/dist/core/extensions/wrapper.d.ts +2 -2
  51. package/dist/core/extensions/wrapper.js +3 -3
  52. package/dist/core/footer-data-provider.d.ts +1 -1
  53. package/dist/core/footer-data-provider.js +1 -1
  54. package/dist/core/handoff.d.ts +0 -1
  55. package/dist/core/handoff.js +0 -1
  56. package/dist/core/http-dispatcher.js +5 -0
  57. package/dist/core/index.d.ts +1 -1
  58. package/dist/core/intercom-rpc.d.ts +135 -0
  59. package/dist/core/intercom-rpc.js +64 -0
  60. package/dist/core/keybindings.d.ts +25 -24
  61. package/dist/core/keybindings.js +27 -6
  62. package/dist/core/mcp-servers.d.ts +134 -0
  63. package/dist/core/mcp-servers.js +223 -0
  64. package/dist/core/model-config.d.ts +122 -5
  65. package/dist/core/model-config.js +35 -1
  66. package/dist/core/model-registry.d.ts +23 -15
  67. package/dist/core/model-registry.js +46 -22
  68. package/dist/core/model-resolver.d.ts +6 -5
  69. package/dist/core/model-resolver.js +51 -21
  70. package/dist/core/model-runtime.d.ts +73 -14
  71. package/dist/core/model-runtime.js +398 -104
  72. package/dist/core/models-store.d.ts +12 -7
  73. package/dist/core/models-store.js +85 -15
  74. package/dist/core/nested-tool-calls.d.ts +102 -0
  75. package/dist/core/nested-tool-calls.js +178 -0
  76. package/dist/core/package-manager.d.ts +8 -1
  77. package/dist/core/package-manager.js +144 -61
  78. package/dist/core/package-manager.test.js +5 -5
  79. package/dist/core/pi-manifest.d.ts +9 -0
  80. package/dist/core/pi-manifest.js +25 -0
  81. package/dist/core/prompt-templates.d.ts +6 -1
  82. package/dist/core/prompt-templates.js +61 -35
  83. package/dist/core/provider-composer.d.ts +44 -19
  84. package/dist/core/provider-composer.js +166 -64
  85. package/dist/core/radius.d.ts +2 -0
  86. package/dist/core/radius.js +2 -0
  87. package/dist/core/release-rpc.d.ts +137 -0
  88. package/dist/core/release-rpc.js +77 -0
  89. package/dist/core/remote-catalog-provider.d.ts +8 -1
  90. package/dist/core/remote-catalog-provider.js +25 -13
  91. package/dist/core/resource-loader.d.ts +12 -1
  92. package/dist/core/resource-loader.js +180 -45
  93. package/dist/core/runtime-credentials.d.ts +5 -5
  94. package/dist/core/runtime-credentials.js +11 -8
  95. package/dist/core/sdk.d.ts +16 -7
  96. package/dist/core/sdk.js +57 -24
  97. package/dist/core/session-manager.d.ts +45 -9
  98. package/dist/core/session-manager.js +124 -31
  99. package/dist/core/settings-diagnostics.d.ts +8 -0
  100. package/dist/core/settings-diagnostics.js +20 -0
  101. package/dist/core/settings-manager.d.ts +62 -32
  102. package/dist/core/settings-manager.js +147 -69
  103. package/dist/core/skills.d.ts +5 -2
  104. package/dist/core/skills.js +58 -35
  105. package/dist/core/slash-commands.js +2 -1
  106. package/dist/core/source-info.d.ts +8 -0
  107. package/dist/core/source-info.js +16 -0
  108. package/dist/core/subagent-rpc.d.ts +110 -0
  109. package/dist/core/subagent-rpc.js +60 -0
  110. package/dist/core/system-prompt.d.ts +9 -3
  111. package/dist/core/system-prompt.js +9 -12
  112. package/dist/core/system-prompt.test.js +2 -7
  113. package/dist/core/tools/bash.d.ts +12 -0
  114. package/dist/core/tools/bash.js +33 -2
  115. package/dist/core/tools/edit-diff.d.ts +0 -5
  116. package/dist/core/tools/edit-diff.js +2 -5
  117. package/dist/core/tools/edit.d.ts +4 -0
  118. package/dist/core/tools/edit.js +31 -11
  119. package/dist/core/tools/find.d.ts +7 -0
  120. package/dist/core/tools/find.js +16 -19
  121. package/dist/core/tools/grep.d.ts +4 -0
  122. package/dist/core/tools/grep.js +5 -1
  123. package/dist/core/tools/index.d.ts +1 -1
  124. package/dist/core/tools/index.js +11 -2
  125. package/dist/core/tools/ls.d.ts +4 -0
  126. package/dist/core/tools/ls.js +5 -1
  127. package/dist/core/tools/output-accumulator.d.ts +11 -0
  128. package/dist/core/tools/output-accumulator.js +40 -10
  129. package/dist/core/tools/read.d.ts +17 -2
  130. package/dist/core/tools/read.js +23 -2
  131. package/dist/core/tools/render-utils.d.ts +6 -0
  132. package/dist/core/tools/render-utils.js +26 -0
  133. package/dist/core/tools/renderers/bash.js +19 -35
  134. package/dist/core/tools/renderers/edit.js +5 -4
  135. package/dist/core/tools/renderers/index.d.ts +2 -2
  136. package/dist/core/tools/renderers/read.js +3 -2
  137. package/dist/core/tools/tool-definition-wrapper.d.ts +5 -3
  138. package/dist/core/tools/tool-definition-wrapper.js +3 -1
  139. package/dist/core/tools/truncate.d.ts +14 -0
  140. package/dist/core/tools/truncate.js +29 -0
  141. package/dist/core/tools/write.d.ts +4 -0
  142. package/dist/core/tools/write.js +6 -2
  143. package/dist/core/trust-manager.js +3 -1
  144. package/dist/core/usage-totals.d.ts +2 -0
  145. package/dist/core/usage-totals.js +23 -0
  146. package/dist/core/virtual-models.d.ts +116 -0
  147. package/dist/core/virtual-models.js +123 -0
  148. package/dist/defaults/models.json +32 -0
  149. package/dist/defaults/settings.json +1 -9
  150. package/dist/extensions/agent-browser.ts +9 -0
  151. package/dist/extensions/codemode/execute.d.ts +15 -0
  152. package/dist/extensions/codemode/execute.js +633 -0
  153. package/dist/extensions/codemode/execute.lazy.d.ts +2 -0
  154. package/dist/extensions/codemode/execute.lazy.js +2 -0
  155. package/dist/extensions/codemode/index.d.ts +20 -0
  156. package/dist/extensions/codemode/index.js +31 -0
  157. package/dist/extensions/codemode/renderer.d.ts +11 -0
  158. package/dist/extensions/codemode/renderer.js +136 -0
  159. package/dist/extensions/codemode/tool.d.ts +129 -0
  160. package/dist/extensions/codemode/tool.js +275 -0
  161. package/dist/extensions/context-compaction-reminder.ts +1 -1
  162. package/dist/extensions/grep-app/index.ts +2 -10
  163. package/dist/extensions/herdr-agent-state.ts +1 -1
  164. package/dist/extensions/{pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/index.d.ts → index.d.ts} +0 -1
  165. package/dist/extensions/index.js +12 -0
  166. package/dist/extensions/jev/classifier-context.ts +54 -0
  167. package/dist/extensions/jev/classifier.test.ts +85 -0
  168. package/dist/extensions/jev/classifier.ts +105 -0
  169. package/dist/extensions/jev/decisions.test.ts +35 -47
  170. package/dist/extensions/jev/decisions.ts +58 -104
  171. package/dist/extensions/jev/test-support.ts +33 -38
  172. package/dist/extensions/jev-advisory-lifecycle.test.ts +12 -12
  173. package/dist/extensions/jev-advisory-memory.test.ts +9 -9
  174. package/dist/extensions/jev-advisory-recommendations.test.ts +8 -8
  175. package/dist/extensions/jev-ask-tool.test.ts +41 -45
  176. package/dist/extensions/jev-ask-tool.ts +10 -38
  177. package/dist/extensions/jev-find-source.test.ts +26 -0
  178. package/dist/extensions/jev-find-source.ts +58 -19
  179. package/dist/{core → extensions}/llama/client.d.ts +2 -0
  180. package/dist/{core → extensions}/llama/client.js +7 -3
  181. package/dist/{core → extensions}/llama/index.js +13 -2
  182. package/dist/{core → extensions}/llama/provider.d.ts +1 -1
  183. package/dist/extensions/llama/provider.js +235 -0
  184. package/dist/extensions/mcp/cli.d.ts +20 -0
  185. package/dist/extensions/mcp/cli.js +496 -0
  186. package/dist/extensions/mcp/cli.lazy.d.ts +2 -0
  187. package/dist/extensions/mcp/cli.lazy.js +2 -0
  188. package/dist/extensions/mcp/config.d.ts +83 -0
  189. package/dist/extensions/mcp/config.js +193 -0
  190. package/dist/extensions/mcp/index.d.ts +78 -0
  191. package/dist/extensions/mcp/index.js +1201 -0
  192. package/dist/extensions/mcp/log.d.ts +15 -0
  193. package/dist/extensions/mcp/log.js +65 -0
  194. package/dist/extensions/mcp/oauth.d.ts +97 -0
  195. package/dist/extensions/mcp/oauth.js +401 -0
  196. package/dist/extensions/mcp/resources.d.ts +41 -0
  197. package/dist/extensions/mcp/resources.js +260 -0
  198. package/dist/extensions/mcp/runtime.d.ts +96 -0
  199. package/dist/extensions/mcp/runtime.js +412 -0
  200. package/dist/extensions/mcp/runtime.lazy.d.ts +2 -0
  201. package/dist/extensions/mcp/runtime.lazy.js +2 -0
  202. package/dist/extensions/mcp/tools.d.ts +86 -0
  203. package/dist/extensions/mcp/tools.js +252 -0
  204. package/dist/extensions/mcp/ui.d.ts +59 -0
  205. package/dist/extensions/mcp/ui.js +185 -0
  206. package/dist/extensions/package.json +1 -1
  207. package/dist/extensions/pi-graft/tools.ts +6 -0
  208. package/dist/extensions/pi-hermes-memory/CHANGELOG.md +25 -0
  209. package/dist/extensions/pi-hermes-memory/README.md +140 -4
  210. package/dist/extensions/pi-hermes-memory/package-lock.json +624 -2720
  211. package/dist/extensions/pi-hermes-memory/package.json +9 -7
  212. package/dist/extensions/pi-hermes-memory/scripts/benchmark-memory-startup.mjs +72 -0
  213. package/dist/extensions/pi-hermes-memory/scripts/check-production-install.mjs +107 -0
  214. package/dist/extensions/pi-hermes-memory/src/auto-consolidation-warning.ts +2 -1
  215. package/dist/extensions/pi-hermes-memory/src/config.ts +35 -0
  216. package/dist/extensions/pi-hermes-memory/src/constants.ts +62 -15
  217. package/dist/extensions/pi-hermes-memory/src/handlers/auto-consolidate.ts +374 -50
  218. package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +7 -4
  219. package/dist/extensions/pi-hermes-memory/src/handlers/correction-detector.ts +19 -14
  220. package/dist/extensions/pi-hermes-memory/src/handlers/insights.ts +75 -1
  221. package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +322 -22
  222. package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +8 -0
  223. package/dist/extensions/pi-hermes-memory/src/handlers/session-flush.ts +193 -54
  224. package/dist/extensions/pi-hermes-memory/src/handlers/skills-command.ts +6 -2
  225. package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +33 -5
  226. package/dist/extensions/pi-hermes-memory/src/index.ts +116 -47
  227. package/dist/extensions/pi-hermes-memory/src/memory-initialization.ts +101 -0
  228. package/dist/extensions/pi-hermes-memory/src/store/atomic-lock-coordinator.ts +10 -2
  229. package/dist/extensions/pi-hermes-memory/src/store/db.ts +34 -9
  230. package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +44 -8
  231. package/dist/extensions/pi-hermes-memory/src/store/schema.ts +3 -1
  232. package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +141 -0
  233. package/dist/extensions/pi-hermes-memory/src/store/standing-instructions.ts +17 -6
  234. package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +20 -10
  235. package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +1 -17
  236. package/dist/extensions/pi-hermes-memory/src/tools/session-search-tool.ts +2 -10
  237. package/dist/extensions/pi-hermes-memory/src/tools/skill-tool.ts +4 -8
  238. package/dist/extensions/pi-hermes-memory/src/types.ts +48 -0
  239. package/dist/extensions/pi-hermes-memory/tests/config.test.ts +108 -0
  240. package/dist/extensions/pi-hermes-memory/tests/handlers/auto-consolidate.test.ts +1185 -42
  241. package/dist/extensions/pi-hermes-memory/tests/handlers/insights.test.ts +57 -1
  242. package/dist/extensions/pi-hermes-memory/tests/handlers/lazy-memory-hooks.test.ts +128 -0
  243. package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +844 -1
  244. package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +16 -0
  245. package/dist/extensions/pi-hermes-memory/tests/handlers/session-flush.test.ts +512 -3
  246. package/dist/extensions/pi-hermes-memory/tests/handlers/skills-command.test.ts +38 -0
  247. package/dist/extensions/pi-hermes-memory/tests/handlers/sync-markdown-memories.test.ts +183 -2
  248. package/dist/extensions/pi-hermes-memory/tests/handlers/system-prompt.test.ts +1 -3
  249. package/dist/extensions/pi-hermes-memory/tests/index.test.ts +17 -0
  250. package/dist/extensions/pi-hermes-memory/tests/integration/corruption-recovery-integration.test.ts +21 -0
  251. package/dist/extensions/pi-hermes-memory/tests/lazy-startup.test.ts +313 -0
  252. package/dist/extensions/pi-hermes-memory/tests/memory-initialization.test.ts +182 -0
  253. package/dist/extensions/pi-hermes-memory/tests/prompt-injection.test.ts +184 -0
  254. package/dist/extensions/pi-hermes-memory/tests/skill-discovery-contract.test.ts +60 -0
  255. package/dist/extensions/pi-hermes-memory/tests/store/atomic-lock-lazy-probe.test.ts +80 -0
  256. package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +2 -0
  257. package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +79 -0
  258. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +268 -0
  259. package/dist/extensions/pi-hermes-memory/tests/store/standing-instructions.test.ts +29 -0
  260. package/dist/extensions/pi-hermes-memory/tests/store/usage-tracking.test.ts +170 -0
  261. package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +80 -1
  262. package/dist/extensions/pi-hermes-memory/tests/tools/skill-tool.test.ts +51 -0
  263. package/dist/extensions/pi-intercom/CHANGELOG.md +66 -0
  264. package/dist/extensions/pi-intercom/README.md +115 -12
  265. package/dist/extensions/pi-intercom/broker/broker.ts +304 -24
  266. package/dist/extensions/pi-intercom/broker/client.ts +9 -2
  267. package/dist/extensions/pi-intercom/broker/cross-machine-provenance.test.ts +63 -0
  268. package/dist/extensions/pi-intercom/broker/mailbox-persistence.test.ts +523 -0
  269. package/dist/extensions/pi-intercom/broker/paths.test.ts +4 -4
  270. package/dist/extensions/pi-intercom/broker/paths.ts +4 -2
  271. package/dist/extensions/pi-intercom/broker/protocol.ts +64 -0
  272. package/dist/extensions/pi-intercom/broker/spawn.test.ts +58 -169
  273. package/dist/extensions/pi-intercom/broker/spawn.ts +40 -87
  274. package/dist/extensions/pi-intercom/cli.mjs +6 -0
  275. package/dist/extensions/pi-intercom/cli.test.ts +428 -0
  276. package/dist/extensions/pi-intercom/cli.ts +343 -0
  277. package/dist/extensions/pi-intercom/config.test.ts +61 -1
  278. package/dist/extensions/pi-intercom/config.ts +53 -2
  279. package/dist/extensions/pi-intercom/cross-machine-discovery.test.ts +218 -0
  280. package/dist/extensions/pi-intercom/cross-machine-discovery.ts +140 -0
  281. package/dist/extensions/pi-intercom/cross-machine-envelope.test.ts +106 -0
  282. package/dist/extensions/pi-intercom/cross-machine-envelope.ts +92 -0
  283. package/dist/extensions/pi-intercom/cross-machine-integration.test.ts +25 -0
  284. package/dist/extensions/pi-intercom/cross-machine-transport.test.ts +106 -0
  285. package/dist/extensions/pi-intercom/cross-machine-transport.ts +110 -0
  286. package/dist/extensions/pi-intercom/extension-api.ts +24 -0
  287. package/dist/extensions/pi-intercom/handover.test.ts +88 -0
  288. package/dist/extensions/pi-intercom/handover.ts +115 -0
  289. package/dist/extensions/pi-intercom/herdr-location.test.ts +173 -0
  290. package/dist/extensions/pi-intercom/herdr-location.ts +137 -0
  291. package/dist/extensions/pi-intercom/human-priority.pi.test.ts +489 -0
  292. package/dist/extensions/pi-intercom/index.ts +770 -172
  293. package/dist/extensions/pi-intercom/intercom.integration.test.ts +869 -21
  294. package/dist/extensions/pi-intercom/package.json +12 -2
  295. package/dist/extensions/pi-intercom/project-agent.ts +1 -1
  296. package/dist/extensions/pi-intercom/release-readiness.test.ts +116 -0
  297. package/dist/extensions/pi-intercom/release-readiness.ts +93 -0
  298. package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +26 -2
  299. package/dist/extensions/pi-intercom/test/handover-picker.test.ts +134 -0
  300. package/dist/extensions/pi-intercom/test/inline-message.test.ts +43 -0
  301. package/dist/extensions/pi-intercom/types.d.ts +247 -0
  302. package/dist/extensions/pi-intercom/types.js +2 -0
  303. package/dist/extensions/pi-intercom/types.ts +39 -1
  304. package/dist/extensions/pi-intercom/ui/handover-picker.ts +318 -0
  305. package/dist/extensions/pi-intercom/ui/inline-message.ts +10 -3
  306. package/dist/extensions/pi-intercom/ui/session-list.ts +28 -15
  307. package/dist/extensions/pi-subagents/.github/workflows/release.yml +5 -1
  308. package/dist/extensions/pi-subagents/.github/workflows/test.yml +188 -18
  309. package/dist/extensions/pi-subagents/CHANGELOG.md +514 -1
  310. package/dist/extensions/pi-subagents/README.md +7 -5
  311. package/dist/extensions/pi-subagents/VISION.md +6 -0
  312. package/dist/extensions/pi-subagents/agents/reviewer.md +7 -5
  313. package/dist/extensions/pi-subagents/agents/worker.md +1 -1
  314. package/dist/extensions/pi-subagents/docs/agents.md +75 -35
  315. package/dist/extensions/pi-subagents/docs/configuration.md +156 -25
  316. package/dist/extensions/pi-subagents/docs/extension-api.md +121 -29
  317. package/dist/extensions/pi-subagents/docs/missions.md +46 -14
  318. package/dist/extensions/pi-subagents/docs/models.md +22 -84
  319. package/dist/extensions/pi-subagents/docs/observability.md +57 -24
  320. package/dist/extensions/pi-subagents/docs/standalone-background.md +59 -0
  321. package/dist/extensions/pi-subagents/docs/tool-reference.md +167 -116
  322. package/dist/extensions/pi-subagents/docs/watchdog.md +41 -10
  323. package/dist/extensions/pi-subagents/docs/workflows.md +239 -163
  324. package/dist/extensions/pi-subagents/examples/typed-gate/.pi/agents/classifier.md +14 -0
  325. package/dist/extensions/pi-subagents/examples/typed-gate/README.md +42 -0
  326. package/dist/extensions/pi-subagents/examples/typed-gate/classify +38 -0
  327. package/dist/extensions/pi-subagents/examples/typed-gate/workflow.js +32 -0
  328. package/dist/extensions/pi-subagents/index.ts +11 -3
  329. package/dist/extensions/pi-subagents/inspector-runner.mjs +3 -3
  330. package/dist/extensions/pi-subagents/package-lock.json +517 -1129
  331. package/dist/extensions/pi-subagents/package.json +22 -11
  332. package/dist/extensions/pi-subagents/prompts/council.md +7 -4
  333. package/dist/extensions/pi-subagents/prompts/parallel-review.md +2 -2
  334. package/dist/extensions/pi-subagents/prompts/review-loop.md +2 -2
  335. package/dist/extensions/pi-subagents/runner-peer-loader.mjs +21 -0
  336. package/dist/extensions/pi-subagents/runner-peer-preload.mjs +30 -0
  337. package/dist/extensions/pi-subagents/scripts/build-package.mjs +79 -0
  338. package/dist/extensions/pi-subagents/skills/council-mode/SKILL.md +2 -2
  339. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +46 -27
  340. package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +11 -7
  341. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +78 -73
  342. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +4 -5
  343. package/dist/extensions/pi-subagents/skills/pi-subagents/references/multi-lane-orchestration.md +10 -2
  344. package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +69 -67
  345. package/dist/extensions/pi-subagents/skills/pi-subagents/references/review-and-validation.md +3 -3
  346. package/dist/extensions/pi-subagents/src/agents/advertised-agent-prompt.ts +21 -10
  347. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +113 -113
  348. package/dist/extensions/pi-subagents/src/agents/agent-memory.ts +91 -4
  349. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +15 -9
  350. package/dist/extensions/pi-subagents/src/agents/agents.ts +432 -193
  351. package/dist/extensions/pi-subagents/src/agents/chain-serializer.ts +6 -1
  352. package/dist/extensions/pi-subagents/src/agents/global-npm-root.ts +58 -0
  353. package/dist/extensions/pi-subagents/src/agents/proactive-skills.ts +5 -2
  354. package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +22 -18
  355. package/dist/extensions/pi-subagents/src/agents/skills.ts +43 -10
  356. package/dist/extensions/pi-subagents/src/api/delegation.ts +20 -1
  357. package/dist/extensions/pi-subagents/src/api/inspectors.ts +27 -0
  358. package/dist/extensions/pi-subagents/src/api/preflight.ts +140 -62
  359. package/dist/extensions/pi-subagents/src/api/required-child-extensions.ts +6 -0
  360. package/dist/extensions/pi-subagents/src/api/shared-types.ts +2 -0
  361. package/dist/extensions/pi-subagents/src/extension/config.ts +24 -40
  362. package/dist/extensions/pi-subagents/src/extension/control-notices.ts +4 -1
  363. package/dist/extensions/pi-subagents/src/extension/doctor.ts +18 -15
  364. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +87 -13
  365. package/dist/extensions/pi-subagents/src/extension/herdr-pi-bridge.ts +162 -0
  366. package/dist/extensions/pi-subagents/src/extension/index.ts +331 -269
  367. package/dist/extensions/pi-subagents/src/extension/observability.ts +164 -0
  368. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +76 -37
  369. package/dist/extensions/pi-subagents/src/extension/release-readiness.ts +367 -0
  370. package/dist/extensions/pi-subagents/src/extension/reply-workflow-script.ts +67 -0
  371. package/dist/extensions/pi-subagents/src/extension/rpc.ts +42 -12
  372. package/dist/extensions/pi-subagents/src/extension/schemas.ts +116 -205
  373. package/dist/extensions/pi-subagents/src/extension/subagent-guide.ts +13 -5
  374. package/dist/extensions/pi-subagents/src/extension/tool-activation.ts +146 -0
  375. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +77 -90
  376. package/dist/extensions/pi-subagents/src/extension/upgrade-notice.ts +40 -0
  377. package/dist/extensions/pi-subagents/src/inspectors/actions.ts +148 -0
  378. package/dist/extensions/pi-subagents/src/inspectors/ghostty/actions.ts +74 -0
  379. package/dist/extensions/pi-subagents/src/inspectors/ghostty/plugin.ts +29 -0
  380. package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +100 -180
  381. package/dist/extensions/pi-subagents/src/inspectors/herdr/plugin.ts +20 -0
  382. package/dist/extensions/pi-subagents/src/inspectors/herdr/project-panes.ts +2 -2
  383. package/dist/extensions/pi-subagents/src/inspectors/{herdr/inspector-runner.ts → inspector-runner.ts} +13 -13
  384. package/dist/extensions/pi-subagents/src/inspectors/plugins.ts +75 -0
  385. package/dist/extensions/pi-subagents/src/inspectors/{herdr/session-roots-codec.ts → session-roots-codec.ts} +4 -15
  386. package/dist/extensions/pi-subagents/src/inspectors/{herdr/shell-command.ts → shell-command.ts} +1 -1
  387. package/dist/extensions/pi-subagents/src/inspectors/types.ts +51 -0
  388. package/dist/extensions/pi-subagents/src/integrations/herdr-status.ts +38 -53
  389. package/dist/extensions/pi-subagents/src/integrations/pi-web-session-liveness.ts +7 -1
  390. package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +53 -9
  391. package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +69 -55
  392. package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +7 -2
  393. package/dist/extensions/pi-subagents/src/missions/goal-driver.ts +45 -32
  394. package/dist/extensions/pi-subagents/src/missions/store.ts +11 -2
  395. package/dist/extensions/pi-subagents/src/missions/workflow-state.ts +1 -44
  396. package/dist/extensions/pi-subagents/src/policy/authority.ts +5 -1
  397. package/dist/extensions/pi-subagents/src/profiles/profiles.ts +30 -18
  398. package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +59 -9
  399. package/dist/extensions/pi-subagents/src/runs/background/active-run-index.ts +18 -2
  400. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +463 -248
  401. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +112 -66
  402. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +33 -20
  403. package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +47 -17
  404. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -5
  405. package/dist/extensions/pi-subagents/src/runs/background/auto-drain.ts +24 -11
  406. package/dist/extensions/pi-subagents/src/runs/background/await-async-run.ts +78 -0
  407. package/dist/extensions/pi-subagents/src/runs/background/binary-bootstrap.ts +66 -0
  408. package/dist/extensions/pi-subagents/src/runs/background/calendar-schedule.ts +90 -0
  409. package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +2 -2
  410. package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +19 -38
  411. package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +62 -3
  412. package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +82 -10
  413. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +272 -24
  414. package/dist/extensions/pi-subagents/src/runs/background/owned-process-tree.ts +30 -3
  415. package/dist/extensions/pi-subagents/src/runs/background/pid-namespace.ts +18 -0
  416. package/dist/extensions/pi-subagents/src/runs/background/process-terminal-candidate.ts +98 -0
  417. package/dist/extensions/pi-subagents/src/runs/background/process-terminal.ts +18 -97
  418. package/dist/extensions/pi-subagents/src/runs/background/result-delivery-ownership.ts +269 -7
  419. package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +14 -5
  420. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +77 -22
  421. package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +4 -3
  422. package/dist/extensions/pi-subagents/src/runs/background/retained-nested-route-tracker.ts +15 -3
  423. package/dist/extensions/pi-subagents/src/runs/background/run-child-session.ts +126 -45
  424. package/dist/extensions/pi-subagents/src/runs/background/run-id-resolver.ts +11 -6
  425. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +18 -7
  426. package/dist/extensions/pi-subagents/src/runs/background/runner-aliases.ts +43 -51
  427. package/dist/extensions/pi-subagents/src/runs/background/runner-child-launch.ts +8 -1
  428. package/dist/extensions/pi-subagents/src/runs/background/runner-child-sessions.ts +5 -4
  429. package/dist/extensions/pi-subagents/src/runs/background/runner-http-dispatcher.ts +119 -0
  430. package/dist/extensions/pi-subagents/src/runs/background/runner-startup-failure.ts +56 -0
  431. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +297 -69
  432. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +67 -16
  433. package/dist/extensions/pi-subagents/src/runs/background/steering.ts +21 -3
  434. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner-bootstrap.ts +276 -0
  435. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +660 -578
  436. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +177 -29
  437. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +77 -28
  438. package/dist/extensions/pi-subagents/src/runs/background/wait-subscriptions.ts +10 -4
  439. package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +7 -13
  440. package/dist/extensions/pi-subagents/src/runs/background/workflow-terminal-proof.ts +41 -23
  441. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +19 -8
  442. package/dist/extensions/pi-subagents/src/runs/foreground/async-stop-action.ts +130 -7
  443. package/dist/extensions/pi-subagents/src/runs/foreground/command-action.ts +41 -0
  444. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +267 -385
  445. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +4 -2
  446. package/dist/extensions/pi-subagents/src/runs/foreground/prompt-audit.ts +6 -10
  447. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +1158 -413
  448. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +3 -1
  449. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-foreground-steering.ts +2 -1
  450. package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +200 -74
  451. package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +133 -34
  452. package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +6 -1
  453. package/dist/extensions/pi-subagents/src/runs/shared/child-commands.ts +228 -0
  454. package/dist/extensions/pi-subagents/src/runs/shared/child-hooks.ts +18 -18
  455. package/dist/extensions/pi-subagents/src/runs/shared/child-launch-plan.ts +16 -4
  456. package/dist/extensions/pi-subagents/src/runs/shared/child-launch.ts +55 -12
  457. package/dist/extensions/pi-subagents/src/runs/shared/child-lifecycle.ts +6 -3
  458. package/dist/extensions/pi-subagents/src/runs/shared/child-runtime-config.ts +11 -1
  459. package/dist/extensions/pi-subagents/src/runs/shared/child-session.ts +367 -74
  460. package/dist/extensions/pi-subagents/src/runs/shared/child-tool-plan.ts +50 -86
  461. package/dist/extensions/pi-subagents/src/runs/shared/claude-code-adapter.ts +288 -0
  462. package/dist/extensions/pi-subagents/src/runs/shared/codex-exec-adapter.ts +129 -0
  463. package/dist/extensions/pi-subagents/src/runs/shared/cursor-agent-adapter.ts +114 -0
  464. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +5 -5
  465. package/dist/extensions/pi-subagents/src/runs/shared/effective-system-prompt.ts +33 -0
  466. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-contract.ts +49 -10
  467. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +61 -9
  468. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +16 -9
  469. package/dist/extensions/pi-subagents/src/runs/shared/external-job-bridge.ts +55 -1
  470. package/dist/extensions/pi-subagents/src/runs/shared/git-environment.ts +1 -1
  471. package/dist/extensions/pi-subagents/src/runs/shared/herdr-connection.ts +134 -0
  472. package/dist/extensions/pi-subagents/src/runs/shared/herdr-external-adapters.ts +169 -0
  473. package/dist/extensions/pi-subagents/src/runs/shared/herdr-machine.ts +279 -0
  474. package/dist/extensions/pi-subagents/src/runs/shared/herdr-pi-protocol.ts +59 -0
  475. package/dist/extensions/pi-subagents/src/runs/shared/herdr-placed-run.ts +263 -0
  476. package/dist/extensions/pi-subagents/src/runs/shared/mcp-config-sources.ts +6 -2
  477. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +108 -13
  478. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-grant.ts +23 -7
  479. package/dist/extensions/pi-subagents/src/runs/shared/model-resolution-diagnostic.ts +76 -0
  480. package/dist/extensions/pi-subagents/src/runs/shared/{model-fallback.ts → model-resolution.ts} +65 -245
  481. package/dist/extensions/pi-subagents/src/runs/shared/model-scope.ts +30 -11
  482. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +24 -3
  483. package/dist/extensions/pi-subagents/src/runs/shared/orca-progress-tabs.ts +5 -4
  484. package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +55 -7
  485. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +14 -4
  486. package/dist/extensions/pi-subagents/src/runs/shared/partial-output.ts +48 -0
  487. package/dist/extensions/pi-subagents/src/runs/shared/pi-spawn.ts +12 -4
  488. package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +88 -1
  489. package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +12 -3
  490. package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +160 -9
  491. package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +49 -35
  492. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +58 -19
  493. package/dist/extensions/pi-subagents/src/runs/shared/tool-availability.ts +2 -2
  494. package/dist/extensions/pi-subagents/src/runs/shared/tool-budget.ts +21 -0
  495. package/dist/extensions/pi-subagents/src/runs/shared/usage-reconciliation.ts +73 -0
  496. package/dist/extensions/pi-subagents/src/runs/shared/workflow-async-child-guidance.ts +18 -0
  497. package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-apply.ts +160 -0
  498. package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +42 -20
  499. package/dist/extensions/pi-subagents/src/runs/shared/worktree-lock.ts +29 -0
  500. package/dist/extensions/pi-subagents/src/runs/shared/worktree-setup-command.ts +27 -4
  501. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +94 -26
  502. package/dist/extensions/pi-subagents/src/shared/child-cache-retention.ts +43 -0
  503. package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +5 -3
  504. package/dist/extensions/pi-subagents/src/shared/disabled-features.ts +123 -0
  505. package/dist/extensions/pi-subagents/src/shared/extension-context.ts +14 -1
  506. package/dist/extensions/pi-subagents/src/shared/file-lease.ts +74 -0
  507. package/dist/extensions/pi-subagents/src/shared/fork-context.ts +27 -77
  508. package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +70 -10
  509. package/dist/extensions/pi-subagents/src/shared/model-info.ts +10 -1
  510. package/dist/extensions/pi-subagents/src/shared/opencode-session-headers.ts +30 -0
  511. package/dist/extensions/pi-subagents/src/shared/owner-record.ts +107 -0
  512. package/dist/extensions/pi-subagents/src/shared/package-version.ts +17 -0
  513. package/dist/extensions/pi-subagents/src/shared/parent-wake.ts +66 -0
  514. package/dist/extensions/pi-subagents/src/shared/process-identity.ts +87 -0
  515. package/dist/extensions/pi-subagents/src/shared/pruned-fork.ts +71 -58
  516. package/dist/extensions/pi-subagents/src/shared/required-child-extensions.ts +115 -0
  517. package/dist/extensions/pi-subagents/src/shared/settings-file-lease.ts +36 -0
  518. package/dist/extensions/pi-subagents/src/shared/settings.ts +7 -4
  519. package/dist/extensions/pi-subagents/src/shared/shortcuts.ts +1 -5
  520. package/dist/extensions/pi-subagents/src/shared/types.ts +155 -48
  521. package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +28 -2
  522. package/dist/extensions/pi-subagents/src/slash/delegation-request.ts +15 -1
  523. package/dist/extensions/pi-subagents/src/slash/prompt-template-bridge.ts +19 -4
  524. package/dist/extensions/pi-subagents/src/slash/prompt-workflows.ts +13 -2
  525. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +15 -15
  526. package/dist/extensions/pi-subagents/src/slash/subagent-cost.ts +46 -9
  527. package/dist/extensions/pi-subagents/src/slash/subagents-admin.ts +29 -16
  528. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +201 -26
  529. package/dist/extensions/pi-subagents/src/tui/fleet.ts +33 -16
  530. package/dist/extensions/pi-subagents/src/tui/render.ts +334 -103
  531. package/dist/extensions/pi-subagents/src/tui/running-tone.ts +28 -0
  532. package/dist/extensions/pi-subagents/src/watchdog/child-status.ts +27 -28
  533. package/dist/extensions/pi-subagents/src/watchdog/diff-tool.ts +47 -12
  534. package/dist/extensions/pi-subagents/src/watchdog/lsp-diagnostics.ts +2 -2
  535. package/dist/extensions/pi-subagents/src/watchdog/model-selection.ts +22 -2
  536. package/dist/extensions/pi-subagents/src/watchdog/permission-arbiter.ts +17 -17
  537. package/dist/extensions/pi-subagents/src/watchdog/register-child.ts +24 -8
  538. package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +43 -39
  539. package/dist/extensions/pi-subagents/src/watchdog/render.ts +2 -2
  540. package/dist/extensions/pi-subagents/src/watchdog/review.ts +127 -78
  541. package/dist/extensions/pi-subagents/src/watchdog/rules.ts +1 -1
  542. package/dist/extensions/pi-subagents/src/watchdog/runtime.ts +107 -31
  543. package/dist/extensions/pi-subagents/src/watchdog/scope.ts +1 -1
  544. package/dist/extensions/pi-subagents/src/watchdog/settings.ts +22 -14
  545. package/dist/extensions/pi-subagents/src/watchdog/tool-actions.ts +14 -13
  546. package/dist/extensions/pi-subagents/src/watchdog/turn-delta.ts +35 -6
  547. package/dist/extensions/pi-subagents/src/watchdog/types.ts +6 -4
  548. package/dist/extensions/pi-subagents/src/watchdog/warning-format.ts +2 -2
  549. package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +3 -3
  550. package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +500 -65
  551. package/dist/extensions/pi-subagents/src/workflows/structured-workflow-scripts.ts +177 -0
  552. package/dist/extensions/pi-subagents/src/workflows/workflow-checklist.ts +8 -2
  553. package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +5 -3
  554. package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +70 -10
  555. package/dist/extensions/pi-subagents/src/workflows/workflow-resources.ts +57 -18
  556. package/dist/extensions/pi-subagents/src/workflows/workflow-reuse.ts +120 -0
  557. package/dist/extensions/pi-subagents/src/workflows/workflow-revival.ts +123 -0
  558. package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +5 -2
  559. package/dist/extensions/pi-subagents/test/fixtures/cwd-workflow-child.ts +37 -0
  560. package/dist/extensions/pi-subagents/test/fixtures/herdr-allocation-lock-child.ts +16 -0
  561. package/dist/extensions/pi-subagents/test/fixtures/herdr-provision-child.ts +15 -0
  562. package/dist/extensions/pi-subagents/test/fixtures/native-nested-wait-provider.ts +76 -0
  563. package/dist/extensions/pi-subagents/test/fixtures/runner-bootstrap-harness.ts +36 -0
  564. package/dist/extensions/pi-subagents/test/fixtures/schedule-history-writer.mjs +48 -0
  565. package/dist/extensions/pi-subagents/test/fixtures/settings-race-writer.mjs +57 -0
  566. package/dist/extensions/pi-subagents/test/fixtures/workflow-cwd-access-failure.ts +33 -0
  567. package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +40 -7
  568. package/dist/extensions/pi-subagents/test/integration/async-attention-clearing.test.ts +192 -0
  569. package/dist/extensions/pi-subagents/test/integration/async-execution.part-1.test.ts +435 -276
  570. package/dist/extensions/pi-subagents/test/integration/async-execution.part-2.test.ts +435 -397
  571. package/dist/extensions/pi-subagents/test/integration/async-execution.part-3.test.ts +918 -497
  572. package/dist/extensions/pi-subagents/test/integration/async-execution.part-4.test.ts +264 -17
  573. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +185 -22
  574. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +3 -2
  575. package/dist/extensions/pi-subagents/test/integration/claude-code-dispatch.test.ts +127 -0
  576. package/dist/extensions/pi-subagents/test/integration/deadline-checkpoint.test.ts +126 -0
  577. package/dist/extensions/pi-subagents/test/integration/doctor-executor.test.ts +29 -1
  578. package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +88 -0
  579. package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +450 -13
  580. package/dist/extensions/pi-subagents/test/integration/foreign-workflow-steering.test.ts +10 -6
  581. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +105 -86
  582. package/dist/extensions/pi-subagents/test/integration/in-process-child.test.ts +403 -18
  583. package/dist/extensions/pi-subagents/test/integration/inline-workflow-visibility.test.ts +351 -0
  584. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +195 -10
  585. package/dist/extensions/pi-subagents/test/integration/model-resolution-diagnostic.test.ts +108 -0
  586. package/dist/extensions/pi-subagents/test/integration/nested-async-wait.test.ts +61 -0
  587. package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +5 -4
  588. package/dist/extensions/pi-subagents/test/integration/recovered-assistant-error.test.ts +1 -1
  589. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +6 -4
  590. package/dist/extensions/pi-subagents/test/integration/render-widget-mouse.test.ts +84 -0
  591. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +242 -16
  592. package/dist/extensions/pi-subagents/test/integration/result-publication.test.ts +2 -2
  593. package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +221 -4
  594. package/dist/extensions/pi-subagents/test/integration/single-execution.part-1.test.ts +1435 -248
  595. package/dist/extensions/pi-subagents/test/integration/single-execution.part-2.test.ts +454 -515
  596. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +140 -21
  597. package/dist/extensions/pi-subagents/test/integration/stop-all-background.test.ts +142 -0
  598. package/dist/extensions/pi-subagents/test/integration/structured-workflows.test.ts +105 -0
  599. package/dist/extensions/pi-subagents/test/integration/workflow-result-publication.test.ts +90 -11
  600. package/dist/extensions/pi-subagents/test/integration/workflow-steer-inbox.test.ts +18 -15
  601. package/dist/extensions/pi-subagents/test/integration/workflow-worktree-admission.test.ts +100 -0
  602. package/dist/extensions/pi-subagents/test/smoke/clean-install.mjs +106 -0
  603. package/dist/extensions/pi-subagents/test/smoke/npm-background.mjs +43 -0
  604. package/dist/extensions/pi-subagents/test/smoke/packed-runner-selection.mjs +42 -0
  605. package/dist/extensions/pi-subagents/test/smoke/runner-loader-capability.mjs +50 -0
  606. package/dist/extensions/pi-subagents/test/smoke/sdk-child.ts +57 -0
  607. package/dist/extensions/pi-subagents/test/smoke/{pi085-extension.ts → sdk-extension.ts} +2 -2
  608. package/dist/extensions/pi-subagents/test/smoke/standalone-background.mjs +140 -0
  609. package/dist/extensions/pi-subagents/test/smoke/standalone-fault.ts +43 -0
  610. package/dist/extensions/pi-subagents/test/smoke/standalone-matrix.mjs +65 -0
  611. package/dist/extensions/pi-subagents/test/smoke/standalone-observer.ts +8 -0
  612. package/dist/extensions/pi-subagents/test/smoke/standalone-parent.ts +220 -0
  613. package/dist/extensions/pi-subagents/test/smoke/standalone-provider.ts +58 -0
  614. package/dist/extensions/pi-subagents/test/smoke/standalone-release.json +8 -0
  615. package/dist/extensions/pi-subagents/test/smoke/standalone-revival.ts +109 -0
  616. package/dist/extensions/pi-subagents/test/smoke/standalone-shared.ts +79 -0
  617. package/dist/extensions/pi-subagents/test/smoke/tool-activation.test.ts +128 -0
  618. package/dist/extensions/pi-subagents/test/support/async-execution-fixture.ts +6 -25
  619. package/dist/extensions/pi-subagents/test/support/async-result-timeout-evidence.ts +61 -0
  620. package/dist/extensions/pi-subagents/test/support/fake-child-session.ts +130 -9
  621. package/dist/extensions/pi-subagents/test/support/foreign-workflow-steer-host.mjs +15 -7
  622. package/dist/extensions/pi-subagents/test/support/helpers.ts +11 -14
  623. package/dist/extensions/pi-subagents/test/support/isolated-temp-root.mjs +21 -3
  624. package/dist/extensions/pi-subagents/test/support/native-peer-loader.mjs +15 -0
  625. package/dist/extensions/pi-subagents/test/support/node-command.ts +29 -6
  626. package/dist/extensions/pi-subagents/test/support/notify-diagnostics-fixture.ts +5 -3
  627. package/dist/extensions/pi-subagents/test/support/single-execution-fixture.ts +7 -15
  628. package/dist/extensions/pi-subagents/test/support/watchdog-stable-host-loader.mjs +23 -0
  629. package/dist/extensions/pi-subagents/test/unit/acceptance-compaction.test.ts +3 -3
  630. package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +158 -155
  631. package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +52 -1
  632. package/dist/extensions/pi-subagents/test/unit/advertised-agent-prompt.test.ts +21 -17
  633. package/dist/extensions/pi-subagents/test/unit/advertised-agent-refresh.test.ts +105 -36
  634. package/dist/extensions/pi-subagents/test/unit/advertisement-barrier.test.ts +151 -0
  635. package/dist/extensions/pi-subagents/test/unit/agent-disabled.test.ts +1 -2
  636. package/dist/extensions/pi-subagents/test/unit/agent-eject-disable.test.ts +33 -3
  637. package/dist/extensions/pi-subagents/test/unit/agent-end-auto-drain.test.ts +149 -0
  638. package/dist/extensions/pi-subagents/test/unit/agent-exclude-dirs.test.ts +246 -0
  639. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +62 -87
  640. package/dist/extensions/pi-subagents/test/unit/agent-global-root-override.test.ts +86 -0
  641. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +398 -48
  642. package/dist/extensions/pi-subagents/test/unit/agent-memory.test.ts +126 -1
  643. package/dist/extensions/pi-subagents/test/unit/agent-name-resolution.test.ts +75 -0
  644. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +94 -42
  645. package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +73 -3
  646. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +428 -2
  647. package/dist/extensions/pi-subagents/test/unit/async-permission-session.test.ts +4 -4
  648. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +112 -1
  649. package/dist/extensions/pi-subagents/test/unit/async-result-timeout-evidence.test.ts +53 -0
  650. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +92 -4
  651. package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +58 -6
  652. package/dist/extensions/pi-subagents/test/unit/async-run-history.test.ts +123 -0
  653. package/dist/extensions/pi-subagents/test/unit/async-spawn-package-dir.test.ts +203 -0
  654. package/dist/extensions/pi-subagents/test/unit/async-spawn-preload.test.ts +26 -35
  655. package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +185 -0
  656. package/dist/extensions/pi-subagents/test/unit/authority-policy.test.ts +9 -1
  657. package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +106 -1
  658. package/dist/extensions/pi-subagents/test/unit/await-async-run.test.ts +202 -0
  659. package/dist/extensions/pi-subagents/test/unit/binary-async-spawn.test.ts +115 -0
  660. package/dist/extensions/pi-subagents/test/unit/binary-pi-spawn.test.ts +27 -0
  661. package/dist/extensions/pi-subagents/test/unit/calendar-schedule.test.ts +70 -0
  662. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +38 -0
  663. package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +10 -2
  664. package/dist/extensions/pi-subagents/test/unit/changelog-format.test.ts +11 -0
  665. package/dist/extensions/pi-subagents/test/unit/child-cache-retention.test.ts +87 -0
  666. package/dist/extensions/pi-subagents/test/unit/child-commands.test.ts +243 -0
  667. package/dist/extensions/pi-subagents/test/unit/child-external-job-bridge.test.ts +126 -0
  668. package/dist/extensions/pi-subagents/test/unit/child-launch-plan.test.ts +12 -1
  669. package/dist/extensions/pi-subagents/test/unit/child-lifecycle.test.ts +36 -0
  670. package/dist/extensions/pi-subagents/test/unit/child-runtime-config.test.ts +24 -0
  671. package/dist/extensions/pi-subagents/test/unit/child-session-commands.test.ts +162 -0
  672. package/dist/extensions/pi-subagents/test/unit/child-session-host-sdk.test.ts +226 -0
  673. package/dist/extensions/pi-subagents/test/unit/child-session-parent-providers.test.ts +200 -0
  674. package/dist/extensions/pi-subagents/test/unit/child-session-queued.test.ts +260 -0
  675. package/dist/extensions/pi-subagents/test/unit/child-tool-plan-permission-system.test.ts +3 -98
  676. package/dist/extensions/pi-subagents/test/unit/child-tool-plan.test.ts +222 -1
  677. package/dist/extensions/pi-subagents/test/unit/claude-code-adapter.test.ts +314 -0
  678. package/dist/extensions/pi-subagents/test/unit/claude-code-dispatch.test.ts +182 -0
  679. package/dist/extensions/pi-subagents/test/unit/codex-exec-adapter.test.ts +157 -0
  680. package/dist/extensions/pi-subagents/test/unit/command-action.test.ts +50 -0
  681. package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +25 -11
  682. package/dist/extensions/pi-subagents/test/unit/completion-replay.test.ts +3 -1
  683. package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +18 -0
  684. package/dist/extensions/pi-subagents/test/unit/control-notices.test.ts +7 -1
  685. package/dist/extensions/pi-subagents/test/unit/cursor-agent-adapter.test.ts +220 -0
  686. package/dist/extensions/pi-subagents/test/unit/default-extensions.test.ts +104 -32
  687. package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +138 -1
  688. package/dist/extensions/pi-subagents/test/unit/disabled-features.test.ts +227 -0
  689. package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +48 -9
  690. package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +7 -4
  691. package/dist/extensions/pi-subagents/test/unit/extension-lazy-loading.test.ts +21 -0
  692. package/dist/extensions/pi-subagents/test/unit/extension-maintenance-lifecycle.test.ts +66 -0
  693. package/dist/extensions/pi-subagents/test/unit/extension-module-preload.test.ts +49 -0
  694. package/dist/extensions/pi-subagents/test/unit/external-cli-runner.test.ts +104 -3
  695. package/dist/extensions/pi-subagents/test/unit/file-lease.test.ts +17 -0
  696. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +316 -0
  697. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +58 -7
  698. package/dist/extensions/pi-subagents/test/unit/fork-context.test.ts +25 -96
  699. package/dist/extensions/pi-subagents/test/unit/ghostty-inspector.test.ts +92 -0
  700. package/dist/extensions/pi-subagents/test/unit/global-npm-root.test.ts +108 -0
  701. package/dist/extensions/pi-subagents/test/unit/herdr-connection.test.ts +43 -0
  702. package/dist/extensions/pi-subagents/test/unit/herdr-external-adapters.test.ts +89 -0
  703. package/dist/extensions/pi-subagents/test/unit/herdr-inspector-bootstrap.test.ts +11 -20
  704. package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +113 -19
  705. package/dist/extensions/pi-subagents/test/unit/herdr-machine.test.ts +161 -0
  706. package/dist/extensions/pi-subagents/test/unit/herdr-native-placement.test.ts +187 -0
  707. package/dist/extensions/pi-subagents/test/unit/herdr-session-roots-codec.test.ts +7 -12
  708. package/dist/extensions/pi-subagents/test/unit/herdr-shell-command.test.ts +2 -2
  709. package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +182 -87
  710. package/dist/extensions/pi-subagents/test/unit/host-peer-runtime-imports.test.ts +68 -49
  711. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +295 -135
  712. package/dist/extensions/pi-subagents/test/unit/inspect-rpc.test.ts +3 -3
  713. package/dist/extensions/pi-subagents/test/unit/inspector-authority-policy.test.ts +144 -0
  714. package/dist/extensions/pi-subagents/test/unit/inspector-registration.test.ts +128 -0
  715. package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +49 -1
  716. package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-grant.test.ts +74 -1
  717. package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-resolution.test.ts +112 -0
  718. package/dist/extensions/pi-subagents/test/unit/mission-global-projection.test.ts +215 -0
  719. package/dist/extensions/pi-subagents/test/unit/mission-goal-driver.test.ts +65 -1
  720. package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +2 -1
  721. package/dist/extensions/pi-subagents/test/unit/model-resolution-diagnostic.test.ts +78 -0
  722. package/dist/extensions/pi-subagents/test/unit/model-resolution.test.ts +153 -0
  723. package/dist/extensions/pi-subagents/test/unit/model-scope.test.ts +43 -1
  724. package/dist/extensions/pi-subagents/test/unit/mutation-evidence.test.ts +1 -21
  725. package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +279 -2
  726. package/dist/extensions/pi-subagents/test/unit/nested-control-fanout.test.ts +73 -0
  727. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +297 -3
  728. package/dist/extensions/pi-subagents/test/unit/notify-diagnostics.test.ts +1 -1
  729. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +431 -23
  730. package/dist/extensions/pi-subagents/test/unit/observability.test.ts +198 -0
  731. package/dist/extensions/pi-subagents/test/unit/opencode-session-headers.test.ts +32 -0
  732. package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +89 -21
  733. package/dist/extensions/pi-subagents/test/unit/owned-process-tree.test.ts +31 -1
  734. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +18 -24
  735. package/dist/extensions/pi-subagents/test/unit/parent-wake.test.ts +206 -0
  736. package/dist/extensions/pi-subagents/test/unit/partial-output.test.ts +53 -0
  737. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +216 -32
  738. package/dist/extensions/pi-subagents/test/unit/pi-spawn-host-root.test.ts +82 -0
  739. package/dist/extensions/pi-subagents/test/unit/pi-subagents-policy-guidance.test.ts +28 -0
  740. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +193 -104
  741. package/dist/extensions/pi-subagents/test/unit/proactive-skills.test.ts +16 -1
  742. package/dist/extensions/pi-subagents/test/unit/process-identity.test.ts +75 -0
  743. package/dist/extensions/pi-subagents/test/unit/process-terminal.test.ts +17 -1
  744. package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +89 -9
  745. package/dist/extensions/pi-subagents/test/unit/prompt-audit-optional-peers.test.ts +6 -0
  746. package/dist/extensions/pi-subagents/test/unit/prompt-audit-provider-routing.test.ts +69 -0
  747. package/dist/extensions/pi-subagents/test/unit/prompt-template-bridge.test.ts +2 -2
  748. package/dist/extensions/pi-subagents/test/unit/prompt-workflows.test.ts +23 -1
  749. package/dist/extensions/pi-subagents/test/unit/pruned-fork.test.ts +117 -3
  750. package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +35 -14
  751. package/dist/extensions/pi-subagents/test/unit/readonly-drain-observation.test.ts +3 -2
  752. package/dist/extensions/pi-subagents/test/unit/release-readiness.test.ts +715 -0
  753. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +261 -9
  754. package/dist/extensions/pi-subagents/test/unit/reply-workflow-script.test.ts +37 -0
  755. package/dist/extensions/pi-subagents/test/unit/required-child-extensions.test.ts +114 -0
  756. package/dist/extensions/pi-subagents/test/unit/result-intercom.test.ts +11 -1
  757. package/dist/extensions/pi-subagents/test/unit/result-takeover.test.ts +332 -0
  758. package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +22 -2
  759. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +125 -18
  760. package/dist/extensions/pi-subagents/test/unit/run-child-session.test.ts +230 -0
  761. package/dist/extensions/pi-subagents/test/unit/run-id-resolver.test.ts +50 -1
  762. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +301 -4
  763. package/dist/extensions/pi-subagents/test/unit/runner-bootstrap.test.ts +182 -0
  764. package/dist/extensions/pi-subagents/test/unit/runner-http-dispatcher.test.ts +136 -0
  765. package/dist/extensions/pi-subagents/test/unit/runner-peer-loader.test.ts +68 -0
  766. package/dist/extensions/pi-subagents/test/unit/runner-peer-symlinks.test.ts +50 -0
  767. package/dist/extensions/pi-subagents/test/unit/running-tone.test.ts +13 -0
  768. package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +155 -4
  769. package/dist/extensions/pi-subagents/test/unit/schedule-claim-initialization.test.ts +71 -0
  770. package/dist/extensions/pi-subagents/test/unit/schedule-claim-preservation.test.ts +98 -0
  771. package/dist/extensions/pi-subagents/test/unit/schedule-history-transactions.test.ts +201 -0
  772. package/dist/extensions/pi-subagents/test/unit/scheduled-mission.test.ts +317 -0
  773. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +412 -11
  774. package/dist/extensions/pi-subagents/test/unit/scheduled-store-root.test.ts +2 -8
  775. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +70 -71
  776. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +748 -5
  777. package/dist/extensions/pi-subagents/test/unit/session-liveness-delivery.test.ts +337 -0
  778. package/dist/extensions/pi-subagents/test/unit/settings-atomic-save.test.ts +419 -0
  779. package/dist/extensions/pi-subagents/test/unit/settings-transactions.test.ts +88 -0
  780. package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +13 -1
  781. package/dist/extensions/pi-subagents/test/unit/skills-disable-model-invocation.test.ts +164 -0
  782. package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +35 -2
  783. package/dist/extensions/pi-subagents/test/unit/slash-bridge.test.ts +2 -2
  784. package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +334 -9
  785. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +170 -0
  786. package/dist/extensions/pi-subagents/test/unit/steering.test.ts +34 -5
  787. package/dist/extensions/pi-subagents/test/unit/structured-output-validation.test.ts +199 -0
  788. package/dist/extensions/pi-subagents/test/unit/structured-workflow-resources.test.ts +241 -0
  789. package/dist/extensions/pi-subagents/test/unit/subagent-control.test.ts +47 -38
  790. package/dist/extensions/pi-subagents/test/unit/subagent-cost.test.ts +97 -0
  791. package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +10 -0
  792. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +343 -44
  793. package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +410 -11
  794. package/dist/extensions/pi-subagents/test/unit/supervisor-ask-registration.test.ts +459 -22
  795. package/dist/extensions/pi-subagents/test/unit/temp-paths.test.ts +43 -3
  796. package/dist/extensions/pi-subagents/test/unit/timeout-defaults.test.ts +11 -1
  797. package/dist/extensions/pi-subagents/test/unit/tool-activation-stale-peer.test.ts +32 -0
  798. package/dist/extensions/pi-subagents/test/unit/tool-activation.test.ts +313 -0
  799. package/dist/extensions/pi-subagents/test/unit/tool-budget.test.ts +14 -0
  800. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +76 -89
  801. package/dist/extensions/pi-subagents/test/unit/typed-gate-output.test.ts +141 -0
  802. package/dist/extensions/pi-subagents/test/unit/upgrade-notice.test.ts +31 -0
  803. package/dist/extensions/pi-subagents/test/unit/usage-reconciliation-owners.test.ts +66 -0
  804. package/dist/extensions/pi-subagents/test/unit/usage-reconciliation.test.ts +23 -0
  805. package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +195 -1
  806. package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +3 -1
  807. package/dist/extensions/pi-subagents/test/unit/watchdog-child-status.test.ts +48 -45
  808. package/dist/extensions/pi-subagents/test/unit/watchdog-compaction-scope.test.ts +94 -0
  809. package/dist/extensions/pi-subagents/test/unit/watchdog-diff-tool.test.ts +48 -3
  810. package/dist/extensions/pi-subagents/test/unit/watchdog-native-scheduling.test.ts +107 -0
  811. package/dist/extensions/pi-subagents/test/unit/watchdog-permission-arbiter.test.ts +95 -7
  812. package/dist/extensions/pi-subagents/test/unit/watchdog-register-child.test.ts +79 -0
  813. package/dist/extensions/pi-subagents/test/unit/watchdog-render.test.ts +7 -4
  814. package/dist/extensions/pi-subagents/test/unit/watchdog-review.test.ts +111 -24
  815. package/dist/extensions/pi-subagents/test/unit/watchdog-rules.test.ts +1 -1
  816. package/dist/extensions/pi-subagents/test/unit/watchdog-runtime.test.ts +283 -2
  817. package/dist/extensions/pi-subagents/test/unit/watchdog-scope.test.ts +3 -0
  818. package/dist/extensions/pi-subagents/test/unit/watchdog-settings.test.ts +12 -1
  819. package/dist/extensions/pi-subagents/test/unit/watchdog-stable-host-layout.test.ts +23 -0
  820. package/dist/extensions/pi-subagents/test/unit/watchdog-tool-actions.test.ts +30 -0
  821. package/dist/extensions/pi-subagents/test/unit/watchdog-turn-delta.test.ts +39 -2
  822. package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +18 -1
  823. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +8 -4
  824. package/dist/extensions/pi-subagents/test/unit/workflow-child-summary.test.ts +10 -0
  825. package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +6 -3
  826. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +44 -1
  827. package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +28 -1
  828. package/dist/extensions/pi-subagents/test/unit/workflow-revival.test.ts +85 -0
  829. package/dist/extensions/pi-subagents/test/unit/workflow-scripts-feature.test.ts +177 -0
  830. package/dist/extensions/pi-subagents/test/unit/workflow-terminal-proof.test.ts +8 -0
  831. package/dist/extensions/pi-subagents/test/unit/workflow-worktree-admission.test.ts +29 -0
  832. package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +343 -4
  833. package/dist/extensions/pi-subagents/test/unit/worktree-lock.test.ts +123 -0
  834. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +252 -22
  835. package/dist/extensions/pi-subagents/tsconfig.build.json +13 -0
  836. package/dist/extensions/pi-tool-display/tests/custom-tool-overrides.test.ts +1 -1
  837. package/dist/extensions/pi-tool-display/tests/tool-overrides-config.test.ts +1 -1
  838. package/dist/extensions/pi-tool-display/tests/tool-overrides-mcp.test.ts +24 -1
  839. package/dist/extensions/pi-tool-display/tests/tool-overrides-registration.test.ts +6 -2
  840. package/dist/extensions/pi-web-agent/src/extension.ts +1 -5
  841. package/dist/extensions/pi-zentui/.github/workflows/ci.yml +67 -4
  842. package/dist/extensions/pi-zentui/AGENTS.md +3 -2
  843. package/dist/extensions/pi-zentui/README.md +60 -32
  844. package/dist/extensions/pi-zentui/docs/configuration.md +662 -51
  845. package/dist/extensions/pi-zentui/docs/footer-format.md +174 -5
  846. package/dist/extensions/pi-zentui/extensions/zentui/accent-rail-editor.ts +15 -4
  847. package/dist/extensions/pi-zentui/extensions/zentui/average-token-rate.ts +146 -0
  848. package/dist/extensions/pi-zentui/extensions/zentui/codex-quota-display.ts +34 -0
  849. package/dist/extensions/pi-zentui/extensions/zentui/codex-quota.ts +298 -0
  850. package/dist/extensions/pi-zentui/extensions/zentui/component-colors.ts +172 -0
  851. package/dist/extensions/pi-zentui/extensions/zentui/component-settings.ts +243 -0
  852. package/dist/extensions/pi-zentui/extensions/zentui/config.ts +851 -114
  853. package/dist/extensions/pi-zentui/extensions/zentui/custom-value-colors.ts +93 -0
  854. package/dist/extensions/pi-zentui/extensions/zentui/custom-variable-demand.ts +61 -0
  855. package/dist/extensions/pi-zentui/extensions/zentui/custom-variable-format.ts +80 -0
  856. package/dist/extensions/pi-zentui/extensions/zentui/custom-variables.ts +152 -0
  857. package/dist/extensions/pi-zentui/extensions/zentui/editor-metadata-format.ts +138 -23
  858. package/dist/extensions/pi-zentui/extensions/zentui/editor-mouse.ts +89 -0
  859. package/dist/extensions/pi-zentui/extensions/zentui/extension-status-controller.ts +148 -0
  860. package/dist/extensions/pi-zentui/extensions/zentui/extension-status-settings.ts +40 -0
  861. package/dist/extensions/pi-zentui/extensions/zentui/extension-status.ts +109 -1
  862. package/dist/extensions/pi-zentui/extensions/zentui/footer-format.ts +203 -23
  863. package/dist/extensions/pi-zentui/extensions/zentui/footer-layout.ts +80 -3
  864. package/dist/extensions/pi-zentui/extensions/zentui/footer-text.ts +1 -1
  865. package/dist/extensions/pi-zentui/extensions/zentui/footer.ts +432 -125
  866. package/dist/extensions/pi-zentui/extensions/zentui/format.ts +92 -4
  867. package/dist/extensions/pi-zentui/extensions/zentui/git.ts +47 -30
  868. package/dist/extensions/pi-zentui/extensions/zentui/github-status.ts +575 -0
  869. package/dist/extensions/pi-zentui/extensions/zentui/host-project-changes.ts +25 -0
  870. package/dist/extensions/pi-zentui/extensions/zentui/host-template-values.ts +29 -0
  871. package/dist/extensions/pi-zentui/extensions/zentui/icons.ts +53 -13
  872. package/dist/extensions/pi-zentui/extensions/zentui/index.ts +778 -258
  873. package/dist/extensions/pi-zentui/extensions/zentui/interaction-summary.ts +70 -5
  874. package/dist/extensions/pi-zentui/extensions/zentui/layered-editor.ts +55 -0
  875. package/dist/extensions/pi-zentui/extensions/zentui/live-context.ts +6 -1
  876. package/dist/extensions/pi-zentui/extensions/zentui/live-metadata-demand.ts +72 -0
  877. package/dist/extensions/pi-zentui/extensions/zentui/live-metadata-display.ts +21 -0
  878. package/dist/extensions/pi-zentui/extensions/zentui/live-metadata.ts +255 -0
  879. package/dist/extensions/pi-zentui/extensions/zentui/minimalist-editor.ts +476 -36
  880. package/dist/extensions/pi-zentui/extensions/zentui/minimalist-settings.ts +118 -0
  881. package/dist/extensions/pi-zentui/extensions/zentui/minimalist-template.ts +177 -0
  882. package/dist/extensions/pi-zentui/extensions/zentui/omp-editor-frame.ts +148 -0
  883. package/dist/extensions/pi-zentui/extensions/zentui/omp-statusline.ts +569 -0
  884. package/dist/extensions/pi-zentui/extensions/zentui/omp-template-lookups.ts +344 -0
  885. package/dist/extensions/pi-zentui/extensions/zentui/omp-template-metrics.ts +91 -0
  886. package/dist/extensions/pi-zentui/extensions/zentui/omp-template-modes.ts +323 -0
  887. package/dist/extensions/pi-zentui/extensions/zentui/omp-ui.ts +210 -0
  888. package/dist/extensions/pi-zentui/extensions/zentui/package-version.ts +30 -12
  889. package/dist/extensions/pi-zentui/extensions/zentui/project-demand.ts +46 -0
  890. package/dist/extensions/pi-zentui/extensions/zentui/project-discovery.ts +58 -0
  891. package/dist/extensions/pi-zentui/extensions/zentui/project-refresh.ts +10 -3
  892. package/dist/extensions/pi-zentui/extensions/zentui/project-state.ts +37 -0
  893. package/dist/extensions/pi-zentui/extensions/zentui/repository-root.ts +1 -0
  894. package/dist/extensions/pi-zentui/extensions/zentui/runtime.ts +119 -43
  895. package/dist/extensions/pi-zentui/extensions/zentui/selector-border.ts +40 -29
  896. package/dist/extensions/pi-zentui/extensions/zentui/settings-command.ts +1268 -722
  897. package/dist/extensions/pi-zentui/extensions/zentui/settings-keys.ts +59 -0
  898. package/dist/extensions/pi-zentui/extensions/zentui/settings-list-selection.ts +13 -0
  899. package/dist/extensions/pi-zentui/extensions/zentui/settings-previews.ts +11 -4
  900. package/dist/extensions/pi-zentui/extensions/zentui/state.ts +24 -11
  901. package/dist/extensions/pi-zentui/extensions/zentui/style.ts +6 -0
  902. package/dist/extensions/pi-zentui/extensions/zentui/telemetry.ts +113 -11
  903. package/dist/extensions/pi-zentui/extensions/zentui/thinking-experimental.ts +234 -46
  904. package/dist/extensions/pi-zentui/extensions/zentui/thinking-steps.ts +20 -5
  905. package/dist/extensions/pi-zentui/extensions/zentui/token-rate.ts +313 -0
  906. package/dist/extensions/pi-zentui/extensions/zentui/turn-summary-format.ts +59 -0
  907. package/dist/extensions/pi-zentui/extensions/zentui/turn-summary-rate.ts +52 -0
  908. package/dist/extensions/pi-zentui/extensions/zentui/ui.ts +640 -172
  909. package/dist/extensions/pi-zentui/extensions/zentui/user-message-styles.ts +72 -34
  910. package/dist/extensions/pi-zentui/extensions/zentui/user-message.ts +219 -34
  911. package/dist/extensions/pi-zentui/extensions/zentui/working-line.ts +495 -119
  912. package/dist/extensions/pi-zentui/omp.ts +157 -0
  913. package/dist/extensions/pi-zentui/package-lock.json +3762 -1507
  914. package/dist/extensions/pi-zentui/package.json +50 -12
  915. package/dist/extensions/pi-zentui/test/accent-rail-editor.test.ts +13 -2
  916. package/dist/extensions/pi-zentui/test/average-token-rate.test.ts +297 -0
  917. package/dist/extensions/pi-zentui/test/behavior-compatibility.mjs +89 -0
  918. package/dist/extensions/pi-zentui/test/codex-quota-lifecycle.test.ts +284 -0
  919. package/dist/extensions/pi-zentui/test/codex-quota-rendering.test.ts +466 -0
  920. package/dist/extensions/pi-zentui/test/codex-quota.test.ts +440 -0
  921. package/dist/extensions/pi-zentui/test/component-colors.test.ts +554 -0
  922. package/dist/extensions/pi-zentui/test/component-settings.test.ts +364 -0
  923. package/dist/extensions/pi-zentui/test/config-component-independence.test.ts +402 -0
  924. package/dist/extensions/pi-zentui/test/config-extension-status-choice.test.ts +233 -0
  925. package/dist/extensions/pi-zentui/test/config-hidden-extension-status-colors.test.ts +118 -0
  926. package/dist/extensions/pi-zentui/test/config-hidden-extension-status-placement.test.ts +142 -0
  927. package/dist/extensions/pi-zentui/test/config-minimalist-templates.test.ts +240 -0
  928. package/dist/extensions/pi-zentui/test/config-template-variables.test.ts +85 -0
  929. package/dist/extensions/pi-zentui/test/config.test.ts +80 -17
  930. package/dist/extensions/pi-zentui/test/custom-value-colors-integration.test.ts +453 -0
  931. package/dist/extensions/pi-zentui/test/custom-value-colors.test.ts +399 -0
  932. package/dist/extensions/pi-zentui/test/custom-variable-alias-prototypes.test.ts +177 -0
  933. package/dist/extensions/pi-zentui/test/custom-variable-consumers.test.ts +194 -0
  934. package/dist/extensions/pi-zentui/test/custom-variable-demand.test.ts +169 -0
  935. package/dist/extensions/pi-zentui/test/custom-variable-probe-reservation.test.ts +141 -0
  936. package/dist/extensions/pi-zentui/test/custom-variables-lifecycle.integration.test.ts +365 -0
  937. package/dist/extensions/pi-zentui/test/custom-variables.test.ts +330 -0
  938. package/dist/extensions/pi-zentui/test/editor-metadata-format.test.ts +121 -0
  939. package/dist/extensions/pi-zentui/test/editor-mouse.test.ts +507 -0
  940. package/dist/extensions/pi-zentui/test/editor-viewport-indicators.test.ts +247 -20
  941. package/dist/extensions/pi-zentui/test/extension-compliance.test.ts +204 -260
  942. package/dist/extensions/pi-zentui/test/extension-status-controller.test.ts +323 -0
  943. package/dist/extensions/pi-zentui/test/extension-status-lifecycle.integration.test.ts +466 -0
  944. package/dist/extensions/pi-zentui/test/extension-status-settings.test.ts +79 -0
  945. package/dist/extensions/pi-zentui/test/footer-alignment.test.ts +135 -0
  946. package/dist/extensions/pi-zentui/test/footer-authority.test.ts +69 -0
  947. package/dist/extensions/pi-zentui/test/footer-auto-compaction.test.ts +148 -0
  948. package/dist/extensions/pi-zentui/test/footer-format-cache.test.ts +186 -0
  949. package/dist/extensions/pi-zentui/test/footer-format.test.ts +154 -4
  950. package/dist/extensions/pi-zentui/test/footer-hidden.test.ts +312 -0
  951. package/dist/extensions/pi-zentui/test/footer-hyperlink.test.ts +22 -0
  952. package/dist/extensions/pi-zentui/test/footer-layout.test.ts +80 -0
  953. package/dist/extensions/pi-zentui/test/footer-thinking-level.test.ts +123 -0
  954. package/dist/extensions/pi-zentui/test/format.test.ts +75 -1
  955. package/dist/extensions/pi-zentui/test/git-probes.test.ts +182 -0
  956. package/dist/extensions/pi-zentui/test/github-status.test.ts +931 -0
  957. package/dist/extensions/pi-zentui/test/host-template-surfaces.test.ts +287 -0
  958. package/dist/extensions/pi-zentui/test/icons.test.ts +86 -16
  959. package/dist/extensions/pi-zentui/test/layered-editor.test.ts +53 -0
  960. package/dist/extensions/pi-zentui/test/live-context-integration.test.ts +154 -7
  961. package/dist/extensions/pi-zentui/test/live-context.test.ts +45 -0
  962. package/dist/extensions/pi-zentui/test/live-metadata-lifecycle.integration.test.ts +963 -0
  963. package/dist/extensions/pi-zentui/test/live-metadata.test.ts +767 -0
  964. package/dist/extensions/pi-zentui/test/minimalist-cache-hit-colors.test.ts +183 -0
  965. package/dist/extensions/pi-zentui/test/minimalist-editor.test.ts +222 -4
  966. package/dist/extensions/pi-zentui/test/minimalist-settings.test.ts +103 -0
  967. package/dist/extensions/pi-zentui/test/minimalist-templates.test.ts +489 -0
  968. package/dist/extensions/pi-zentui/test/omp-editor-composers.test.ts +324 -0
  969. package/dist/extensions/pi-zentui/test/omp-statusline.test.ts +579 -0
  970. package/dist/extensions/pi-zentui/test/omp-template-lookups.test.ts +630 -0
  971. package/dist/extensions/pi-zentui/test/omp-template-metrics.test.ts +72 -0
  972. package/dist/extensions/pi-zentui/test/omp-template-modes.test.ts +557 -0
  973. package/dist/extensions/pi-zentui/test/omp-ui.test.ts +93 -0
  974. package/dist/extensions/pi-zentui/test/package-contents.mjs +1 -0
  975. package/dist/extensions/pi-zentui/test/pi-version-policy.test.ts +37 -0
  976. package/dist/extensions/pi-zentui/test/project-demand-integration.test.ts +542 -0
  977. package/dist/extensions/pi-zentui/test/project-discovery.test.ts +412 -0
  978. package/dist/extensions/pi-zentui/test/project-refresh.test.ts +44 -0
  979. package/dist/extensions/pi-zentui/test/project-state.test.ts +38 -1
  980. package/dist/extensions/pi-zentui/test/responsive-dependencies.test.ts +7 -7
  981. package/dist/extensions/pi-zentui/test/runtime.test.ts +127 -2
  982. package/dist/extensions/pi-zentui/test/selesai-v030-gate.json +939 -0
  983. package/dist/extensions/pi-zentui/test/settings-command.test.ts +1330 -82
  984. package/dist/extensions/pi-zentui/test/settings-keys.test.ts +41 -0
  985. package/dist/extensions/pi-zentui/test/settings-list-selection.test.ts +88 -0
  986. package/dist/extensions/pi-zentui/test/settings-previews.test.ts +4 -1
  987. package/dist/extensions/pi-zentui/test/state.test.ts +15 -1
  988. package/dist/extensions/pi-zentui/test/telemetry-lifecycle-integration.test.ts +214 -12
  989. package/dist/extensions/pi-zentui/test/telemetry-snapshot.test.ts +246 -0
  990. package/dist/extensions/pi-zentui/test/thinking-experimental-cache.test.ts +246 -0
  991. package/dist/extensions/pi-zentui/test/thinking-experimental-rows.test.ts +22 -0
  992. package/dist/extensions/pi-zentui/test/thinking-experimental-tui.mjs +113 -51
  993. package/dist/extensions/pi-zentui/test/thinking-experimental.test.ts +576 -76
  994. package/dist/extensions/pi-zentui/test/thinking-steps.test.ts +23 -0
  995. package/dist/extensions/pi-zentui/test/token-rate.test.ts +450 -0
  996. package/dist/extensions/pi-zentui/test/turn-summary-format.test.ts +207 -0
  997. package/dist/extensions/pi-zentui/test/turn-summary-lifecycle.integration.test.ts +72 -5
  998. package/dist/extensions/pi-zentui/test/turn-summary-rate.test.ts +158 -0
  999. package/dist/extensions/pi-zentui/test/usage-lifecycle-integration.test.ts +421 -0
  1000. package/dist/extensions/pi-zentui/test/usage-snapshot.test.ts +154 -0
  1001. package/dist/extensions/pi-zentui/test/user-message-cache.test.ts +239 -0
  1002. package/dist/extensions/pi-zentui/test/user-message-native-reduced-capabilities.test.ts +61 -0
  1003. package/dist/extensions/pi-zentui/test/user-message-native.test.ts +447 -0
  1004. package/dist/extensions/pi-zentui/test/user-message-styles.test.ts +2 -2
  1005. package/dist/extensions/pi-zentui/test/working-line-editor-placement.test.ts +317 -0
  1006. package/dist/extensions/pi-zentui/test/working-line-generation-cache.test.ts +238 -0
  1007. package/dist/extensions/pi-zentui/test/working-line-lifecycle.integration.test.ts +674 -179
  1008. package/dist/extensions/pi-zentui/test/working-line-message-ownership.test.ts +239 -0
  1009. package/dist/extensions/pi-zentui/test/working-line-metric-animation.test.ts +284 -0
  1010. package/dist/extensions/pi-zentui/test/working-line-placement.test.ts +298 -0
  1011. package/dist/extensions/pi-zentui/test/working-line.test.ts +386 -18
  1012. package/dist/extensions/pi-zentui/test/wrapped-editor-consumers.integration.test.ts +579 -0
  1013. package/dist/extensions/pi-zentui/test/wrapped-editor-usage.integration.test.ts +298 -0
  1014. package/dist/extensions/pi-zentui/tsconfig.json +1 -1
  1015. package/dist/extensions/pi-zentui/vitest.host.config.ts +33 -0
  1016. package/dist/extensions/question/index.ts +1 -5
  1017. package/dist/extensions/rtk.test.ts +28 -15
  1018. package/dist/extensions/rtk.ts +22 -22
  1019. package/dist/extensions/skills-index/index.test.ts +99 -0
  1020. package/dist/extensions/skills-index/index.ts +105 -0
  1021. package/dist/extensions/skills-index/package.json +9 -0
  1022. package/dist/extensions/tokenin-onboarding.ts +52 -210
  1023. package/dist/extensions/tool-search/index.d.ts +11 -0
  1024. package/dist/extensions/tool-search/index.js +14 -0
  1025. package/dist/extensions/tool-search/tool.d.ts +72 -0
  1026. package/dist/extensions/tool-search/tool.js +188 -0
  1027. package/dist/index.d.ts +21 -9
  1028. package/dist/index.js +17 -5
  1029. package/dist/main.d.ts +10 -0
  1030. package/dist/main.js +107 -43
  1031. package/dist/migrations.js +4 -3
  1032. package/dist/modes/index.d.ts +2 -1
  1033. package/dist/modes/interactive/bug-report.js +4 -0
  1034. package/dist/modes/interactive/components/armin.d.ts +3 -0
  1035. package/dist/modes/interactive/components/armin.js +7 -5
  1036. package/dist/modes/interactive/components/assistant-message.js +1 -1
  1037. package/dist/modes/interactive/components/auth-url.d.ts +13 -0
  1038. package/dist/modes/interactive/components/auth-url.js +36 -0
  1039. package/dist/modes/interactive/components/bash-execution.d.ts +5 -1
  1040. package/dist/modes/interactive/components/bash-execution.js +17 -14
  1041. package/dist/modes/interactive/components/branch-summary-message.d.ts +2 -1
  1042. package/dist/modes/interactive/components/branch-summary-message.js +5 -2
  1043. package/dist/modes/interactive/components/compaction-summary-message.d.ts +2 -1
  1044. package/dist/modes/interactive/components/compaction-summary-message.js +5 -2
  1045. package/dist/modes/interactive/components/config-selector.js +13 -3
  1046. package/dist/modes/interactive/components/custom-editor.js +7 -0
  1047. package/dist/modes/interactive/components/custom-entry.d.ts +3 -1
  1048. package/dist/modes/interactive/components/custom-entry.js +8 -2
  1049. package/dist/modes/interactive/components/custom-message.js +1 -0
  1050. package/dist/modes/interactive/components/first-time-setup.d.ts +4 -4
  1051. package/dist/modes/interactive/components/first-time-setup.js +8 -2
  1052. package/dist/modes/interactive/components/footer.d.ts +7 -0
  1053. package/dist/modes/interactive/components/footer.js +44 -4
  1054. package/dist/modes/interactive/components/index.d.ts +0 -1
  1055. package/dist/modes/interactive/components/index.js +0 -1
  1056. package/dist/modes/interactive/components/login-dialog.d.ts +2 -0
  1057. package/dist/modes/interactive/components/login-dialog.js +11 -5
  1058. package/dist/modes/interactive/components/mermaid.d.ts +10 -0
  1059. package/dist/modes/interactive/components/mermaid.js +74 -0
  1060. package/dist/modes/interactive/components/model-selector.d.ts +14 -9
  1061. package/dist/modes/interactive/components/model-selector.js +79 -31
  1062. package/dist/modes/interactive/components/oauth-selector.d.ts +8 -2
  1063. package/dist/modes/interactive/components/oauth-selector.js +24 -21
  1064. package/dist/modes/interactive/components/pi-logo.d.ts +18 -0
  1065. package/dist/modes/interactive/components/pi-logo.js +36 -0
  1066. package/dist/modes/interactive/components/radius-login-selector.d.ts +14 -0
  1067. package/dist/modes/interactive/components/radius-login-selector.js +84 -0
  1068. package/dist/modes/interactive/components/scoped-models-selector.d.ts +4 -0
  1069. package/dist/modes/interactive/components/scoped-models-selector.js +26 -0
  1070. package/dist/modes/interactive/components/settings-selector.d.ts +8 -11
  1071. package/dist/modes/interactive/components/settings-selector.js +60 -102
  1072. package/dist/modes/interactive/components/skill-invocation-message.d.ts +2 -1
  1073. package/dist/modes/interactive/components/skill-invocation-message.js +5 -2
  1074. package/dist/modes/interactive/components/themed-text.d.ts +16 -0
  1075. package/dist/modes/interactive/components/themed-text.js +28 -0
  1076. package/dist/modes/interactive/components/tool-execution.d.ts +11 -18
  1077. package/dist/modes/interactive/components/tool-execution.js +34 -47
  1078. package/dist/modes/interactive/components/tree-selector.js +7 -0
  1079. package/dist/modes/interactive/components/user-message.d.ts +3 -1
  1080. package/dist/modes/interactive/components/user-message.js +14 -6
  1081. package/dist/modes/interactive/components/visual-truncate.d.ts +27 -3
  1082. package/dist/modes/interactive/components/visual-truncate.js +39 -6
  1083. package/dist/modes/interactive/external-editor.js +2 -1
  1084. package/dist/modes/interactive/interactive-mode.d.ts +41 -8
  1085. package/dist/modes/interactive/interactive-mode.js +854 -492
  1086. package/dist/modes/interactive/program-status-reporter.d.ts +33 -0
  1087. package/dist/modes/interactive/program-status-reporter.js +109 -0
  1088. package/dist/modes/interactive/theme/dark.json +59 -72
  1089. package/dist/modes/interactive/theme/light.json +57 -69
  1090. package/dist/modes/interactive/theme/system-theme.d.ts +54 -0
  1091. package/dist/modes/interactive/theme/system-theme.js +545 -0
  1092. package/dist/modes/interactive/theme/theme-controller.d.ts +46 -6
  1093. package/dist/modes/interactive/theme/theme-controller.js +127 -47
  1094. package/dist/modes/interactive/theme/theme-json.d.ts +1 -0
  1095. package/dist/modes/interactive/theme/theme-json.js +3 -1
  1096. package/dist/modes/interactive/theme/theme-schema.json +7 -2
  1097. package/dist/modes/interactive/theme/theme.d.ts +66 -39
  1098. package/dist/modes/interactive/theme/theme.js +243 -320
  1099. package/dist/modes/interactive/tui-renderer.d.ts +2 -1
  1100. package/dist/modes/interactive/tui-renderer.js +1 -0
  1101. package/dist/modes/json-event.d.ts +33 -0
  1102. package/dist/modes/json-event.js +28 -0
  1103. package/dist/modes/print-mode.js +12 -2
  1104. package/dist/modes/rpc/intercom-bridge.d.ts +14 -0
  1105. package/dist/modes/rpc/intercom-bridge.js +75 -0
  1106. package/dist/modes/rpc/intercom-bridge.test.js +65 -0
  1107. package/dist/modes/rpc/release-bridge.d.ts +35 -0
  1108. package/dist/modes/rpc/release-bridge.js +159 -0
  1109. package/dist/modes/rpc/release-bridge.test.d.ts +1 -0
  1110. package/dist/modes/rpc/release-bridge.test.js +347 -0
  1111. package/dist/modes/rpc/rpc-client.d.ts +43 -27
  1112. package/dist/modes/rpc/rpc-client.js +97 -37
  1113. package/dist/modes/rpc/rpc-intercom-transport.test.d.ts +1 -0
  1114. package/dist/modes/rpc/rpc-intercom-transport.test.js +85 -0
  1115. package/dist/modes/rpc/rpc-mode.d.ts +1 -13
  1116. package/dist/modes/rpc/rpc-mode.js +250 -34
  1117. package/dist/modes/rpc/rpc-release-transport.test.d.ts +1 -0
  1118. package/dist/modes/rpc/rpc-release-transport.test.js +329 -0
  1119. package/dist/modes/rpc/rpc-subagent-transport.test.d.ts +1 -0
  1120. package/dist/modes/rpc/rpc-subagent-transport.test.js +60 -0
  1121. package/dist/modes/rpc/rpc-types.d.ts +22 -23
  1122. package/dist/modes/rpc/rpc-types.js +0 -6
  1123. package/dist/modes/rpc/subagent-bridge.d.ts +23 -0
  1124. package/dist/modes/rpc/subagent-bridge.js +93 -0
  1125. package/dist/modes/rpc/test-fixtures/intercom-host.d.ts +1 -0
  1126. package/dist/modes/rpc/test-fixtures/intercom-host.js +13 -0
  1127. package/dist/package-manager-cli.js +16 -5
  1128. package/dist/rpc-entry.js +1 -0
  1129. package/dist/skills/pi-subagents/SKILL.md +109 -35
  1130. package/dist/skills/pi-subagents/references/constraints-and-recipes.md +38 -238
  1131. package/dist/skills/pi-subagents/references/execution-controls.md +181 -83
  1132. package/dist/skills/pi-subagents/references/management-authoring-rpc.md +9 -9
  1133. package/dist/skills/pi-subagents/references/multi-lane-orchestration.md +24 -2
  1134. package/dist/skills/pi-subagents/references/prompting-and-roles.md +121 -91
  1135. package/dist/skills/pi-subagents/references/review-and-validation.md +73 -0
  1136. package/dist/utils/ansi.d.ts +8 -0
  1137. package/dist/utils/ansi.js +30 -11
  1138. package/dist/utils/clipboard-image.js +14 -17
  1139. package/dist/utils/clipboard.d.ts +2 -0
  1140. package/dist/utils/clipboard.js +17 -11
  1141. package/dist/utils/frontmatter.js +2 -1
  1142. package/dist/utils/image-convert.d.ts +12 -0
  1143. package/dist/utils/image-convert.js +45 -6
  1144. package/dist/utils/image-resize-core.d.ts +12 -0
  1145. package/dist/utils/image-resize-core.js +5 -0
  1146. package/dist/utils/image-resize-worker.js +3 -2
  1147. package/dist/utils/image-resize.js +9 -10
  1148. package/dist/utils/mime.js +1 -1
  1149. package/dist/utils/output-files.d.ts +14 -0
  1150. package/dist/utils/output-files.js +29 -0
  1151. package/dist/utils/paths.d.ts +6 -3
  1152. package/dist/utils/paths.js +28 -5
  1153. package/dist/utils/shell.d.ts +1 -3
  1154. package/dist/utils/shell.js +3 -30
  1155. package/dist/utils/syntax-highlight.d.ts +1 -0
  1156. package/dist/utils/syntax-highlight.js +68 -2
  1157. package/dist/utils/tool-result-images.d.ts +20 -0
  1158. package/dist/utils/tool-result-images.js +47 -0
  1159. package/dist/utils/tools-manager.d.ts +5 -0
  1160. package/dist/utils/tools-manager.js +6 -6
  1161. package/dist/utils/version-check.d.ts +4 -0
  1162. package/dist/utils/version-check.js +20 -2
  1163. package/docs/cli-integration.md +104 -0
  1164. package/docs/cli.md +333 -0
  1165. package/docs/codemode.md +230 -0
  1166. package/docs/configuration.md +47 -0
  1167. package/docs/environment-variables.md +5 -0
  1168. package/docs/extensions.md +107 -30
  1169. package/docs/json.md +8 -4
  1170. package/docs/keybindings.md +10 -10
  1171. package/docs/mcp.md +262 -0
  1172. package/docs/models.md +104 -3
  1173. package/docs/providers.md +20 -2
  1174. package/docs/rpc-subagent.schema.json +491 -0
  1175. package/docs/rpc.md +223 -13
  1176. package/docs/sdk.md +41 -33
  1177. package/docs/security.md +21 -20
  1178. package/docs/settings.md +18 -46
  1179. package/docs/terminal-setup.md +14 -0
  1180. package/docs/virtual-models.md +114 -0
  1181. package/examples/extensions/jev-router.ts +113 -0
  1182. package/examples/extensions/tokenin-usage-widget.ts +124 -0
  1183. package/examples/rpc-client.ts +35 -0
  1184. package/examples/sdk/14-codemode-mcp.ts +67 -0
  1185. package/package.json +16 -8
  1186. package/dist/core/agent-session-auto-handoff.test.js +0 -195
  1187. package/dist/core/built-in-extensions.d.ts +0 -2
  1188. package/dist/core/built-in-extensions.js +0 -2
  1189. package/dist/core/llama/provider.js +0 -143
  1190. package/dist/core/settings-manager-auto-handoff.test.js +0 -53
  1191. package/dist/extensions/capability-gateway/catalog.ts +0 -177
  1192. package/dist/extensions/capability-gateway/index.test.ts +0 -226
  1193. package/dist/extensions/capability-gateway/index.ts +0 -669
  1194. package/dist/extensions/capability-gateway/integration.test.ts +0 -803
  1195. package/dist/extensions/capability-gateway/package.json +0 -16
  1196. package/dist/extensions/capability-gateway/routing.test.ts +0 -574
  1197. package/dist/extensions/capability-gateway/routing.ts +0 -403
  1198. package/dist/extensions/pi-subagents/runner-server-preload.mjs +0 -13
  1199. package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +0 -89
  1200. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +0 -259
  1201. package/dist/extensions/pi-subagents/src/runs/shared/llm-intent-arbiter.ts +0 -312
  1202. package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +0 -374
  1203. package/dist/extensions/pi-subagents/src/runs/shared/readonly-model-continuation.ts +0 -69
  1204. package/dist/extensions/pi-subagents/src/runs/shared/readonly-session-evidence.ts +0 -307
  1205. package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +0 -211
  1206. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/cli.d.ts +0 -3
  1207. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/register-bedrock.d.ts +0 -2
  1208. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/restore-sandbox-env.d.ts +0 -17
  1209. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/args.d.ts +0 -57
  1210. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/config-selector.d.ts +0 -16
  1211. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/file-processor.d.ts +0 -15
  1212. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/initial-message.d.ts +0 -18
  1213. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/list-models.d.ts +0 -9
  1214. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/project-trust.d.ts +0 -10
  1215. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/session-picker.d.ts +0 -10
  1216. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/startup-ui.d.ts +0 -20
  1217. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli.d.ts +0 -3
  1218. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/config.d.ts +0 -96
  1219. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-runtime.d.ts +0 -119
  1220. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-services.d.ts +0 -85
  1221. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session.d.ts +0 -620
  1222. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-guidance.d.ts +0 -5
  1223. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-storage.d.ts +0 -56
  1224. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/bash-executor.d.ts +0 -32
  1225. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/cache-stats.d.ts +0 -49
  1226. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/branch-summarization.d.ts +0 -93
  1227. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/compaction.d.ts +0 -128
  1228. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/index.d.ts +0 -7
  1229. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/utils.d.ts +0 -38
  1230. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/defaults.d.ts +0 -3
  1231. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/diagnostics.d.ts +0 -15
  1232. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/event-bus.d.ts +0 -9
  1233. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/exec.d.ts +0 -29
  1234. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/experimental.d.ts +0 -2
  1235. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/ansi-to-html.d.ts +0 -22
  1236. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/index.d.ts +0 -37
  1237. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/tool-renderer.d.ts +0 -34
  1238. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/index.d.ts +0 -12
  1239. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/loader.d.ts +0 -23
  1240. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/runner.d.ts +0 -171
  1241. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/types.d.ts +0 -1261
  1242. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/wrapper.d.ts +0 -20
  1243. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/footer-data-provider.d.ts +0 -54
  1244. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/http-dispatcher.d.ts +0 -22
  1245. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/index.d.ts +0 -13
  1246. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/keybindings.d.ts +0 -358
  1247. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/messages.d.ts +0 -77
  1248. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-config.d.ts +0 -512
  1249. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-registry.d.ts +0 -43
  1250. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-resolver.d.ts +0 -121
  1251. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-runtime.d.ts +0 -82
  1252. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/models-store.d.ts +0 -17
  1253. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/output-guard.d.ts +0 -7
  1254. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/package-manager.d.ts +0 -210
  1255. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/project-trust.d.ts +0 -15
  1256. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/prompt-templates.d.ts +0 -54
  1257. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-attribution.d.ts +0 -4
  1258. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-composer.d.ts +0 -55
  1259. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/radius.d.ts +0 -2
  1260. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/remote-catalog-provider.d.ts +0 -5
  1261. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resolve-config-value.d.ts +0 -30
  1262. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resource-loader.d.ts +0 -206
  1263. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/runtime-credentials.d.ts +0 -15
  1264. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/sdk.d.ts +0 -106
  1265. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-cwd.d.ts +0 -19
  1266. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-manager.d.ts +0 -356
  1267. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/settings-manager.d.ts +0 -297
  1268. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/skills.d.ts +0 -60
  1269. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/slash-commands.d.ts +0 -15
  1270. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/source-info.d.ts +0 -18
  1271. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/system-prompt.d.ts +0 -28
  1272. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/telemetry.d.ts +0 -3
  1273. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/timings.d.ts +0 -10
  1274. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/bash.d.ts +0 -68
  1275. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit-diff.d.ts +0 -106
  1276. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit.d.ts +0 -51
  1277. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/file-mutation-queue.d.ts +0 -6
  1278. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/find.d.ts +0 -35
  1279. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/grep.d.ts +0 -37
  1280. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/index.d.ts +0 -40
  1281. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/ls.d.ts +0 -37
  1282. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/output-accumulator.d.ts +0 -52
  1283. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/path-utils.d.ts +0 -10
  1284. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/read.d.ts +0 -35
  1285. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/render-utils.d.ts +0 -24
  1286. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/tool-definition-wrapper.d.ts +0 -14
  1287. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/truncate.d.ts +0 -70
  1288. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/write.d.ts +0 -26
  1289. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/trust-manager.d.ts +0 -36
  1290. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/usage-totals.d.ts +0 -19
  1291. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/client.d.ts +0 -61
  1292. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/huggingface.d.ts +0 -23
  1293. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/index.d.ts +0 -3
  1294. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/provider.d.ts +0 -10
  1295. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/ui.d.ts +0 -42
  1296. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/index.d.ts +0 -35
  1297. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/main.d.ts +0 -12
  1298. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/migrations.d.ts +0 -33
  1299. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/index.d.ts +0 -9
  1300. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/armin.d.ts +0 -34
  1301. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/assistant-message.d.ts +0 -22
  1302. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bash-execution.d.ts +0 -34
  1303. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bordered-loader.d.ts +0 -16
  1304. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/branch-summary-message.d.ts +0 -16
  1305. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/compaction-summary-message.d.ts +0 -16
  1306. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/config-selector.d.ts +0 -102
  1307. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/countdown-timer.d.ts +0 -14
  1308. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-editor.d.ts +0 -21
  1309. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-entry.d.ts +0 -19
  1310. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-message.d.ts +0 -20
  1311. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/daxnuts.d.ts +0 -23
  1312. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/diff.d.ts +0 -12
  1313. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/dynamic-border.d.ts +0 -15
  1314. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/earendil-announcement.d.ts +0 -5
  1315. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-editor.d.ts +0 -22
  1316. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-input.d.ts +0 -23
  1317. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-selector.d.ts +0 -26
  1318. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/first-time-setup.d.ts +0 -25
  1319. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/footer.d.ts +0 -32
  1320. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/index.d.ts +0 -34
  1321. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/keybinding-hints.d.ts +0 -13
  1322. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/login-dialog.d.ts +0 -52
  1323. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/model-selector.d.ts +0 -54
  1324. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/oauth-selector.d.ts +0 -33
  1325. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/scoped-models-selector.d.ts +0 -42
  1326. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector-search.d.ts +0 -23
  1327. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector.d.ts +0 -95
  1328. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/settings-selector.d.ts +0 -77
  1329. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/show-images-selector.d.ts +0 -10
  1330. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/skill-invocation-message.d.ts +0 -17
  1331. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/status-indicator.d.ts +0 -28
  1332. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/theme-selector.d.ts +0 -11
  1333. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/thinking-selector.d.ts +0 -11
  1334. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tool-execution.d.ts +0 -63
  1335. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tree-selector.d.ts +0 -94
  1336. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/trust-selector.d.ts +0 -23
  1337. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message-selector.d.ts +0 -30
  1338. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message.d.ts +0 -14
  1339. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/visual-truncate.d.ts +0 -24
  1340. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/interactive-mode.d.ts +0 -394
  1341. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/model-search.d.ts +0 -12
  1342. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme-controller.d.ts +0 -29
  1343. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme.d.ts +0 -120
  1344. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/print-mode.d.ts +0 -28
  1345. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/jsonl.d.ts +0 -17
  1346. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-client.d.ts +0 -246
  1347. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-mode.d.ts +0 -20
  1348. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-types.d.ts +0 -457
  1349. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/package-manager-cli.d.ts +0 -8
  1350. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/rpc-entry.d.ts +0 -3
  1351. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/ansi.d.ts +0 -2
  1352. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/changelog.d.ts +0 -22
  1353. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/child-process.d.ts +0 -18
  1354. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-image.d.ts +0 -11
  1355. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-native.d.ts +0 -11
  1356. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard.d.ts +0 -4
  1357. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/deprecation.d.ts +0 -4
  1358. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/exif-orientation.d.ts +0 -5
  1359. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/frontmatter.d.ts +0 -8
  1360. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/fs-watch.d.ts +0 -5
  1361. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/git.d.ts +0 -26
  1362. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/html.d.ts +0 -7
  1363. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-convert.d.ts +0 -10
  1364. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-process.d.ts +0 -18
  1365. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-core.d.ts +0 -30
  1366. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-worker.d.ts +0 -2
  1367. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize.d.ts +0 -16
  1368. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/json.d.ts +0 -3
  1369. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/mime.d.ts +0 -3
  1370. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/open-browser.d.ts +0 -9
  1371. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/paths.d.ts +0 -31
  1372. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/photon.d.ts +0 -21
  1373. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/pi-user-agent.d.ts +0 -2
  1374. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/shell.d.ts +0 -31
  1375. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/sleep.d.ts +0 -5
  1376. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/syntax-highlight.d.ts +0 -12
  1377. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/tools-manager.d.ts +0 -3
  1378. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/version-check.d.ts +0 -15
  1379. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/windows-self-update.d.ts +0 -3
  1380. package/dist/extensions/pi-subagents/test/smoke/pi085-child.ts +0 -31
  1381. package/dist/extensions/pi-subagents/test/smoke/pi085-clean-install.mjs +0 -74
  1382. package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +0 -150
  1383. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +0 -766
  1384. package/dist/extensions/pi-subagents/test/unit/llm-intent-arbiter.test.ts +0 -327
  1385. package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +0 -309
  1386. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +0 -1093
  1387. package/dist/extensions/pi-subagents/test/unit/readonly-model-continuation.test.ts +0 -94
  1388. package/dist/extensions/pi-subagents/test/unit/readonly-session-evidence.test.ts +0 -1329
  1389. package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +0 -153
  1390. package/dist/extensions/pi-zentui/extensions/zentui/accent-rail-layout-patch.ts +0 -457
  1391. package/dist/extensions/pi-zentui/test/accent-rail-layout-patch.test.ts +0 -669
  1392. package/dist/extensions/pi-zentui/test/thinking-experimental-docs.test.ts +0 -51
  1393. package/dist/modes/interactive/components/daxnuts.d.ts +0 -22
  1394. package/dist/modes/interactive/components/daxnuts.js +0 -139
  1395. /package/dist/core/{agent-session-auto-handoff.test.d.ts → agent-session-custom-tools.test.d.ts} +0 -0
  1396. /package/dist/{core → extensions}/llama/huggingface.d.ts +0 -0
  1397. /package/dist/{core → extensions}/llama/huggingface.js +0 -0
  1398. /package/dist/{core → extensions}/llama/index.d.ts +0 -0
  1399. /package/dist/{core → extensions}/llama/ui.d.ts +0 -0
  1400. /package/dist/{core → extensions}/llama/ui.js +0 -0
  1401. /package/dist/{core/settings-manager-auto-handoff.test.d.ts → modes/rpc/intercom-bridge.test.d.ts} +0 -0
@@ -2,7 +2,7 @@
2
2
  * Unit tests for auto-consolidation — triggerConsolidation and /memory-consolidate command.
3
3
  */
4
4
 
5
- import { describe, it, beforeEach, before, after } from "node:test";
5
+ import { describe, it, beforeEach, afterEach, before, after } from "node:test";
6
6
  import assert from "node:assert/strict";
7
7
  import { readFileSync } from "node:fs";
8
8
  import * as fs from "node:fs/promises";
@@ -12,22 +12,30 @@ import { registerConsolidateCommand, triggerConsolidation } from "../../src/hand
12
12
  import { resolveWatchedChildPiInvocation } from "../../src/handlers/pi-child-process.js";
13
13
  import { MemoryStore } from "../../src/store/memory-store.js";
14
14
  import { AtomicLockCoordinator } from "../../src/store/atomic-lock-coordinator.js";
15
- import { DEFAULT_CONSOLIDATION_TIMEOUT_MS, ENTRY_DELIMITER } from "../../src/constants.js";
15
+ import { DatabaseManager } from "../../src/store/db.js";
16
+ import { addMemory, recordSearchHits } from "../../src/store/sqlite-memory-store.js";
17
+ import {
18
+ DEFAULT_CONSOLIDATION_CHUNK_CHARS,
19
+ MAX_CONSOLIDATION_ROUNDS,
20
+ DEFAULT_CONSOLIDATION_TIMEOUT_MS,
21
+ ENTRY_DELIMITER,
22
+ } from "../../src/constants.js";
23
+ import { takeChunk } from "../../src/handlers/auto-consolidate.js";
16
24
 
17
25
  // ─── Mock infrastructure ───
18
26
 
19
27
  let execCalls: any[];
20
28
  let directCalls: unknown[][];
21
29
 
22
- const directTransportLlmConfig = { reviewTransport: "direct" as const };
30
+ const directTransportLlmConfig = { reviewTransport: "direct" as const, consolidationChunking: true };
23
31
 
24
32
  function createDirectCtx(): { model: unknown; modelRegistry: unknown; _tag: string } {
25
33
  return { model: {}, modelRegistry: {}, _tag: "consolidation-direct-ctx" };
26
34
  }
27
35
 
28
36
  function makeDirectDeps(
29
- result: { ok: boolean; appliedCount: number } | "throw",
30
- ): { runDirectMemoryCompletion: (...args: unknown[]) => Promise<{ ok: boolean; appliedCount: number }> } {
37
+ result: { ok: boolean; appliedCount: number; fallbackReason?: string } | "throw",
38
+ ): { runDirectMemoryCompletion: (...args: unknown[]) => Promise<{ ok: boolean; appliedCount: number; fallbackReason?: string }> } {
31
39
  return {
32
40
  runDirectMemoryCompletion: async (...args: unknown[]) => {
33
41
  directCalls.push(args);
@@ -94,6 +102,11 @@ const mockStore = {
94
102
  getAllFailureEntries: () => ["failure lesson 1", "failure lesson 2"],
95
103
  getStorageIdentity: async (target: string) => path.join("mock-store", target),
96
104
  loadFromDisk: async () => {},
105
+ // Mechanics tests exercise the subprocess handshake, so the fixture store
106
+ // reports itself over its capacity goal — a healthy store would clean-no-op
107
+ // before spawning a child.
108
+ capacityGoal: () => 10,
109
+ capacityUsage: () => 1000,
97
110
  } as any;
98
111
 
99
112
  async function settle(ms = 10) {
@@ -139,13 +152,18 @@ async function runManualConsolidate(timeoutMs?: number): Promise<void> {
139
152
  // ─── Tests ───
140
153
 
141
154
  describe("triggerConsolidation", () => {
142
- beforeEach(() => {
155
+ beforeEach(async () => {
143
156
  execCalls = [];
157
+ // Fresh lock dir per test: the shared lock file couples otherwise
158
+ // independent tests through lease-release timing on Windows.
159
+ process.env.PI_HERMES_CONSOLIDATION_LOCK_DIR = await fs.mkdtemp(
160
+ path.join(os.tmpdir(), "pi-consolidation-locks-"),
161
+ );
144
162
  });
145
163
 
146
164
  it("builds prompt with current entries and calls pi.exec", async () => {
147
165
  const pi = createMockPi();
148
- await triggerConsolidation(pi, mockStore, "memory");
166
+ await triggerConsolidation(pi, mockStore, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
149
167
 
150
168
  assert.strictEqual(execCalls.length, 1, "should call pi.exec once");
151
169
  const args = logicalChildArgs(execCalls[0]);
@@ -157,12 +175,12 @@ describe("triggerConsolidation", () => {
157
175
  assert.ok(prompt.includes("memory"), "prompt should reference target");
158
176
  });
159
177
 
160
- it("returns { consolidated: true } on success (exit code 0)", async () => {
178
+ it("reports an honest no-shrink result when the child exits 0 without shrinking", async () => {
161
179
  const pi = createMockPi({ code: 0, stdout: "Done", stderr: "" });
162
- const result = await triggerConsolidation(pi, mockStore, "memory");
180
+ const result = await triggerConsolidation(pi, mockStore, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
163
181
 
164
- assert.strictEqual(result.consolidated, true);
165
- assert.strictEqual(result.error, undefined);
182
+ assert.strictEqual(result.consolidated, false, "exit 0 without shrinking is not success");
183
+ assert.ok(result.error?.includes("could not shrink the remaining"), result.error);
166
184
  });
167
185
 
168
186
  it("clears a failed release before the next consolidation", async () => {
@@ -177,12 +195,12 @@ describe("triggerConsolidation", () => {
177
195
 
178
196
  try {
179
197
  const pi = createMockPi();
180
- const first = await triggerConsolidation(pi, mockStore, "memory");
181
- const second = await triggerConsolidation(pi, mockStore, "memory");
198
+ const first = await triggerConsolidation(pi, mockStore, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
199
+ const second = await triggerConsolidation(pi, mockStore, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
182
200
 
183
- assert.strictEqual(first.consolidated, true);
184
- assert.strictEqual(second.consolidated, true);
185
- assert.strictEqual(execCalls.length, 2);
201
+ assert.strictEqual(first.consolidated, false, "a no-shrink child is honestly reported");
202
+ assert.strictEqual(second.consolidated, false);
203
+ assert.strictEqual(execCalls.length, 2, "release clearing must not block the next consolidation");
186
204
  assert.ok(deleteAttempts >= 4);
187
205
  } finally {
188
206
  prototype.deleteOwnedLock = originalDeleteOwnedLock;
@@ -206,9 +224,9 @@ describe("triggerConsolidation", () => {
206
224
  } as any;
207
225
 
208
226
  await withLockWait("0", async () => {
209
- const first = triggerConsolidation(pi, mockStore, "memory");
227
+ const first = triggerConsolidation(pi, mockStore, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
210
228
  await execStarted;
211
- const second = triggerConsolidation(pi, mockStore, "memory");
229
+ const second = triggerConsolidation(pi, mockStore, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
212
230
  const raced = await Promise.race([
213
231
  second.then((result) => ({ result })),
214
232
  settle(100).then(() => ({ timeout: true as const })),
@@ -244,16 +262,20 @@ describe("triggerConsolidation", () => {
244
262
  } as any;
245
263
 
246
264
  await withLockWait("2000", async () => {
247
- const first = triggerConsolidation(pi, mockStore, "memory");
265
+ const first = triggerConsolidation(pi, mockStore, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
248
266
  await firstExecStarted;
249
- const second = triggerConsolidation(pi, mockStore, "memory");
267
+ const second = triggerConsolidation(pi, mockStore, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
250
268
  await settle(20);
251
269
  releaseExecs.forEach((release) => release());
252
270
 
253
271
  const [firstResult, secondResult] = await Promise.all([first, second]);
254
- assert.strictEqual(firstResult.consolidated, true);
255
- assert.strictEqual(secondResult.consolidated, true, "the queued caller should consolidate, not hard-fail");
272
+ // The mock children never shrink the store, so both runs honestly
273
+ // report a no-shrink partial — the mechanic under test is that the
274
+ // queued caller WAITS and runs its own child instead of hard-failing.
275
+ assert.strictEqual(firstResult.consolidated, false);
276
+ assert.strictEqual(secondResult.consolidated, false, "the queued caller should run its own round, not hard-fail");
256
277
  assert.strictEqual(secondResult.deferred, undefined);
278
+ assert.ok(secondResult.error?.includes("could not shrink the remaining"), secondResult.error);
257
279
  assert.strictEqual(execCalls.length, 2);
258
280
  });
259
281
  });
@@ -266,6 +288,8 @@ describe("triggerConsolidation", () => {
266
288
  getAllFailureEntries: () => [],
267
289
  getStorageIdentity: async (target: string) => path.join("shrinking-store", target),
268
290
  loadFromDisk: async () => { entries = ["merged"]; },
291
+ capacityGoal: () => 10,
292
+ capacityUsage: () => entries.join(ENTRY_DELIMITER).length,
269
293
  } as any;
270
294
 
271
295
  const releaseExecs: Array<() => void> = [];
@@ -284,9 +308,9 @@ describe("triggerConsolidation", () => {
284
308
  } as any;
285
309
 
286
310
  await withLockWait("2000", async () => {
287
- const first = triggerConsolidation(pi, shrinkingStore, "memory");
311
+ const first = triggerConsolidation(pi, shrinkingStore, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
288
312
  await firstExecStarted;
289
- const second = triggerConsolidation(pi, shrinkingStore, "memory");
313
+ const second = triggerConsolidation(pi, shrinkingStore, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
290
314
  await settle(20);
291
315
  releaseExecs.forEach((release) => release());
292
316
 
@@ -302,8 +326,17 @@ describe("triggerConsolidation", () => {
302
326
  memoryDir: path.join(root, name),
303
327
  memoryCharLimit: 5_000,
304
328
  userCharLimit: 5_000,
329
+ memoryMode: "policy-only",
305
330
  } as any));
306
331
  await Promise.all(stores.map((store) => store.loadFromDisk()));
332
+ // Seed both stores over their capacity goal — a healthy store is a clean
333
+ // no-op and would never reach the concurrent-children mechanic under test.
334
+ for (const store of stores) {
335
+ for (let i = 0; i < 10; i++) {
336
+ const r = await store.add("memory", `concurrent-store-entry-${i}-${"x".repeat(580)}`);
337
+ assert.ok(r.success, `seed ${i} should succeed`);
338
+ }
339
+ }
307
340
 
308
341
  let started = 0;
309
342
  let markFirstStarted!: () => void;
@@ -316,7 +349,10 @@ describe("triggerConsolidation", () => {
316
349
  started++;
317
350
  if (started === 1) markFirstStarted();
318
351
  if (started === 2) markBothStarted();
319
- await new Promise<void>((resolve) => { releases.push(resolve); });
352
+ if (started <= 2) {
353
+ // Round 1 of each store hangs until both children have started.
354
+ await new Promise<void>((resolve) => { releases.push(resolve); });
355
+ }
320
356
  return { code: 0, stdout: "Done", stderr: "" };
321
357
  },
322
358
  } as any;
@@ -334,16 +370,16 @@ describe("triggerConsolidation", () => {
334
370
  await Promise.allSettled([first, second]);
335
371
 
336
372
  assert.strictEqual(raced, "both-started");
337
- assert.strictEqual(started, 2);
373
+ assert.ok(started >= 2, "both distinct stores must run their own child");
338
374
  } finally {
339
375
  releases.forEach((release) => release());
340
- await fs.rm(root, { recursive: true, force: true });
376
+ await fs.rm(root, { recursive: true, force: true }).catch(() => {});
341
377
  }
342
378
  });
343
379
 
344
380
  it("returns { consolidated: false } on failure (non-zero exit code)", async () => {
345
381
  const pi = createMockPi({ code: 1, stdout: "", stderr: "some error" });
346
- const result = await triggerConsolidation(pi, mockStore, "memory");
382
+ const result = await triggerConsolidation(pi, mockStore, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
347
383
 
348
384
  assert.strictEqual(result.consolidated, false);
349
385
  assert.ok(result.error, "should have error message");
@@ -440,10 +476,10 @@ it("returns { consolidated: false } when pi.exec throws", async () => {
440
476
  undefined,
441
477
  60000,
442
478
  "memory",
443
- { llmModelOverride: "openrouter/deepseek/deepseek-v4-flash" },
479
+ { llmModelOverride: "openrouter/deepseek/deepseek-v4-flash", consolidationChunking: true },
444
480
  );
445
481
 
446
- assert.strictEqual(result.consolidated, true);
482
+ assert.strictEqual(result.consolidated, false, "the mock child shrinks nothing — reported honestly");
447
483
  assert.strictEqual(execCalls.length, 2, "should retry once without overrides");
448
484
  assert.deepStrictEqual(logicalChildArgs(execCalls[0]).slice(0, 6), [
449
485
  "-p",
@@ -478,14 +514,14 @@ it("returns { consolidated: false } when pi.exec throws", async () => {
478
514
  undefined,
479
515
  60000,
480
516
  "memory",
481
- { llmModelOverride: "openrouter/deepseek/deepseek-v4-flash" },
517
+ { llmModelOverride: "openrouter/deepseek/deepseek-v4-flash", consolidationChunking: true },
482
518
  );
483
519
 
484
520
  assert.strictEqual(result.consolidated, false);
485
521
  assert.strictEqual(execCalls.length, 1, "should not retry generic consolidation failures");
486
522
  });
487
523
 
488
- it("handles empty entries gracefully", async () => {
524
+ it("handles empty entries as a clean no-op", async () => {
489
525
  const emptyStore = {
490
526
  getMemoryEntries: () => [],
491
527
  getUserEntries: () => [],
@@ -494,10 +530,11 @@ it("returns { consolidated: false } when pi.exec throws", async () => {
494
530
  } as any;
495
531
 
496
532
  const pi = createMockPi();
497
- await triggerConsolidation(pi, emptyStore, "memory");
533
+ const result = await triggerConsolidation(pi, emptyStore, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
498
534
 
499
- const prompt = childPrompt(execCalls[0]);
500
- assert.ok(prompt.includes("(empty)"), "prompt should show (empty) for empty entries");
535
+ assert.strictEqual(execCalls.length, 0, "an empty store spawns no child");
536
+ assert.strictEqual(result.consolidated, true);
537
+ assert.strictEqual(result.rounds, 0);
501
538
  });
502
539
 
503
540
  describe("direct transport", () => {
@@ -551,11 +588,38 @@ it("returns { consolidated: false } when pi.exec throws", async () => {
551
588
  makeDirectDeps({ ok: true, appliedCount: 0 }),
552
589
  );
553
590
 
554
- assert.strictEqual(result.consolidated, true);
591
+ assert.strictEqual(result.consolidated, false, "the fallback child shrank nothing — reported honestly");
592
+ assert.ok(result.error?.includes("could not shrink the remaining"), result.error);
555
593
  assert.strictEqual(directCalls.length, 1);
556
594
  assert.strictEqual(execCalls.length, 1, "empty direct result must fall back to subprocess");
557
595
  });
558
596
 
597
+ it("returns terminal on empty_response without acquiring the lock or spawning a child (#235)", async () => {
598
+ const pi = createMockPi();
599
+ const directCtx = createDirectCtx();
600
+ const result = await triggerConsolidation(
601
+ pi,
602
+ mockStore,
603
+ "memory",
604
+ undefined,
605
+ 60000,
606
+ "memory",
607
+ directTransportLlmConfig,
608
+ directCtx,
609
+ null,
610
+ null,
611
+ makeDirectDeps({ ok: true, appliedCount: 0, fallbackReason: "empty_response" }),
612
+ );
613
+
614
+ // An empty completion is terminal: the subprocess child would run the
615
+ // same model against the same server-side thinking default and fail
616
+ // the same way (#197), so it must not even be attempted.
617
+ assert.strictEqual(result.consolidated, false);
618
+ assert.match(result.error ?? "", /returned an empty completion; no consolidation attempted/);
619
+ assert.strictEqual(directCalls.length, 1);
620
+ assert.strictEqual(execCalls.length, 0, "empty completion is terminal — no subprocess");
621
+ });
622
+
559
623
  it("falls back to subprocess when direct transport returns ok false", async () => {
560
624
  const pi = createMockPi();
561
625
  const directCtx = createDirectCtx();
@@ -573,7 +637,7 @@ it("returns { consolidated: false } when pi.exec throws", async () => {
573
637
  makeDirectDeps({ ok: false, appliedCount: 0 }),
574
638
  );
575
639
 
576
- assert.strictEqual(result.consolidated, true);
640
+ assert.strictEqual(result.consolidated, false, "the fallback child shrank nothing — reported honestly");
577
641
  assert.strictEqual(directCalls.length, 1);
578
642
  assert.strictEqual(execCalls.length, 1, "failed direct result must fall back to subprocess");
579
643
  });
@@ -595,7 +659,7 @@ it("returns { consolidated: false } when pi.exec throws", async () => {
595
659
  makeDirectDeps("throw"),
596
660
  );
597
661
 
598
- assert.strictEqual(result.consolidated, true);
662
+ assert.strictEqual(result.consolidated, false, "the fallback child shrank nothing — reported honestly");
599
663
  assert.strictEqual(directCalls.length, 1);
600
664
  assert.strictEqual(execCalls.length, 1, "thrown direct error must fall back to subprocess");
601
665
  });
@@ -616,7 +680,7 @@ it("returns { consolidated: false } when pi.exec throws", async () => {
616
680
  makeDirectDeps({ ok: true, appliedCount: 3 }),
617
681
  );
618
682
 
619
- assert.strictEqual(result.consolidated, true);
683
+ assert.strictEqual(result.consolidated, false, "the fallback child shrank nothing — reported honestly");
620
684
  assert.strictEqual(directCalls.length, 0, "direct path must be skipped without directCtx");
621
685
  assert.strictEqual(execCalls.length, 1, "subprocess-only path must still consolidate");
622
686
  });
@@ -651,9 +715,11 @@ describe("registerConsolidateCommand", () => {
651
715
  getUserEntries: () => [],
652
716
  getStorageIdentity: async (target: string) => path.join("project-store", target),
653
717
  loadFromDisk: async () => { projectReloaded = true; },
718
+ capacityGoal: () => 10,
719
+ capacityUsage: () => 100,
654
720
  } as any;
655
721
 
656
- registerConsolidateCommand(pi, mockStore, 60000, projectStore, "demo-project");
722
+ registerConsolidateCommand(pi, mockStore, 60000, projectStore, "demo-project", { consolidationChunking: true });
657
723
  await handler({}, {
658
724
  signal: undefined,
659
725
  ui: {
@@ -677,8 +743,8 @@ describe("registerConsolidateCommand", () => {
677
743
  assert.ok(statuses.some(([key, text]) => key === "pi-hermes-memory:consolidation" && text?.includes("Consolidating memory")), "should publish busy progress");
678
744
  assert.deepStrictEqual(statuses.at(-1), ["pi-hermes-memory:consolidation", undefined], "should clear busy progress when done");
679
745
  const finalNotification = notifications[notifications.length - 1] ?? "";
680
- assert.ok(finalNotification.includes("failure: ✅ consolidated"), "final notification should include failure result");
681
- assert.ok(finalNotification.includes("project:demo-project: ✅ consolidated"), "final notification should include project result");
746
+ assert.ok(finalNotification.includes("failure: ❌"), "final notification should include the failure result");
747
+ assert.ok(finalNotification.includes("project:demo-project: ❌"), "final notification should include the project result");
682
748
  });
683
749
 
684
750
  it("passes the configured timeout through to the manual consolidate child", async () => {
@@ -987,4 +1053,1081 @@ describe("MemoryStore auto-consolidation integration", () => {
987
1053
  "a successful-but-ineffective consolidation is not a consolidation failure",
988
1054
  );
989
1055
  });
1056
+
1057
+ it("add() surfaces a partial consolidation note when the retry still fails", async () => {
1058
+ const store = await storeWithConsolidator("partial", async () => (
1059
+ { consolidated: true, partial: true, rounds: 1, error: "time budget exhausted" } as any
1060
+ ));
1061
+
1062
+ const result = await store.add("memory", "b".repeat(20));
1063
+
1064
+ assert.ok(!result.success, "add should still fail when nothing was freed");
1065
+ assert.ok(
1066
+ result.error!.includes("Consolidation is incomplete: time budget exhausted"),
1067
+ result.error,
1068
+ );
1069
+ assert.ok(
1070
+ !result.error!.includes("attempted but failed"),
1071
+ "partial progress is not a consolidation failure",
1072
+ );
1073
+ });
1074
+ });
1075
+
1076
+
1077
+ /** Simulate the child by rewriting the store markdown file directly. */
1078
+ async function removeEntryFromDisk(store: MemoryStore, strippedText: string): Promise<void> {
1079
+ const filePath = path.join((store as any).memoryDir, "MEMORY.md");
1080
+ const raw = await fs.readFile(filePath, "utf-8");
1081
+ const blocks = raw.split(ENTRY_DELIMITER);
1082
+ const marker = strippedText.slice(0, 40);
1083
+ const kept = blocks.filter((block) => !block.includes(marker));
1084
+ assert.ok(kept.length < blocks.length, `child should find entry '${marker}' in the store file`);
1085
+ await fs.writeFile(filePath, kept.join(ENTRY_DELIMITER), "utf-8");
1086
+ }
1087
+
1088
+ function parsePromptBatch(prompt: string): string[] {
1089
+ const marker = "--- Current Memory Entries ---";
1090
+ const start = prompt.indexOf(marker);
1091
+ assert.ok(start >= 0, "prompt should contain the entries section");
1092
+ const end = prompt.indexOf("Use memory_add", start);
1093
+ const body = prompt.slice(start + marker.length, end);
1094
+ return body
1095
+ .split(ENTRY_DELIMITER)
1096
+ .map((entry) => entry.trim())
1097
+ .filter((entry) => entry.length > 0 && entry !== "(empty)");
1098
+ }
1099
+
1100
+
1101
+ // ─── Chunked subprocess consolidation ───
1102
+
1103
+ describe("chunked subprocess consolidation", () => {
1104
+ let MEMORY_ROOT = "";
1105
+ let storeSeq = 0;
1106
+
1107
+ before(async () => {
1108
+ MEMORY_ROOT = await fs.mkdtemp(path.join(os.tmpdir(), "pi-consolidation-chunk-"));
1109
+ });
1110
+
1111
+ after(async () => {
1112
+ try { await fs.rm(MEMORY_ROOT, { recursive: true, force: true }); } catch { /* ignore */ }
1113
+ });
1114
+
1115
+ beforeEach(() => {
1116
+ execCalls = [];
1117
+ });
1118
+
1119
+ /**
1120
+ * A real on-disk store in its OWN fresh directory (shared dirs leak entries
1121
+ * between tests and change the batch math), with a realistic 5000-char
1122
+ * capacity goal. policy-only lets seeds exceed the cap so the chunked path
1123
+ * has work to do. Entries are uniquely marked because memory-tool removal
1124
+ * matches by normalized substring — look-alike filler would cross-match.
1125
+ */
1126
+ async function makeOverChunkStore(entryCount: number, entryChars = 600, memoryCharLimit = 5000): Promise<MemoryStore> {
1127
+ const memoryDir = path.join(MEMORY_ROOT, `store-${++storeSeq}`);
1128
+ const store = new MemoryStore({
1129
+ memoryCharLimit,
1130
+ userCharLimit: 100,
1131
+ memoryMode: "policy-only",
1132
+ nudgeInterval: 10,
1133
+ reviewEnabled: false,
1134
+ flushOnCompact: false,
1135
+ flushOnShutdown: false,
1136
+ flushMinTurns: 6,
1137
+ autoConsolidate: false,
1138
+ correctionDetection: false,
1139
+ nudgeToolCalls: 15,
1140
+ memoryDir,
1141
+ });
1142
+ await store.loadFromDisk();
1143
+ for (let i = 0; i < entryCount; i++) {
1144
+ const filler = "y".repeat(Math.max(0, entryChars - `chunk-entry-${i}-`.length));
1145
+ const result = await store.add("memory", `chunk-entry-${i}-${filler}`);
1146
+ assert.ok(result.success, `seed add #${i} should succeed`);
1147
+ }
1148
+ return store;
1149
+ }
1150
+
1151
+ /**
1152
+ * Mock child that behaves like a real `pi -p` consolidation subprocess: it
1153
+ * reads its prompt, edits the store FILE on disk (not the parent's memory —
1154
+ * the parent's reload must observe what a separate process wrote), and
1155
+ * exits. Scripted per round.
1156
+ */
1157
+ function createChunkedChildPi(
1158
+ store: MemoryStore,
1159
+ script: Array<"shrink" | "noop" | "fail">,
1160
+ ) {
1161
+ let round = 0;
1162
+ return {
1163
+ on: () => {},
1164
+ exec: async (...args: any[]) => {
1165
+ execCalls.push(captureExecArgs(args));
1166
+ const action = script[Math.min(round, script.length - 1)];
1167
+ round++;
1168
+ if (action === "fail") {
1169
+ return { code: 124, stdout: "", stderr: "", killed: true };
1170
+ }
1171
+ if (action === "shrink") {
1172
+ const prompt = execCalls[execCalls.length - 1][1].at(-1) as string;
1173
+ const batch = parsePromptBatch(prompt);
1174
+ assert.ok(batch.length > 0, "child prompt should contain at least one entry");
1175
+ await removeEntryFromDisk(store, batch[0]);
1176
+ }
1177
+ return { code: 0, stdout: "Consolidated", stderr: "" };
1178
+ },
1179
+ registerTool: () => {},
1180
+ registerCommand: () => {},
1181
+ } as any;
1182
+ }
1183
+
1184
+ function batchFromExecCall(call: any[]): string[] {
1185
+ return parsePromptBatch(call[1].at(-1) as string);
1186
+ }
1187
+
1188
+ it("treats a small healthy store as a clean no-op", async () => {
1189
+ // Tiny store, well under its capacity goal: nothing to shrink, no child
1190
+ // spawned, clean success (rounds: 0) — not a ❌ failure.
1191
+ const store = await makeOverChunkStore(2, 20);
1192
+ const pi = createMockPi();
1193
+
1194
+ const result = await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
1195
+
1196
+ assert.strictEqual(execCalls.length, 0, "a healthy store spawns no child");
1197
+ assert.strictEqual(result.consolidated, true);
1198
+ assert.strictEqual(result.rounds, 0);
1199
+ assert.strictEqual(result.error, undefined);
1200
+ });
1201
+
1202
+ it("runs small over-goal stores as one unscoped decisive round", async () => {
1203
+ // 6 entries ≈ 3879 encoded chars: under the 4000 chunk size (one prompt)
1204
+ // but over the 3000 capacity goal — the legacy single-shot call, unscoped.
1205
+ const store = await makeOverChunkStore(6, 600, 3000);
1206
+ const pi = createChunkedChildPi(store, ["shrink"]);
1207
+
1208
+ const result = await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
1209
+
1210
+ assert.strictEqual(execCalls.length, 1, "a store that fits one prompt gets exactly one child");
1211
+ const prompt = childPrompt(execCalls[0]);
1212
+ assert.ok(prompt.includes("chunk-entry-0") && prompt.includes("chunk-entry-5"), "decisive prompt carries the whole store");
1213
+ assert.ok(!prompt.includes("covers ONLY the entries listed above"), "decisive round is unscoped");
1214
+ assert.strictEqual(result.consolidated, true);
1215
+ assert.strictEqual(result.rounds, 1);
1216
+ assert.strictEqual(result.partial, true, "still over the goal after one round — visible, not silent");
1217
+ });
1218
+
1219
+ it("reports a clean single-round run when the decisive round reaches the goal", async () => {
1220
+ const store = await makeOverChunkStore(6, 600, 3000);
1221
+ // Decisive round merges two entries away → 4 entries ≈ 2585 chars ≤ goal.
1222
+ const pi: any = {
1223
+ on: () => {},
1224
+ exec: async (...args: any[]) => {
1225
+ execCalls.push(captureExecArgs(args));
1226
+ const prompt = execCalls[execCalls.length - 1][1].at(-1) as string;
1227
+ const batch = parsePromptBatch(prompt);
1228
+ await removeEntryFromDisk(store, batch[0]);
1229
+ await removeEntryFromDisk(store, batch[1]);
1230
+ return { code: 0, stdout: "Consolidated", stderr: "" };
1231
+ },
1232
+ registerTool: () => {},
1233
+ registerCommand: () => {},
1234
+ };
1235
+
1236
+ const result = await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
1237
+
1238
+ assert.strictEqual(execCalls.length, 1);
1239
+ assert.strictEqual(result.consolidated, true);
1240
+ assert.strictEqual(result.partial, false, "goal met, no failure — a clean run");
1241
+ assert.strictEqual(result.error, undefined);
1242
+ assert.strictEqual(store.getMemoryEntries().length, 4);
1243
+ });
1244
+
1245
+ it("treats an over-chunk but under-goal store as a clean no-op (cap units, not prompt units)", async () => {
1246
+ // 7 entries ≈ 4526 ENCODED chars: over the 4000-char prompt budget but
1247
+ // UNDER the 5000-char capacity goal measured in cap units (encoded
1248
+ // entries). 8 entries (≈ 5173) would cross the goal and run rounds.
1249
+ const store = await makeOverChunkStore(7);
1250
+ const pi = createChunkedChildPi(store, ["shrink"]);
1251
+
1252
+ const result = await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
1253
+
1254
+ assert.strictEqual(execCalls.length, 0, "nothing needs to shrink toward the capacity goal");
1255
+ assert.strictEqual(result.consolidated, true);
1256
+ assert.strictEqual(result.rounds, 0);
1257
+ assert.strictEqual(result.error, undefined);
1258
+ assert.strictEqual(store.getMemoryEntries().length, 7);
1259
+ });
1260
+
1261
+ it("completes an over-goal store in bounded rounds with the default per-round timeout", async () => {
1262
+ const store = await makeOverChunkStore(10); // ≈ 6367 encoded chars > 5000 goal
1263
+ const pi = createChunkedChildPi(store, ["shrink", "shrink", "shrink"]);
1264
+
1265
+ const result = await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
1266
+
1267
+ // Each round removes one entry (−647 encoded chars): 6367 → 5730 → 5093 →
1268
+ // 4456 ≤ goal. The walk advances past each consumed slice.
1269
+ assert.strictEqual(execCalls.length, 3);
1270
+ assert.strictEqual(result.consolidated, true);
1271
+ assert.strictEqual(result.rounds, 3);
1272
+ assert.ok(!result.partial, "goal met with no failure is a clean run");
1273
+ assert.strictEqual(result.error, undefined, "goal met with no failure carries no error");
1274
+ assert.strictEqual(store.getMemoryEntries().length, 7);
1275
+ for (const call of execCalls) {
1276
+ const batch = batchFromExecCall(call);
1277
+ const batchChars = batch.join(ENTRY_DELIMITER).length;
1278
+ assert.ok(batchChars <= DEFAULT_CONSOLIDATION_CHUNK_CHARS, `round prompt ${batchChars} must fit one chunk`);
1279
+ // Rounds share the trigger budget: round 1 gets the full per-round
1280
+ // timeout, later rounds get what remains (still ≥ the round floor).
1281
+ const roundTimeout = Number(call[1][1]);
1282
+ assert.ok(roundTimeout > 0 && roundTimeout <= DEFAULT_CONSOLIDATION_TIMEOUT_MS, `round timeout ${roundTimeout}`);
1283
+ assert.strictEqual(call[2].timeout, roundTimeout + 5000);
1284
+ }
1285
+ });
1286
+
1287
+ it("keeps walking forward: round 2 slices after round 1's slice, not from the top", async () => {
1288
+ const store = await makeOverChunkStore(10);
1289
+ const batches: string[][] = [];
1290
+ const pi: any = {
1291
+ on: () => {},
1292
+ exec: async (...args: any[]) => {
1293
+ execCalls.push(captureExecArgs(args));
1294
+ const prompt = execCalls[execCalls.length - 1][1].at(-1) as string;
1295
+ const batch = parsePromptBatch(prompt);
1296
+ batches.push(batch);
1297
+ await removeEntryFromDisk(store, batch[0]);
1298
+ return { code: 0, stdout: "Consolidated", stderr: "" };
1299
+ },
1300
+ registerTool: () => {},
1301
+ registerCommand: () => {},
1302
+ };
1303
+
1304
+ await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
1305
+
1306
+ assert.ok(batches.length >= 2, "expected multiple rounds");
1307
+ // The discriminating check vs an offset-reset mutant: the walk must move
1308
+ // FORWARD — round 2 starts after round 1's slice. Later rounds may revisit
1309
+ // entries after index shifts (documented approximation).
1310
+ const overlap = batches[1].filter((entry) => batches[0].includes(entry));
1311
+ assert.strictEqual(overlap.length, 0, `round 2 re-processed ${overlap.length} entries from round 1 — the walk must advance`);
1312
+ });
1313
+
1314
+ it("resumes after a killed round: partial progress persists and a second trigger finishes", async () => {
1315
+ const store = await makeOverChunkStore(11); // ≈ 6663 chars > 5000 goal
1316
+ const originalEntries = [...store.getMemoryEntries()];
1317
+ const pi = createChunkedChildPi(store, ["shrink", "fail"]);
1318
+
1319
+ const first = await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", {
1320
+ consolidationChunkChars: 2500,
1321
+ consolidationChunking: true,
1322
+ consolidationChunking: true,
1323
+ });
1324
+
1325
+ assert.strictEqual(execCalls.length, 2, "round 1 succeeds, round 2 is killed");
1326
+ assert.strictEqual(first.consolidated, true, "one completed round is real progress on disk");
1327
+ assert.strictEqual(first.partial, true, "a killed run must not read as a clean success");
1328
+ assert.strictEqual(first.rounds, 1);
1329
+ assert.ok(first.error?.includes("terminated"), first.error);
1330
+ assert.ok(first.error?.includes("1 earlier round shrank the store"), first.error);
1331
+ assert.ok(first.error?.includes("chars over its 5000-char capacity goal"), first.error);
1332
+ assert.strictEqual(store.getMemoryEntries().length, 10);
1333
+
1334
+ // The retried add / next trigger resumes from current disk state and
1335
+ // finishes the job.
1336
+ execCalls = [];
1337
+ const second = await triggerConsolidation(
1338
+ createChunkedChildPi(store, ["shrink", "shrink"]),
1339
+ store,
1340
+ "memory",
1341
+ undefined,
1342
+ DEFAULT_CONSOLIDATION_TIMEOUT_MS,
1343
+ "memory",
1344
+ { consolidationChunkChars: 2500, consolidationChunking: true },
1345
+ );
1346
+
1347
+ assert.strictEqual(second.consolidated, true);
1348
+ assert.strictEqual(second.error, undefined);
1349
+ assert.ok(!second.partial);
1350
+ assert.strictEqual(second.rounds, 3);
1351
+ const survivors = store.getMemoryEntries();
1352
+ assert.strictEqual(survivors.length, 7, "resume finishes the shrink below the capacity goal");
1353
+ const removed = originalEntries.filter((entry) => !survivors.includes(entry));
1354
+ assert.ok(
1355
+ originalEntries.every((entry) => survivors.includes(entry) || removed.includes(entry)),
1356
+ "no entry may vanish or be invented by chunking",
1357
+ );
1358
+ });
1359
+
1360
+ it("walks unshrinkable slices and reports the store still over its goal", async () => {
1361
+ const store = await makeOverChunkStore(9); // ≈ 5733 encoded chars > 5000 goal
1362
+ const pi = createChunkedChildPi(store, ["noop"]);
1363
+
1364
+ const result = await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", {
1365
+ consolidationChunkChars: 2500,
1366
+ consolidationChunking: true,
1367
+ consolidationChunking: true,
1368
+ });
1369
+
1370
+ assert.strictEqual(execCalls.length, MAX_CONSOLIDATION_ROUNDS, "the round cap fires on a store that never shrinks");
1371
+ assert.strictEqual(result.consolidated, false, "nothing shrank — success must not be claimed");
1372
+ assert.ok(result.error?.includes("could not shrink the store toward its 5000-char capacity goal"), result.error);
1373
+ assert.ok(result.error?.includes("distinct facts"), result.error);
1374
+ assert.strictEqual(store.getMemoryEntries().length, 9, "a noop child must not lose entries");
1375
+ });
1376
+
1377
+ it("reports a first-round kill exactly like the single-shot path", async () => {
1378
+ const store = await makeOverChunkStore(9);
1379
+ const pi = createChunkedChildPi(store, ["fail"]);
1380
+
1381
+ const result = await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", {
1382
+ consolidationChunkChars: 2500,
1383
+ consolidationChunking: true,
1384
+ consolidationChunking: true,
1385
+ });
1386
+
1387
+ assert.strictEqual(execCalls.length, 1);
1388
+ assert.strictEqual(result.consolidated, false);
1389
+ assert.strictEqual(result.partial, undefined);
1390
+ assert.ok(result.error?.includes("terminated"), result.error);
1391
+ });
1392
+
1393
+ it("reports out-of-scope deletions without resurrecting them", async () => {
1394
+ // The parent cannot tell a rogue child deletion from a legitimate
1395
+ // cross-slice dedup or a concurrent writer — so deletions outside the
1396
+ // slice are reported, never re-added (resurrection would ping-pong across
1397
+ // triggers and fights legitimate dedup, the #226 class).
1398
+ const store = await makeOverChunkStore(9); // ≈ 5451 chars
1399
+ const seeds = store.getMemoryEntries();
1400
+ const outOfScopeEntry = seeds[6];
1401
+ const pi = {
1402
+ on: () => {},
1403
+ exec: async (...args: any[]) => {
1404
+ execCalls.push(captureExecArgs(args));
1405
+ const prompt = execCalls[execCalls.length - 1][1].at(-1) as string;
1406
+ const batch = parsePromptBatch(prompt);
1407
+ // The rogue child removes its own head AND an entry it was never shown.
1408
+ await removeEntryFromDisk(store, batch[0]);
1409
+ await removeEntryFromDisk(store, outOfScopeEntry);
1410
+ return { code: 0, stdout: "Consolidated", stderr: "" };
1411
+ },
1412
+ registerTool: () => {},
1413
+ registerCommand: () => {},
1414
+ } as any;
1415
+
1416
+ const result = await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", {
1417
+ consolidationChunkChars: 2500,
1418
+ consolidationChunking: true,
1419
+ consolidationChunking: true,
1420
+ });
1421
+
1422
+ assert.strictEqual(execCalls.length, 1);
1423
+ const survivors = store.getMemoryEntries();
1424
+ assert.ok(!survivors.includes(outOfScopeEntry), "out-of-scope deletions are reported, never resurrected");
1425
+ assert.ok(result.error?.includes("out-of-scope entr"), result.error);
1426
+ assert.ok(result.error?.includes("concurrent writer"), result.error);
1427
+ assert.strictEqual(result.partial, true, "a scope deviation keeps the run partial");
1428
+ });
1429
+
1430
+ it("stops before the first round when the time budget cannot fit a round", async () => {
1431
+ const store = await makeOverChunkStore(9);
1432
+ const pi = createChunkedChildPi(store, ["shrink"]);
1433
+
1434
+ const result = await triggerConsolidation(pi, store, "memory", undefined, 5, "memory", {
1435
+ consolidationChunkChars: 2500,
1436
+ consolidationChunking: true,
1437
+ consolidationChunking: true,
1438
+ });
1439
+
1440
+ assert.strictEqual(execCalls.length, 0, "a budget that cannot fit a round spawns no child");
1441
+ assert.strictEqual(result.consolidated, false);
1442
+ assert.ok(result.error?.includes("time budget (5ms) exhausted"), result.error);
1443
+ });
1444
+
1445
+ describe("takeChunk", () => {
1446
+ it("packs whole entries up to the char budget", () => {
1447
+ const entries = ["a".repeat(30), "b".repeat(30), "c".repeat(30)];
1448
+ const batch = takeChunk(entries, 70); // each entry costs 30 + delimiter
1449
+ assert.strictEqual(batch.length, 2);
1450
+ assert.strictEqual(batch.join(ENTRY_DELIMITER).length <= 70, true);
1451
+ });
1452
+
1453
+ it("lets an oversized entry travel alone", () => {
1454
+ const oversized = "x".repeat(3000);
1455
+ assert.deepStrictEqual(takeChunk([oversized, "small"], 2500), [oversized]);
1456
+ });
1457
+
1458
+ it("keeps an exactly-fitting entry", () => {
1459
+ const exact = "y".repeat(2497); // 2497 + 3 delimiter chars = 2500
1460
+ assert.deepStrictEqual(takeChunk([exact], 2500), [exact]);
1461
+ });
1462
+ });
1463
+
1464
+ it("gives the decisive final round the whole remaining store, unscoped", async () => {
1465
+ // Small cap: goal (3000) < chunk (4000), so the loop reaches a state where
1466
+ // the remaining store fits one prompt while still over the goal — that
1467
+ // decisive round must run unscoped, with full context.
1468
+ const store = await makeOverChunkStore(8, 600, 3000); // ≈ 4845 chars > 3000 goal
1469
+ let sawUnscopedFullPrompt = false;
1470
+ const pi: any = {
1471
+ on: () => {},
1472
+ exec: async (...args: any[]) => {
1473
+ execCalls.push(captureExecArgs(args));
1474
+ const prompt = execCalls[execCalls.length - 1][1].at(-1) as string;
1475
+ const batch = parsePromptBatch(prompt);
1476
+ const scoped = prompt.includes("covers ONLY the entries listed above");
1477
+ if (batch.length === store.getMemoryEntries().length && !scoped) {
1478
+ sawUnscopedFullPrompt = true;
1479
+ return { code: 0, stdout: "Consolidated", stderr: "" }; // decisive round may decline
1480
+ }
1481
+ await removeEntryFromDisk(store, batch[0]);
1482
+ return { code: 0, stdout: "Consolidated", stderr: "" };
1483
+ },
1484
+ registerTool: () => {},
1485
+ registerCommand: () => {},
1486
+ };
1487
+
1488
+ await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
1489
+
1490
+ assert.ok(sawUnscopedFullPrompt, "once the remaining store fits one prompt, the round must be unscoped and whole");
1491
+ });
1492
+ });
1493
+
1494
+ // ─── Chunked prompt scoping ───
1495
+
1496
+ describe("chunked prompt scoping", () => {
1497
+ let MEMORY_DIR = "";
1498
+
1499
+ before(async () => {
1500
+ MEMORY_DIR = await fs.mkdtemp(path.join(os.tmpdir(), "pi-consolidation-scope-"));
1501
+ });
1502
+
1503
+ after(async () => {
1504
+ try { await fs.rm(MEMORY_DIR, { recursive: true, force: true }); } catch { /* ignore */ }
1505
+ });
1506
+
1507
+ beforeEach(() => {
1508
+ execCalls = [];
1509
+ });
1510
+
1511
+ it("adds the scope guard only to chunked-round prompts", async () => {
1512
+ const store = new MemoryStore({
1513
+ memoryCharLimit: 5000,
1514
+ userCharLimit: 100,
1515
+ memoryMode: "policy-only",
1516
+ nudgeInterval: 10,
1517
+ reviewEnabled: false,
1518
+ flushOnCompact: false,
1519
+ flushOnShutdown: false,
1520
+ flushMinTurns: 6,
1521
+ autoConsolidate: false,
1522
+ correctionDetection: false,
1523
+ nudgeToolCalls: 15,
1524
+ memoryDir: MEMORY_DIR,
1525
+ });
1526
+ await store.loadFromDisk();
1527
+ for (let i = 0; i < 9; i++) {
1528
+ await store.add("memory", `scope-entry-${i}-${"z".repeat(580)}`); // ≈ 5382 chars > 5000 goal
1529
+ }
1530
+
1531
+ const pi = {
1532
+ on: () => {},
1533
+ exec: async (...args: any[]) => {
1534
+ execCalls.push(captureExecArgs(args));
1535
+ return { code: 0, stdout: "done", stderr: "" };
1536
+ },
1537
+ registerTool: () => {},
1538
+ registerCommand: () => {},
1539
+ } as any;
1540
+
1541
+ await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
1542
+
1543
+ const prompts = execCalls.map((call) => call[1].at(-1) as string);
1544
+ assert.ok(prompts.length >= 1, "over-chunk store should run at least one chunked round");
1545
+ for (const prompt of prompts) {
1546
+ assert.ok(
1547
+ prompt.includes("covers ONLY the entries listed above"),
1548
+ "every chunked-round prompt must carry the scope guard",
1549
+ );
1550
+ assert.ok(
1551
+ prompt.includes("Do NOT add, modify, or remove any entry that is not listed above"),
1552
+ "chunked-round prompt must forbid out-of-scope mutations",
1553
+ );
1554
+ }
1555
+
1556
+ execCalls = [];
1557
+ // Same store, now under one chunk (chunkChars raised): single-shot keeps
1558
+ // the unscoped wording.
1559
+ await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", {
1560
+ consolidationChunkChars: 100_000,
1561
+ });
1562
+ assert.strictEqual(execCalls.length, 1);
1563
+ const singleShotPrompt = execCalls[0][1].at(-1) as string;
1564
+ assert.ok(
1565
+ !singleShotPrompt.includes("covers ONLY the entries listed above"),
1566
+ "single-shot prompt must stay unchanged",
1567
+ );
1568
+ });
1569
+ });
1570
+
1571
+ // ─── Legacy-inject (cap-enforced) chunked path ───
1572
+
1573
+ describe("chunked consolidation in legacy-inject mode", () => {
1574
+ let MEMORY_ROOT = "";
1575
+ let seq = 0;
1576
+
1577
+ before(async () => {
1578
+ MEMORY_ROOT = await fs.mkdtemp(path.join(os.tmpdir(), "pi-consolidation-legacy-"));
1579
+ });
1580
+
1581
+ after(async () => {
1582
+ try { await fs.rm(MEMORY_ROOT, { recursive: true, force: true }); } catch { /* ignore */ }
1583
+ });
1584
+
1585
+ beforeEach(() => {
1586
+ execCalls = [];
1587
+ });
1588
+
1589
+ it("runs the chunked loop against a cap-enforced over-limit store without re-entering caps", async () => {
1590
+ // Auto-consolidation only auto-runs in legacy-inject mode, and only when
1591
+ // the store is over its limit — so this is the mode the loop must be
1592
+ // proven in. A policy-only seed store fills the directory past the
1593
+ // smaller legacy cap; a second legacy-mode instance over the same
1594
+ // directory then consolidates an over-limit store. The loop mutates
1595
+ // nothing through store.add(), so no cap rejection and no nested
1596
+ // consolidation trigger can occur (previously the out-of-scope restore
1597
+ // re-entered exactly that path from inside the held lease).
1598
+ const memoryDir = path.join(MEMORY_ROOT, `legacy-${++seq}`);
1599
+ const seeder = new MemoryStore({
1600
+ memoryCharLimit: 5000,
1601
+ userCharLimit: 100,
1602
+ memoryMode: "policy-only",
1603
+ nudgeInterval: 10,
1604
+ reviewEnabled: false,
1605
+ flushOnCompact: false,
1606
+ flushOnShutdown: false,
1607
+ flushMinTurns: 6,
1608
+ autoConsolidate: false,
1609
+ correctionDetection: false,
1610
+ nudgeToolCalls: 15,
1611
+ memoryDir,
1612
+ });
1613
+ await seeder.loadFromDisk();
1614
+ for (let i = 0; i < 8; i++) {
1615
+ const r = await seeder.add("memory", `seed-${i}-${"x".repeat(72)}`);
1616
+ assert.ok(r.success, `seed ${i} should succeed`);
1617
+ }
1618
+
1619
+ // Legacy-inject view of the same directory: cap 300, store now over it.
1620
+ const store = new MemoryStore({
1621
+ memoryCharLimit: 300,
1622
+ userCharLimit: 100,
1623
+ nudgeInterval: 10,
1624
+ reviewEnabled: false,
1625
+ flushOnCompact: false,
1626
+ flushOnShutdown: false,
1627
+ flushMinTurns: 6,
1628
+ autoConsolidate: false,
1629
+ correctionDetection: false,
1630
+ nudgeToolCalls: 15,
1631
+ memoryDir,
1632
+ });
1633
+ await store.loadFromDisk();
1634
+ const before = store.getMemoryEntries();
1635
+ assert.strictEqual(before.length, 8);
1636
+ assert.ok(before.join(ENTRY_DELIMITER).length > 300, "store must be over the legacy cap");
1637
+
1638
+ const pi = (() => {
1639
+ let round = 0;
1640
+ const script = ["shrink", "shrink", "noop"];
1641
+ return {
1642
+ on: () => {},
1643
+ exec: async (...args: any[]) => {
1644
+ execCalls.push(captureExecArgs(args));
1645
+ const action = script[Math.min(round, script.length - 1)];
1646
+ round++;
1647
+ if (action === "shrink") {
1648
+ const prompt = execCalls[execCalls.length - 1][1].at(-1) as string;
1649
+ const marker = "--- Current Memory Entries ---";
1650
+ const start = prompt.indexOf(marker);
1651
+ const body = prompt.slice(start + marker.length, prompt.indexOf("Use memory_add", start));
1652
+ const batch = body.split(ENTRY_DELIMITER).map((e) => e.trim()).filter((e) => e && e !== "(empty)");
1653
+ await removeEntryFromDisk(store, batch[0]);
1654
+ }
1655
+ return { code: 0, stdout: "Consolidated", stderr: "" };
1656
+ },
1657
+ registerTool: () => {},
1658
+ registerCommand: () => {},
1659
+ } as any;
1660
+ })();
1661
+ const result = await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", {
1662
+ consolidationChunkChars: 500,
1663
+ consolidationChunking: true,
1664
+ });
1665
+
1666
+ assert.strictEqual(result.consolidated, true);
1667
+ assert.strictEqual(result.partial, true, "still over the 300-char goal after the walk");
1668
+ assert.ok(result.error?.includes("could not shrink the remaining"), result.error);
1669
+ assert.ok(!result.error?.includes("another session is consolidating"), "no nested-consolidation stall may surface");
1670
+ const survivors = store.getMemoryEntries();
1671
+ assert.strictEqual(survivors.length, 6, "rounds shrank the store through the child's file edits");
1672
+ const removed = before.filter((entry) => !survivors.includes(entry));
1673
+ assert.strictEqual(removed.length, 2);
1674
+ });
1675
+ });
1676
+
1677
+ describe("/memory-consolidate partial display", () => {
1678
+ it("shows ⚠️ partial with the reason when a round fails after earlier progress", async () => {
1679
+ const memoryDir = await fs.mkdtemp(path.join(os.tmpdir(), "pi-consolidation-partial-ui-"));
1680
+ try {
1681
+ const store = new MemoryStore({
1682
+ memoryCharLimit: 5000,
1683
+ userCharLimit: 100,
1684
+ memoryMode: "policy-only",
1685
+ nudgeInterval: 10,
1686
+ reviewEnabled: false,
1687
+ flushOnCompact: false,
1688
+ flushOnShutdown: false,
1689
+ flushMinTurns: 6,
1690
+ autoConsolidate: false,
1691
+ correctionDetection: false,
1692
+ nudgeToolCalls: 15,
1693
+ memoryDir,
1694
+ });
1695
+ await store.loadFromDisk();
1696
+ for (let i = 0; i < 11; i++) {
1697
+ await store.add("memory", `partial-ui-${i}-${"x".repeat(580)}`); // ≈ 6663 chars > 5000 goal
1698
+ }
1699
+
1700
+ execCalls = [];
1701
+ let handler: ManualCommandHandler | undefined;
1702
+ const pi = {
1703
+ on: () => {},
1704
+ exec: async (...args: any[]) => {
1705
+ execCalls.push(captureExecArgs(args));
1706
+ const round = execCalls.length;
1707
+ if (round === 1) {
1708
+ const prompt = execCalls[0][1].at(-1) as string;
1709
+ const batch = parsePromptBatch(prompt);
1710
+ await removeEntryFromDisk(store, batch[0]);
1711
+ return { code: 0, stdout: "ok", stderr: "" };
1712
+ }
1713
+ return { code: 124, stdout: "", stderr: "", killed: true };
1714
+ },
1715
+ registerTool: () => {},
1716
+ registerCommand: (_name: string, command: { handler: ManualCommandHandler }) => {
1717
+ handler = command.handler;
1718
+ },
1719
+ } as unknown as Parameters<typeof registerConsolidateCommand>[0];
1720
+
1721
+ registerConsolidateCommand(pi, store, DEFAULT_CONSOLIDATION_TIMEOUT_MS, null, null, {
1722
+ consolidationChunkChars: 2500,
1723
+ consolidationChunking: true,
1724
+ consolidationChunking: true,
1725
+ });
1726
+ assert.ok(handler, "command handler should be registered");
1727
+
1728
+ const notifications: string[] = [];
1729
+ await handler!({}, { signal: undefined, ui: { notify: (msg: string) => notifications.push(msg) } });
1730
+
1731
+ const summary = notifications[notifications.length - 1] ?? "";
1732
+ assert.ok(summary.includes("memory: ✅ consolidated (1 round) ⚠️ partial:"), summary);
1733
+ assert.ok(summary.includes("terminated"), summary);
1734
+ } finally {
1735
+ await fs.rm(memoryDir, { recursive: true, force: true }).catch(() => {});
1736
+ }
1737
+ });
1738
+ });
1739
+
1740
+ // ─── Third-review follow-ups: budget starvation, slice growth, reload throw, abort, shrink-then-fail ───
1741
+
1742
+ describe("chunked consolidation edge behavior", () => {
1743
+ let MEMORY_ROOT = "";
1744
+ let seq = 0;
1745
+
1746
+ before(async () => {
1747
+ MEMORY_ROOT = await fs.mkdtemp(path.join(os.tmpdir(), "pi-consolidation-edge-"));
1748
+ });
1749
+
1750
+ after(async () => {
1751
+ try { await fs.rm(MEMORY_ROOT, { recursive: true, force: true }); } catch { /* ignore */ }
1752
+ });
1753
+
1754
+ beforeEach(() => {
1755
+ execCalls = [];
1756
+ });
1757
+
1758
+ function fileChild(store: MemoryStore, onRound: (batch: string[], round: number) => Promise<"shrink" | "grow" | "noop" | "fail">) {
1759
+ let round = 0;
1760
+ return {
1761
+ on: () => {},
1762
+ exec: async (...args: any[]) => {
1763
+ execCalls.push(captureExecArgs(args));
1764
+ const prompt = execCalls[execCalls.length - 1][1].at(-1) as string;
1765
+ const batch = parsePromptBatch(prompt);
1766
+ round++;
1767
+ const action = onRound(batch, round);
1768
+ return action.then((a: string) => (a === "fail" ? { code: 124, stdout: "", stderr: "", killed: true } : { code: 0, stdout: "ok", stderr: "" }));
1769
+ },
1770
+ registerTool: () => {},
1771
+ registerCommand: () => {},
1772
+ } as any;
1773
+ }
1774
+
1775
+ async function makeStore(entryCount: number, cap = 5000): Promise<MemoryStore> {
1776
+ const memoryDir = path.join(MEMORY_ROOT, `edge-${++seq}`);
1777
+ const store = new MemoryStore({
1778
+ memoryCharLimit: cap, userCharLimit: 100, memoryMode: "policy-only", nudgeInterval: 10,
1779
+ reviewEnabled: false, flushOnCompact: false, flushOnShutdown: false, flushMinTurns: 6,
1780
+ autoConsolidate: false, correctionDetection: false, nudgeToolCalls: 15, memoryDir,
1781
+ } as any);
1782
+ await store.loadFromDisk();
1783
+ for (let i = 0; i < entryCount; i++) {
1784
+ const r = await store.add("memory", `edge-entry-${i}-` + "y".repeat(580));
1785
+ if (!r.success) throw new Error(`seed ${i}`);
1786
+ }
1787
+ return store;
1788
+ }
1789
+
1790
+ it("a growing round is walked past, not rewarded", async () => {
1791
+ const store = await makeStore(9); // ≈ 5820 encoded chars > 5000 goal
1792
+ const pi: any = {
1793
+ on: () => {}, registerTool: () => {}, registerCommand: () => {},
1794
+ exec: async (...args: any[]) => {
1795
+ execCalls.push(captureExecArgs(args));
1796
+ const prompt = execCalls[execCalls.length - 1][1].at(-1) as string;
1797
+ const batch = parsePromptBatch(prompt);
1798
+ if (batch.length > 0) await store.remove("memory", batch[0]);
1799
+ // ...and the rogue/growing child also adds a fresh entry.
1800
+ await store.add("memory", `grown-entry-${roundCounter}-` + "z".repeat(580));
1801
+ return { code: 0, stdout: "ok", stderr: "" };
1802
+ },
1803
+ registerTool: () => {}, registerCommand: () => {},
1804
+ };
1805
+ let roundCounter = 0;
1806
+ // NOTE: roundCounter is captured by the closure above via hoisting of let.
1807
+ const result = await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", {
1808
+ consolidationChunkChars: 2500,
1809
+ consolidationChunking: true,
1810
+ consolidationChunking: true,
1811
+ });
1812
+
1813
+ assert.strictEqual(result.consolidated, true);
1814
+ assert.ok(store.getMemoryEntries().length <= 9, "a growing round must not grow the store: removal offsets its addition");
1815
+ assert.ok(result.rounds !== undefined && result.rounds <= MAX_CONSOLIDATION_ROUNDS, "bounded rounds");
1816
+ });
1817
+
1818
+ it("loadFromDisk failure between rounds is reported and stops the walk", async () => {
1819
+ const store = await makeStore(9);
1820
+ const pi: any = {
1821
+ on: () => {}, registerTool: () => {}, registerCommand: () => {},
1822
+ exec: async (...args: any[]) => {
1823
+ execCalls.push(captureExecArgs(args));
1824
+ return { code: 0, stdout: "ok", stderr: "" };
1825
+ },
1826
+ registerTool: () => {}, registerCommand: () => {},
1827
+ };
1828
+ (store as any).loadFromDisk = async () => {
1829
+ throw new Error("injected reload failure");
1830
+ };
1831
+
1832
+ const result = await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", {
1833
+ consolidationChunkChars: 2500,
1834
+ consolidationChunking: true,
1835
+ consolidationChunking: true,
1836
+ });
1837
+
1838
+ assert.strictEqual(result.consolidated, false);
1839
+ assert.ok(result.error?.includes("could not reload memory after a consolidation round"), result.error);
1840
+ assert.strictEqual(execCalls.length, 1);
1841
+ });
1842
+
1843
+ it("abort landing between rounds stops the walk with an honest note", async () => {
1844
+ const store = await makeStore(9);
1845
+ const controller = new AbortController();
1846
+ const pi: any = {
1847
+ on: () => {}, registerTool: () => {}, registerCommand: () => {},
1848
+ exec: async (...args: any[]) => {
1849
+ execCalls.push(captureExecArgs(args));
1850
+ controller.abort(); // abort lands between rounds, not during a child
1851
+ return { code: 0, stdout: "ok", stderr: "" };
1852
+ },
1853
+ registerTool: () => {}, registerCommand: () => {},
1854
+ };
1855
+
1856
+ const result = await triggerConsolidation(pi, store, "memory", controller.signal, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", {
1857
+ consolidationChunkChars: 2500,
1858
+ consolidationChunking: true,
1859
+ consolidationChunking: true,
1860
+ });
1861
+
1862
+ assert.strictEqual(execCalls.length, 1, "abort between rounds must stop the walk");
1863
+ assert.strictEqual(result.consolidated, false, "nothing completed before the abort");
1864
+ assert.ok(result.error?.includes("aborted between consolidation rounds"), result.error);
1865
+ });
1866
+
1867
+ it("a round that shrinks on disk and then fails reports partial, not total failure", async () => {
1868
+ const store = await makeStore(9);
1869
+ const pi: any = {
1870
+ on: () => {}, registerTool: () => {}, registerCommand: () => {},
1871
+ exec: async (...args: any[]) => {
1872
+ execCalls.push(captureExecArgs(args));
1873
+ const prompt = execCalls[execCalls.length - 1][1].at(-1) as string;
1874
+ const batch = parsePromptBatch(prompt);
1875
+ // The child merges its slice, THEN dies — the shrink is real and on disk.
1876
+ await store.remove("memory", batch[0]);
1877
+ return { code: 124, stdout: "", stderr: "", killed: true };
1878
+ },
1879
+ registerTool: () => {}, registerCommand: () => {},
1880
+ };
1881
+
1882
+ const result = await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", {
1883
+ consolidationChunkChars: 2500,
1884
+ consolidationChunking: true,
1885
+ consolidationChunking: true,
1886
+ });
1887
+
1888
+ assert.strictEqual(result.consolidated, true, "the on-disk shrink is real progress");
1889
+ assert.strictEqual(result.partial, true, "…but the run ended in failure and must say so");
1890
+ assert.strictEqual(result.rounds, 0, "no round completed successfully");
1891
+ assert.ok(result.error?.includes("The failing round still shrank the store by"), result.error);
1892
+ assert.ok(store.getMemoryEntries().length < 9, "the shrink persisted");
1893
+ });
1894
+
1895
+ it("starving rounds share the budget: per-round timeouts shrink until the gate trips", { timeout: 60000 }, async () => {
1896
+ const store = await makeStore(17); // ≈ 11K encoded chars, needs several rounds
1897
+ const watchdogTimeouts: number[] = [];
1898
+ const pi: any = {
1899
+ on: () => {}, registerTool: () => {}, registerCommand: () => {},
1900
+ exec: async (...args: any[]) => {
1901
+ execCalls.push(captureExecArgs(args));
1902
+ const call = execCalls[execCalls.length - 1];
1903
+ watchdogTimeouts.push(Number(call[1][1]));
1904
+ const prompt = call[1].at(-1) as string;
1905
+ const batch = parsePromptBatch(prompt);
1906
+ await new Promise((r) => setTimeout(r, 800)); // child works for 0.8s per round
1907
+ if (batch.length > 0) await store.remove("memory", batch[0]);
1908
+ return { code: 0, stdout: "ok", stderr: "" };
1909
+ },
1910
+ registerTool: () => {}, registerCommand: () => {},
1911
+ };
1912
+
1913
+ const result = await triggerConsolidation(pi, store, "memory", undefined, 11500, "memory", {
1914
+ consolidationChunkChars: 2500,
1915
+ consolidationChunking: true,
1916
+ consolidationChunking: true,
1917
+ });
1918
+
1919
+ assert.ok(watchdogTimeouts.length >= 2, "multiple rounds before the budget gate");
1920
+ for (let i = 1; i < watchdogTimeouts.length; i++) {
1921
+ assert.ok(
1922
+ watchdogTimeouts[i] < watchdogTimeouts[i - 1],
1923
+ `round ${i + 1} must get a STRICTLY SMALLER share of the shared budget (got ${watchdogTimeouts[i - 1]} → ${watchdogTimeouts[i]}) — a mutant passing the full timeout every round fails here`,
1924
+ );
1925
+ }
1926
+ assert.ok(result.error?.includes("time budget (11500ms) exhausted"), result.error);
1927
+ });
1928
+ });
1929
+
1930
+ // ─── Usage signals (PR-2 promotion gate) ───
1931
+
1932
+ const SIGNAL_ENTRY_RECALLED = "usage-signal entry alpha — recalled by search often";
1933
+ const SIGNAL_ENTRY_NEVER = "usage-signal entry beta — never recalled by search";
1934
+ const SIGNALS_HEADER = "--- Usage Signals (memory_search recall tracking) ---";
1935
+ const SIGNALS_GUIDANCE = "Treat these as tie-breakers, not removal orders";
1936
+
1937
+ function makeUsageStore(entries: string[]) {
1938
+ return {
1939
+ getMemoryEntries: () => [...entries],
1940
+ getUserEntries: () => [],
1941
+ getAllFailureEntries: () => [],
1942
+ getStorageIdentity: async (target: string) => path.join("usage-store", target),
1943
+ loadFromDisk: async () => {},
1944
+ capacityGoal: () => 10,
1945
+ capacityUsage: () => 1000,
1946
+ } as any;
1947
+ }
1948
+
1949
+ function todayStr(): string {
1950
+ return new Date().toISOString().split("T")[0];
1951
+ }
1952
+
1953
+ describe("consolidation usage signals", () => {
1954
+ let usageDb: DatabaseManager;
1955
+ let usageDir = "";
1956
+
1957
+ beforeEach(async () => {
1958
+ // This describe is top-level (appended after the others), so the
1959
+ // triggerConsolidation describe's beforeEach does not apply: reset the
1960
+ // shared exec capture and lock dir here too.
1961
+ execCalls = [];
1962
+ process.env.PI_HERMES_CONSOLIDATION_LOCK_DIR = await fs.mkdtemp(
1963
+ path.join(os.tmpdir(), "pi-consolidation-locks-"),
1964
+ );
1965
+ usageDir = await fs.mkdtemp(path.join(os.tmpdir(), "pi-usage-signal-consolidation-"));
1966
+ usageDb = new DatabaseManager(usageDir);
1967
+ });
1968
+
1969
+ afterEach(() => {
1970
+ try { usageDb.close(); } catch { /* already closed by the test */ }
1971
+ try { fs.rmSync(usageDir, { recursive: true, force: true }); } catch { /* best effort */ }
1972
+ });
1973
+
1974
+ it("keeps the subprocess prompt byte-identical when the database has no tracking data", async () => {
1975
+ addMemory(usageDb, SIGNAL_ENTRY_NEVER, "memory"); // zero hits → no signals
1976
+ const store = makeUsageStore([SIGNAL_ENTRY_NEVER]);
1977
+
1978
+ const piWithDb = createMockPi();
1979
+ await triggerConsolidation(piWithDb, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true }, null, usageDb);
1980
+ const withDbPrompt = childPrompt(execCalls[0]);
1981
+
1982
+ execCalls = [];
1983
+ const piNoDb = createMockPi();
1984
+ await triggerConsolidation(piNoDb, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true });
1985
+ const noDbPrompt = childPrompt(execCalls[0]);
1986
+
1987
+ assert.strictEqual(withDbPrompt, noDbPrompt, "prompt must be identical with a dataless database attached");
1988
+ assert.ok(!withDbPrompt.includes(SIGNALS_HEADER));
1989
+
1990
+ });
1991
+
1992
+ it("annotates recalled and never-recalled entries once tracking data exists", async () => {
1993
+ const recalledRow = addMemory(usageDb, SIGNAL_ENTRY_RECALLED, "memory");
1994
+ addMemory(usageDb, SIGNAL_ENTRY_NEVER, "memory");
1995
+ recordSearchHits(usageDb, [recalledRow.id]);
1996
+ const store = makeUsageStore([SIGNAL_ENTRY_RECALLED, SIGNAL_ENTRY_NEVER]);
1997
+
1998
+ const pi = createMockPi();
1999
+ await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true }, null, usageDb);
2000
+
2001
+ const prompt = childPrompt(execCalls[0]);
2002
+ assert.ok(prompt.includes(SIGNALS_HEADER), "usage signals header present");
2003
+ assert.ok(prompt.includes(`recalled 1x, last ${todayStr()}: "${SIGNAL_ENTRY_RECALLED}"`), "recalled entry annotated with count + date");
2004
+ assert.ok(prompt.includes(`never recalled: "${SIGNAL_ENTRY_NEVER}"`), "never-recalled entry annotated");
2005
+ assert.ok(prompt.includes(SIGNALS_GUIDANCE), "tie-breaker guidance present");
2006
+ // The real entry list stays untouched (child copies entry text from there).
2007
+ assert.ok(prompt.includes(`--- Current Memory Entries ---\n${SIGNAL_ENTRY_RECALLED}\n§\n${SIGNAL_ENTRY_NEVER}\n\n${SIGNALS_HEADER}`));
2008
+
2009
+ });
2010
+
2011
+ it("omits the section when consolidationUsageSignals is off even with data", async () => {
2012
+ const recalledRow = addMemory(usageDb, SIGNAL_ENTRY_RECALLED, "memory");
2013
+ recordSearchHits(usageDb, [recalledRow.id]);
2014
+ const store = makeUsageStore([SIGNAL_ENTRY_RECALLED]);
2015
+
2016
+ const pi = createMockPi();
2017
+ await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true, consolidationUsageSignals: false }, null, usageDb);
2018
+
2019
+ const prompt = childPrompt(execCalls[0]);
2020
+ assert.ok(!prompt.includes(SIGNALS_HEADER), "kill-switch must suppress the section");
2021
+
2022
+ });
2023
+
2024
+ it("annotates only the presented batch in chunked rounds", async () => {
2025
+ const entries: string[] = [];
2026
+ for (let i = 0; i < 12; i++) {
2027
+ entries.push(`usage chunk entry ${String(i).padStart(2, "0")} — ${"filler prose for sizing ".repeat(3)}end-${i}`);
2028
+ }
2029
+ const store = makeUsageStore(entries);
2030
+ const rows = entries.map((entry) => addMemory(usageDb, entry, "memory"));
2031
+ recordSearchHits(usageDb, [rows[10].id]); // only a TAIL entry has usage data
2032
+
2033
+ const pi = createMockPi();
2034
+ await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", {
2035
+ consolidationChunking: true,
2036
+ consolidationChunkChars: 500,
2037
+ }, null, usageDb);
2038
+
2039
+ assert.ok(execCalls.length >= 3, `expected multiple rounds, got ${execCalls.length}`);
2040
+ const firstPrompt = childPrompt(execCalls[0]);
2041
+ assert.ok(!firstPrompt.includes(SIGNALS_HEADER), "a batch with no tracked entries gets no section");
2042
+ const annotatedAt = execCalls.findIndex((_, i) => childPrompt(execCalls[i]).includes("recalled 1x"));
2043
+ assert.ok(annotatedAt > 0, "the round containing the tracked entry carries the section");
2044
+ const annotatedPrompt = childPrompt(execCalls[annotatedAt]);
2045
+ assert.ok(annotatedPrompt.includes(`recalled 1x, last ${todayStr()}: "${entries[10].slice(0, 77)}...`), "tail entry annotated when it reaches a batch");
2046
+
2047
+ });
2048
+
2049
+ it("embeds the same section in the direct-transport userPrompt", async () => {
2050
+ const recalledRow = addMemory(usageDb, SIGNAL_ENTRY_RECALLED, "memory");
2051
+ recordSearchHits(usageDb, [recalledRow.id]);
2052
+ const store = makeUsageStore([SIGNAL_ENTRY_RECALLED]);
2053
+
2054
+ directCalls = [];
2055
+ const pi = createMockPi();
2056
+ const deps = makeDirectDeps({ ok: true, appliedCount: 1 });
2057
+ const result = await triggerConsolidation(
2058
+ pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory",
2059
+ directTransportLlmConfig, createDirectCtx() as any, usageDb, null, deps,
2060
+ );
2061
+
2062
+ assert.strictEqual(result.consolidated, true);
2063
+ assert.strictEqual(directCalls.length, 1, "direct transport used, no subprocess needed");
2064
+ const options = (directCalls[0][3] ?? directCalls[0][directCalls[0].length - 1]) as { userPrompt: string };
2065
+ assert.ok(options.userPrompt.includes(SIGNALS_HEADER), "direct prompt carries the section");
2066
+ assert.ok(options.userPrompt.includes(`recalled 1x, last ${todayStr()}: "${SIGNAL_ENTRY_RECALLED}"`));
2067
+
2068
+ });
2069
+ });
2070
+
2071
+ describe("consolidation usage signals — large all-recalled store (review blocker)", () => {
2072
+ let usageDb: DatabaseManager;
2073
+ let usageDir = "";
2074
+
2075
+ beforeEach(async () => {
2076
+ // Top-level describe: reset the shared exec capture and lock dir here too.
2077
+ execCalls = [];
2078
+ process.env.PI_HERMES_CONSOLIDATION_LOCK_DIR = await fs.mkdtemp(
2079
+ path.join(os.tmpdir(), "pi-consolidation-locks-"),
2080
+ );
2081
+ usageDir = await fs.mkdtemp(path.join(os.tmpdir(), "pi-usage-signal-cap-"));
2082
+ usageDb = new DatabaseManager(usageDir);
2083
+ });
2084
+
2085
+ afterEach(() => {
2086
+ try { usageDb.close(); } catch { /* already closed by the test */ }
2087
+ try { fs.rmSync(usageDir, { recursive: true, force: true }); } catch { /* best effort */ }
2088
+ });
2089
+
2090
+ it("caps the tracked half, ranks by hits, and folds the remainder into a summary line", async () => {
2091
+ // 40 entries, EVERY one recalled (the mature-store shape where the old
2092
+ // uncapped tracked half grew with the store: 40 tracked lines). Each entry
2093
+ // ~120 chars so the whole store fits one decisive prompt (chunking off).
2094
+ const entries: string[] = [];
2095
+ for (let i = 0; i < 40; i++) {
2096
+ entries.push(`mature-store entry ${String(i).padStart(2, "0")} — ${"recalled prose for sizing ".repeat(3)}end-${i}`);
2097
+ }
2098
+ const store = makeUsageStore(entries);
2099
+ const rows = entries.map((entry) => addMemory(usageDb, entry, "memory"));
2100
+ for (const row of rows) {
2101
+ const hits = 1 + (rows.indexOf(row) % 5); // 1..5 hits, entry 39 has 5
2102
+ for (let i = 0; i < hits; i++) recordSearchHits(usageDb, [row.id]);
2103
+ }
2104
+ // Highest count is on the LAST store entry — sorting must still surface it.
2105
+ for (let i = 0; i < 95; i++) recordSearchHits(usageDb, [rows[39].id]);
2106
+
2107
+ const pi = createMockPi();
2108
+ // One decisive whole-store round: all 40 tracked entries in ONE prompt —
2109
+ // the mature-store shape the owner measured at 270% of the chunk budget.
2110
+ await triggerConsolidation(pi, store, "memory", undefined, DEFAULT_CONSOLIDATION_TIMEOUT_MS, "memory", { consolidationChunking: true, consolidationChunkChars: 999999 }, null, usageDb);
2111
+
2112
+ const prompt = childPrompt(execCalls[0]);
2113
+ const sectionStart = prompt.indexOf("--- Usage Signals (memory_search recall tracking) ---");
2114
+ assert.ok(sectionStart > 0, "signals section present");
2115
+ const section = prompt.slice(sectionStart, prompt.indexOf("Use memory_add", sectionStart));
2116
+
2117
+ const trackedLines = section.split("\n").filter((l) => l.startsWith("- recalled "));
2118
+ assert.strictEqual(trackedLines.length, 20, `tracked half capped at 20 (got ${trackedLines.length})`);
2119
+ assert.match(section, /\(\+20 more recalled entries omitted — showing the top 20 by recall count\)/, "remainder folded into a summary line");
2120
+ // Ranked by hits: the 100-hit entry must top the kept half despite being
2121
+ // LAST in store order, and the kept half is non-increasing by count.
2122
+ assert.match(trackedLines[0], /- recalled 100x, last \d{4}-\d{2}-\d{2}: "mature-store entry 39/);
2123
+ const counts = trackedLines.map((l) => Number(l.match(/- recalled (\d+)x/)![1]));
2124
+ for (let i = 1; i < counts.length; i++) {
2125
+ assert.ok(counts[i] <= counts[i - 1], `kept half must be sorted by hits desc (got ${counts[i - 1]} -> ${counts[i]})`);
2126
+ }
2127
+ // Never-recalled half is empty here — no never-recalled summary expected.
2128
+ assert.ok(!section.includes("have no recorded recalls"));
2129
+ // Bounded section: constant line count, not store-proportional.
2130
+ assert.ok(section.length < 4500, `section bounded (got ${section.length} chars)`);
2131
+ usageDb.close();
2132
+ });
990
2133
  });