@selesai/code 0.13.15 → 0.13.18

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 (473) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +2 -14
  3. package/dist/bun/cli.d.ts +3 -1
  4. package/dist/bun/cli.js +3 -9
  5. package/dist/bun/{register-bedrock.js → runtime-setup.js} +5 -0
  6. package/dist/bun/sandbox-env-setup.d.ts +1 -0
  7. package/dist/bun/sandbox-env-setup.js +3 -0
  8. package/dist/cli/auth-command.d.ts +23 -0
  9. package/dist/cli/auth-command.js +102 -0
  10. package/dist/cli/config-selector.js +2 -1
  11. package/dist/cli/setup.d.ts +1 -0
  12. package/dist/cli/setup.js +11 -0
  13. package/dist/cli.js +2 -14
  14. package/dist/config.d.ts +3 -2
  15. package/dist/config.js +9 -4
  16. package/dist/core/agent-session-runtime.js +15 -7
  17. package/dist/core/agent-session.d.ts +2 -6
  18. package/dist/core/agent-session.js +15 -4
  19. package/dist/core/compaction/branch-summarization.d.ts +1 -1
  20. package/dist/core/compaction/branch-summarization.js +2 -1
  21. package/dist/core/extensions/loader.js +3 -0
  22. package/dist/core/extensions/types.d.ts +16 -2
  23. package/dist/core/http-dispatcher.js +2 -0
  24. package/dist/core/keybindings.d.ts +5 -0
  25. package/dist/core/keybindings.js +4 -0
  26. package/dist/core/messages.d.ts +1 -1
  27. package/dist/core/model-config.d.ts +15 -0
  28. package/dist/core/model-config.js +3 -0
  29. package/dist/core/model-runtime.d.ts +1 -0
  30. package/dist/core/model-runtime.js +5 -2
  31. package/dist/core/provider-composer.js +8 -2
  32. package/dist/core/session-export.d.ts +3 -0
  33. package/dist/core/session-export.js +31 -0
  34. package/dist/core/session-manager.d.ts +3 -2
  35. package/dist/core/session-manager.js +40 -13
  36. package/dist/core/skills.d.ts +1 -1
  37. package/dist/core/skills.js +4 -2
  38. package/dist/core/system-prompt.js +10 -10
  39. package/dist/core/tools/bash.js +3 -117
  40. package/dist/core/tools/edit.d.ts +1 -12
  41. package/dist/core/tools/edit.js +5 -163
  42. package/dist/core/tools/find.js +4 -55
  43. package/dist/core/tools/grep.js +4 -60
  44. package/dist/core/tools/ls.js +4 -49
  45. package/dist/core/tools/read.d.ts +4 -0
  46. package/dist/core/tools/read.js +10 -122
  47. package/dist/core/tools/renderers/bash.d.ts +11 -0
  48. package/dist/core/tools/renderers/bash.js +129 -0
  49. package/dist/core/tools/renderers/edit.d.ts +22 -0
  50. package/dist/core/tools/renderers/edit.js +166 -0
  51. package/dist/core/tools/renderers/find.d.ts +9 -0
  52. package/dist/core/tools/renderers/find.js +63 -0
  53. package/dist/core/tools/renderers/grep.d.ts +9 -0
  54. package/dist/core/tools/renderers/grep.js +68 -0
  55. package/dist/core/tools/renderers/index.d.ts +27 -0
  56. package/dist/core/tools/renderers/index.js +46 -0
  57. package/dist/core/tools/renderers/ls.d.ts +9 -0
  58. package/dist/core/tools/renderers/ls.js +57 -0
  59. package/dist/core/tools/renderers/read.d.ts +10 -0
  60. package/dist/core/tools/renderers/read.js +128 -0
  61. package/dist/core/tools/renderers/write.d.ts +9 -0
  62. package/dist/core/tools/renderers/write.js +152 -0
  63. package/dist/core/tools/write.js +5 -146
  64. package/dist/extensions/capability-gateway/index.ts +12 -1
  65. package/dist/extensions/capability-gateway/integration.test.ts +23 -0
  66. package/dist/extensions/pi-hermes-memory/CHANGELOG.md +18 -0
  67. package/dist/extensions/pi-hermes-memory/README.md +16 -12
  68. package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +1 -1
  69. package/dist/extensions/pi-hermes-memory/package-lock.json +587 -62
  70. package/dist/extensions/pi-hermes-memory/package.json +4 -4
  71. package/dist/extensions/pi-hermes-memory/src/config.ts +32 -0
  72. package/dist/extensions/pi-hermes-memory/src/constants.ts +12 -2
  73. package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +109 -51
  74. package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +9 -3
  75. package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +257 -98
  76. package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +9 -2
  77. package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +5 -0
  78. package/dist/extensions/pi-hermes-memory/src/index.ts +22 -2
  79. package/dist/extensions/pi-hermes-memory/src/paths.ts +1 -1
  80. package/dist/extensions/pi-hermes-memory/src/store/db.ts +6 -0
  81. package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +58 -1
  82. package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +60 -8
  83. package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +169 -7
  84. package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +7 -21
  85. package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +134 -15
  86. package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +4 -2
  87. package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +24 -9
  88. package/dist/extensions/pi-hermes-memory/src/types.ts +11 -0
  89. package/dist/extensions/pi-hermes-memory/tests/config.test.ts +42 -0
  90. package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +159 -3
  91. package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +452 -0
  92. package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +39 -0
  93. package/dist/extensions/pi-hermes-memory/tests/integration/corruption-recovery-integration.test.ts +91 -0
  94. package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +29 -0
  95. package/dist/extensions/pi-hermes-memory/tests/store/fts-query.test.ts +116 -0
  96. package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +163 -0
  97. package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +233 -0
  98. package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +12 -0
  99. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +175 -0
  100. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +2 -2
  101. package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +22 -0
  102. package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +37 -1
  103. package/dist/extensions/pi-intercom/CHANGELOG.md +13 -0
  104. package/dist/extensions/pi-intercom/README.md +16 -2
  105. package/dist/extensions/pi-intercom/broker/spawn.test.ts +19 -2
  106. package/dist/extensions/pi-intercom/broker/spawn.ts +4 -4
  107. package/dist/extensions/pi-intercom/index.ts +1 -1
  108. package/dist/extensions/pi-intercom/intercom.integration.test.ts +121 -2
  109. package/dist/extensions/pi-intercom/package.json +1 -1
  110. package/dist/extensions/pi-intercom/project-agent.test.ts +1 -1
  111. package/dist/extensions/pi-intercom/project-agent.ts +1 -6
  112. package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +7 -6
  113. package/dist/extensions/pi-rewind-hook/index.test.ts +7 -0
  114. package/dist/extensions/pi-subagents/.github/workflows/test.yml +36 -4
  115. package/dist/extensions/pi-subagents/CHANGELOG.md +120 -0
  116. package/dist/extensions/pi-subagents/README.md +3 -3
  117. package/dist/extensions/pi-subagents/agents/researcher.md +23 -13
  118. package/dist/extensions/pi-subagents/agents/reviewer.md +1 -1
  119. package/dist/extensions/pi-subagents/agents/scout.md +1 -1
  120. package/dist/extensions/pi-subagents/docs/agents.md +32 -16
  121. package/dist/extensions/pi-subagents/docs/configuration.md +41 -15
  122. package/dist/extensions/pi-subagents/docs/extension-api.md +109 -6
  123. package/dist/extensions/pi-subagents/docs/missions.md +2 -0
  124. package/dist/extensions/pi-subagents/docs/models.md +58 -1
  125. package/dist/extensions/pi-subagents/docs/observability.md +50 -12
  126. package/dist/extensions/pi-subagents/docs/tool-reference.md +17 -10
  127. package/dist/extensions/pi-subagents/docs/watchdog.md +1 -1
  128. package/dist/extensions/pi-subagents/docs/workflows.md +26 -9
  129. package/dist/extensions/pi-subagents/package-lock.json +747 -177
  130. package/dist/extensions/pi-subagents/package.json +6 -4
  131. package/dist/extensions/pi-subagents/runner-server-preload.mjs +13 -0
  132. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +2 -1
  133. package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +1 -1
  134. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +21 -4
  135. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -1
  136. package/dist/extensions/pi-subagents/skills/pi-subagents/references/multi-lane-orchestration.md +2 -0
  137. package/dist/extensions/pi-subagents/src/agents/advertised-agent-prompt.ts +63 -0
  138. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +61 -16
  139. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +2 -0
  140. package/dist/extensions/pi-subagents/src/agents/agents.ts +8 -0
  141. package/dist/extensions/pi-subagents/src/api/capability-ceiling.ts +0 -1
  142. package/dist/extensions/pi-subagents/src/api/{pi-args.ts → child-tool-plan.ts} +1 -1
  143. package/dist/extensions/pi-subagents/src/api/preflight.ts +7 -4
  144. package/dist/extensions/pi-subagents/src/api/shared-types.ts +2 -2
  145. package/dist/extensions/pi-subagents/src/api/workflow-resources.ts +6 -0
  146. package/dist/extensions/pi-subagents/src/extension/config.ts +4 -2
  147. package/dist/extensions/pi-subagents/src/extension/doctor.ts +2 -10
  148. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +9 -11
  149. package/dist/extensions/pi-subagents/src/extension/index.ts +99 -10
  150. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +13 -0
  151. package/dist/extensions/pi-subagents/src/extension/rpc.ts +7 -23
  152. package/dist/extensions/pi-subagents/src/extension/schemas.ts +11 -8
  153. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +25 -7
  154. package/dist/extensions/pi-subagents/src/integrations/pi-web-session-liveness.ts +73 -0
  155. package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +228 -136
  156. package/dist/extensions/pi-subagents/src/intercom/supervisor-ui.ts +244 -0
  157. package/dist/extensions/pi-subagents/src/missions/workflow-state.ts +37 -16
  158. package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +18 -18
  159. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +51 -25
  160. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +46 -3
  161. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +14 -3
  162. package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +9 -0
  163. package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +10 -12
  164. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -15
  165. package/dist/extensions/pi-subagents/src/runs/background/auto-drain.ts +40 -29
  166. package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +8 -0
  167. package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +79 -247
  168. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +88 -12
  169. package/dist/extensions/pi-subagents/src/runs/background/owned-process-tree.ts +6 -6
  170. package/dist/extensions/pi-subagents/src/runs/background/process-terminal.ts +24 -24
  171. package/dist/extensions/pi-subagents/src/runs/background/retained-nested-route-tracker.ts +96 -0
  172. package/dist/extensions/pi-subagents/src/runs/background/run-child-session.ts +642 -0
  173. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +75 -6
  174. package/dist/extensions/pi-subagents/src/runs/background/runner-aliases.ts +163 -0
  175. package/dist/extensions/pi-subagents/src/runs/background/runner-child-launch.ts +86 -0
  176. package/dist/extensions/pi-subagents/src/runs/background/runner-child-sessions.ts +31 -0
  177. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +18 -4
  178. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +3 -1
  179. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +597 -1092
  180. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +3 -0
  181. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +4 -0
  182. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +20 -17
  183. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +296 -394
  184. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +4 -0
  185. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +3 -1
  186. package/dist/extensions/pi-subagents/src/runs/foreground/prompt-audit.ts +9 -5
  187. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +630 -283
  188. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +8 -5
  189. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-foreground-steering.ts +78 -98
  190. package/dist/extensions/pi-subagents/src/runs/shared/abort-recovery.ts +3 -3
  191. package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +16 -3
  192. package/dist/extensions/pi-subagents/src/runs/shared/agent-contract.ts +1 -1
  193. package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +47 -47
  194. package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +1 -2
  195. package/dist/extensions/pi-subagents/src/runs/shared/child-hooks.ts +174 -0
  196. package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +14 -3
  197. package/dist/extensions/pi-subagents/src/runs/shared/child-launch.ts +319 -0
  198. package/dist/extensions/pi-subagents/src/runs/shared/child-lifecycle.ts +25 -0
  199. package/dist/extensions/pi-subagents/src/runs/shared/child-runtime-config.ts +126 -0
  200. package/dist/extensions/pi-subagents/src/runs/shared/child-session.ts +373 -0
  201. package/dist/extensions/pi-subagents/src/runs/shared/child-tool-plan.ts +530 -0
  202. package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +2 -2
  203. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +2 -1
  204. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +16 -0
  205. package/dist/extensions/pi-subagents/src/runs/shared/host-step-status.ts +11 -11
  206. package/dist/extensions/pi-subagents/src/runs/shared/llm-intent-arbiter.ts +30 -20
  207. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +5 -4
  208. package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +84 -15
  209. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +88 -12
  210. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +37 -53
  211. package/dist/extensions/pi-subagents/src/runs/shared/nested-path.ts +1 -1
  212. package/dist/extensions/pi-subagents/src/runs/shared/orca-progress-tabs.ts +18 -7
  213. package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +57 -12
  214. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +3 -4
  215. package/dist/extensions/pi-subagents/src/runs/shared/permissions.ts +0 -11
  216. package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +4 -1
  217. package/dist/extensions/pi-subagents/src/runs/shared/readonly-drain-observation.ts +42 -0
  218. package/dist/extensions/pi-subagents/src/runs/shared/readonly-model-continuation.ts +69 -0
  219. package/dist/extensions/pi-subagents/src/runs/shared/readonly-session-evidence.ts +307 -0
  220. package/dist/extensions/pi-subagents/src/runs/shared/run-fanout-budget.ts +8 -21
  221. package/dist/extensions/pi-subagents/src/runs/shared/runtime-acknowledged-extensions.ts +3 -30
  222. package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +17 -4
  223. package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +2 -0
  224. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +99 -386
  225. package/dist/extensions/pi-subagents/src/runs/shared/tool-availability.ts +18 -62
  226. package/dist/extensions/pi-subagents/src/runs/shared/tool-budget.ts +0 -14
  227. package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +31 -9
  228. package/dist/extensions/pi-subagents/src/runs/shared/worktree-setup-command.ts +190 -0
  229. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +506 -226
  230. package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +1 -1
  231. package/dist/extensions/pi-subagents/src/shared/jsonl-writer.ts +11 -0
  232. package/dist/extensions/pi-subagents/src/shared/model-response-aliases.ts +13 -0
  233. package/dist/extensions/pi-subagents/src/shared/thinking-ceiling.ts +0 -6
  234. package/dist/extensions/pi-subagents/src/shared/types.ts +145 -89
  235. package/dist/extensions/pi-subagents/src/shared/utils.ts +13 -6
  236. package/dist/extensions/pi-subagents/src/shared/watch-strategy.ts +2 -0
  237. package/dist/extensions/pi-subagents/src/shared/workflow-child-permit.ts +18 -13
  238. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +0 -6
  239. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +1 -1
  240. package/dist/extensions/pi-subagents/src/tui/fleet.ts +11 -6
  241. package/dist/extensions/pi-subagents/src/tui/render.ts +277 -46
  242. package/dist/extensions/pi-subagents/src/watchdog/child-status.ts +0 -1
  243. package/dist/extensions/pi-subagents/src/watchdog/register-child.ts +12 -12
  244. package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +3 -3
  245. package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +116 -15
  246. package/dist/extensions/pi-subagents/src/workflows/workflow-checklist.ts +15 -18
  247. package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +57 -8
  248. package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +19 -19
  249. package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +3 -3
  250. package/dist/extensions/pi-subagents/src/workflows/workflow-resources.ts +97 -22
  251. package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +3 -0
  252. package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +336 -21
  253. package/dist/extensions/pi-subagents/test/integration/async-execution.part-1.test.ts +1181 -0
  254. package/dist/extensions/pi-subagents/test/integration/async-execution.part-2.test.ts +2240 -0
  255. package/dist/extensions/pi-subagents/test/integration/async-execution.part-3.test.ts +2268 -0
  256. package/dist/extensions/pi-subagents/test/integration/async-execution.part-4.test.ts +1512 -0
  257. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +231 -16
  258. package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +4 -18
  259. package/dist/extensions/pi-subagents/test/integration/foreign-workflow-steering.test.ts +95 -0
  260. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +9 -15
  261. package/dist/extensions/pi-subagents/test/integration/in-process-child.test.ts +374 -0
  262. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +20 -10
  263. package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +18 -6
  264. package/dist/extensions/pi-subagents/test/integration/recovered-assistant-error.test.ts +151 -0
  265. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +42 -1
  266. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +150 -25
  267. package/dist/extensions/pi-subagents/test/integration/result-publication.test.ts +354 -0
  268. package/dist/extensions/pi-subagents/test/integration/shared-cwd-terminal-evidence.test.ts +117 -0
  269. package/dist/extensions/pi-subagents/test/integration/single-execution.part-1.test.ts +3678 -0
  270. package/dist/extensions/pi-subagents/test/integration/{single-execution.test.ts → single-execution.part-2.test.ts} +500 -4207
  271. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +1 -2
  272. package/dist/extensions/pi-subagents/test/integration/workflow-result-publication.test.ts +127 -0
  273. package/dist/extensions/pi-subagents/test/integration/workflow-steer-inbox.test.ts +365 -0
  274. package/dist/extensions/pi-subagents/test/smoke/pi085-child.ts +31 -0
  275. package/dist/extensions/pi-subagents/test/smoke/pi085-clean-install.mjs +74 -0
  276. package/dist/extensions/pi-subagents/test/smoke/pi085-extension.ts +16 -0
  277. package/dist/extensions/pi-subagents/test/support/async-execution-fixture.ts +699 -0
  278. package/dist/extensions/pi-subagents/test/support/fake-child-session.ts +418 -0
  279. package/dist/extensions/pi-subagents/test/support/foreign-workflow-steer-host.mjs +13 -0
  280. package/dist/extensions/pi-subagents/test/support/mock-pi.ts +30 -76
  281. package/dist/extensions/pi-subagents/test/support/notify-diagnostics-fixture.ts +84 -0
  282. package/dist/extensions/pi-subagents/test/support/result-publication-capacity-preload.mjs +70 -0
  283. package/dist/extensions/pi-subagents/test/support/runner-child-session-factory.ts +17 -0
  284. package/dist/extensions/pi-subagents/test/support/single-execution-fixture.ts +390 -0
  285. package/dist/extensions/pi-subagents/test/unit/acceptance-compaction.test.ts +120 -0
  286. package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +24 -3
  287. package/dist/extensions/pi-subagents/test/unit/advertised-agent-prompt.test.ts +87 -0
  288. package/dist/extensions/pi-subagents/test/unit/advertised-agent-refresh.test.ts +163 -0
  289. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +70 -31
  290. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +78 -3
  291. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +2 -8
  292. package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +1 -1
  293. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +73 -66
  294. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +51 -1
  295. package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +49 -1
  296. package/dist/extensions/pi-subagents/test/unit/async-spawn-preload.test.ts +103 -0
  297. package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +3 -3
  298. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +9 -8
  299. package/dist/extensions/pi-subagents/test/unit/capability-ceiling.test.ts +10 -7
  300. package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +48 -6
  301. package/dist/extensions/pi-subagents/test/unit/child-runtime-config.test.ts +90 -0
  302. package/dist/extensions/pi-subagents/test/unit/{pi-args-permission-system.test.ts → child-tool-plan-permission-system.test.ts} +48 -86
  303. package/dist/extensions/pi-subagents/test/unit/child-tool-plan.test.ts +33 -0
  304. package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +18 -18
  305. package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +9 -9
  306. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +8 -7
  307. package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +225 -65
  308. package/dist/extensions/pi-subagents/test/unit/extension-bindings.test.ts +17 -22
  309. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +11 -1
  310. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +47 -3
  311. package/dist/extensions/pi-subagents/test/unit/foreign-workflow-steering.test.ts +74 -0
  312. package/dist/extensions/pi-subagents/test/unit/fork-cache-key.test.ts +23 -29
  313. package/dist/extensions/pi-subagents/test/unit/host-peer-runtime-imports.test.ts +96 -4
  314. package/dist/extensions/pi-subagents/test/unit/host-step-status.test.ts +4 -4
  315. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +116 -55
  316. package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +58 -1
  317. package/dist/extensions/pi-subagents/test/unit/llm-intent-arbiter.test.ts +104 -3
  318. package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +10 -1
  319. package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +31 -1
  320. package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +102 -51
  321. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +196 -6
  322. package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +181 -38
  323. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +62 -70
  324. package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +58 -53
  325. package/dist/extensions/pi-subagents/test/unit/notify-diagnostics.test.ts +42 -0
  326. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +84 -0
  327. package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +13 -5
  328. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +21 -5
  329. package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +5 -4
  330. package/dist/extensions/pi-subagents/test/unit/permissions.test.ts +2 -6
  331. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +28 -2
  332. package/dist/extensions/pi-subagents/test/unit/pi-web-session-liveness.test.ts +209 -0
  333. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +38 -1
  334. package/dist/extensions/pi-subagents/test/unit/prompt-audit-optional-peers.test.ts +43 -0
  335. package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +24 -2
  336. package/dist/extensions/pi-subagents/test/unit/readonly-drain-observation.test.ts +174 -0
  337. package/dist/extensions/pi-subagents/test/unit/readonly-model-continuation.test.ts +94 -0
  338. package/dist/extensions/pi-subagents/test/unit/readonly-session-evidence.test.ts +1329 -0
  339. package/dist/extensions/pi-subagents/test/unit/recursion-guard.test.ts +29 -80
  340. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +11 -8
  341. package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +2 -2
  342. package/dist/extensions/pi-subagents/test/unit/retained-nested-route-tracker.test.ts +175 -0
  343. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +38 -12
  344. package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +2 -5
  345. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +89 -1
  346. package/dist/extensions/pi-subagents/test/unit/runtime-acknowledged-extensions.test.ts +2 -16
  347. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +27 -3
  348. package/dist/extensions/pi-subagents/test/unit/scheduled-supervisor-demand.test.ts +215 -0
  349. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +15 -11
  350. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +237 -1
  351. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +2 -5
  352. package/dist/extensions/pi-subagents/test/unit/streamed-progress-bounds.test.ts +2 -2
  353. package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +14 -1
  354. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +130 -739
  355. package/dist/extensions/pi-subagents/test/unit/supervisor-ask-registration.test.ts +682 -0
  356. package/dist/extensions/pi-subagents/test/unit/supervisor-ui.test.ts +137 -0
  357. package/dist/extensions/pi-subagents/test/unit/tool-budget.test.ts +1 -11
  358. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +23 -3
  359. package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +8 -1
  360. package/dist/extensions/pi-subagents/test/unit/watchdog-tool-actions.test.ts +19 -1
  361. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +72 -4
  362. package/dist/extensions/pi-subagents/test/unit/workflow-checklist.test.ts +17 -3
  363. package/dist/extensions/pi-subagents/test/unit/workflow-child-summary.test.ts +34 -0
  364. package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +12 -2
  365. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +46 -6
  366. package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +3 -3
  367. package/dist/extensions/pi-subagents/test/unit/workflow-resources.test.ts +133 -1
  368. package/dist/extensions/pi-subagents/test/unit/workflow-resume-hint.test.ts +53 -2
  369. package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +222 -14
  370. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +526 -85
  371. package/dist/extensions/pi-web-agent/src/backends/config.ts +1 -0
  372. package/dist/extensions/pi-web-agent/src/backends/settings-reader.ts +5 -3
  373. package/dist/extensions/pi-web-agent/src/search/tokenin.ts +7 -3
  374. package/dist/extensions/pi-web-agent/src/types.ts +1 -1
  375. package/dist/extensions/pi-zentui/README.md +17 -0
  376. package/dist/extensions/pi-zentui/assets/screenshots/footer-status-hyperlink.png +0 -0
  377. package/dist/extensions/pi-zentui/docs/configuration.md +71 -2
  378. package/dist/extensions/pi-zentui/extensions/zentui/config.ts +11 -0
  379. package/dist/extensions/pi-zentui/extensions/zentui/editor-transfer.ts +14 -0
  380. package/dist/extensions/pi-zentui/extensions/zentui/extension-status.ts +29 -13
  381. package/dist/extensions/pi-zentui/extensions/zentui/footer-layout.ts +5 -4
  382. package/dist/extensions/pi-zentui/extensions/zentui/footer-text.ts +11 -0
  383. package/dist/extensions/pi-zentui/extensions/zentui/footer.ts +11 -10
  384. package/dist/extensions/pi-zentui/extensions/zentui/index.ts +77 -3
  385. package/dist/extensions/pi-zentui/extensions/zentui/presets.ts +77 -0
  386. package/dist/extensions/pi-zentui/extensions/zentui/settings-command.ts +103 -2
  387. package/dist/extensions/pi-zentui/extensions/zentui/working-line-extension-segments.ts +115 -0
  388. package/dist/extensions/pi-zentui/extensions/zentui/working-line.ts +87 -5
  389. package/dist/extensions/pi-zentui/package-lock.json +277 -517
  390. package/dist/extensions/pi-zentui/package.json +7 -4
  391. package/dist/extensions/pi-zentui/test/config-presets.test.ts +238 -0
  392. package/dist/extensions/pi-zentui/test/editor-transfer.test.ts +24 -1
  393. package/dist/extensions/pi-zentui/test/extension-compliance.test.ts +570 -2
  394. package/dist/extensions/pi-zentui/test/extension-status.test.ts +90 -0
  395. package/dist/extensions/pi-zentui/test/footer-hyperlink.test.ts +243 -0
  396. package/dist/extensions/pi-zentui/test/package-contents.mjs +1 -0
  397. package/dist/extensions/pi-zentui/test/presets.test.ts +121 -0
  398. package/dist/extensions/pi-zentui/test/settings-command.test.ts +205 -1
  399. package/dist/extensions/pi-zentui/test/working-line-extension-segments.test.ts +139 -0
  400. package/dist/extensions/pi-zentui/test/working-line-lifecycle.integration.test.ts +237 -3
  401. package/dist/extensions/pi-zentui/test/working-line.test.ts +94 -2
  402. package/dist/index.d.ts +1 -1
  403. package/dist/main.js +4 -1
  404. package/dist/modes/interactive/chat-viewport.d.ts +19 -0
  405. package/dist/modes/interactive/chat-viewport.js +27 -0
  406. package/dist/modes/interactive/components/assistant-message.d.ts +6 -2
  407. package/dist/modes/interactive/components/assistant-message.js +30 -13
  408. package/dist/modes/interactive/components/custom-editor.d.ts +10 -1
  409. package/dist/modes/interactive/components/custom-editor.js +39 -1
  410. package/dist/modes/interactive/components/first-time-setup.js +1 -1
  411. package/dist/modes/interactive/components/index.d.ts +1 -1
  412. package/dist/modes/interactive/components/markdown-transform.d.ts +2 -0
  413. package/dist/modes/interactive/components/markdown-transform.js +18 -0
  414. package/dist/modes/interactive/components/model-selector.js +19 -17
  415. package/dist/modes/interactive/components/scoped-models-selector.js +21 -23
  416. package/dist/modes/interactive/components/settings-selector.d.ts +7 -1
  417. package/dist/modes/interactive/components/settings-selector.js +128 -20
  418. package/dist/modes/interactive/components/settings-submenu.d.ts +71 -0
  419. package/dist/modes/interactive/components/settings-submenu.js +164 -0
  420. package/dist/modes/interactive/components/status-indicator.d.ts +3 -1
  421. package/dist/modes/interactive/components/status-indicator.js +10 -3
  422. package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
  423. package/dist/modes/interactive/components/thinking-selector.js +75 -18
  424. package/dist/modes/interactive/components/tool-execution.d.ts +21 -4
  425. package/dist/modes/interactive/components/tool-execution.js +35 -33
  426. package/dist/modes/interactive/components/trust-selector.js +2 -2
  427. package/dist/modes/interactive/interactive-mode.d.ts +13 -15
  428. package/dist/modes/interactive/interactive-mode.js +144 -80
  429. package/dist/modes/interactive/session-share.d.ts +15 -0
  430. package/dist/modes/interactive/session-share.js +183 -0
  431. package/dist/modes/interactive/theme/dark.json +2 -1
  432. package/dist/modes/interactive/theme/light.json +2 -1
  433. package/dist/modes/interactive/theme/theme-controller.d.ts +1 -0
  434. package/dist/modes/interactive/theme/theme-controller.js +5 -0
  435. package/dist/modes/interactive/theme/theme-json.d.ts +83 -0
  436. package/dist/modes/interactive/theme/theme-json.js +129 -0
  437. package/dist/modes/interactive/theme/theme-schema.json +9 -1
  438. package/dist/modes/interactive/theme/theme.d.ts +14 -5
  439. package/dist/modes/interactive/theme/theme.js +18 -119
  440. package/dist/modes/interactive/tui-renderer.d.ts +20 -0
  441. package/dist/modes/interactive/tui-renderer.js +65 -0
  442. package/dist/utils/exif-orientation.js +2 -3
  443. package/dist/utils/management-http.d.ts +24 -0
  444. package/dist/utils/management-http.js +53 -0
  445. package/dist/utils/text.d.ts +7 -0
  446. package/dist/utils/text.js +8 -0
  447. package/dist/utils/tools-manager.d.ts +1 -0
  448. package/dist/utils/tools-manager.js +43 -21
  449. package/docs/docs.json +0 -4
  450. package/package.json +4 -4
  451. package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +0 -415
  452. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +0 -1059
  453. package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +0 -116
  454. package/dist/extensions/pi-subagents/src/shared/post-exit-stdio-guard.ts +0 -85
  455. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +0 -224
  456. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +0 -6986
  457. package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +0 -447
  458. package/dist/extensions/pi-subagents/test/support/real-session-child-cli.mjs +0 -185
  459. package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +0 -311
  460. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-pi-args.test.ts +0 -84
  461. package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +0 -202
  462. package/dist/extensions/pi-subagents/test/unit/close-grace-timer.test.ts +0 -101
  463. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +0 -2347
  464. package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +0 -104
  465. package/dist/extensions/pi-subagents/test/unit/windows-hide-spawn.test.ts +0 -49
  466. package/dist/skills/imagegen-frontend-mobile/SKILL.md +0 -1465
  467. package/dist/skills/imagegen-frontend-web/SKILL.md +0 -987
  468. package/dist/skills/implanger/SKILL.md +0 -70
  469. package/dist/skills/output/SKILL.md +0 -49
  470. package/dist/skills/planger/SKILL.md +0 -167
  471. package/dist/skills/workflow/SKILL.md +0 -95
  472. package/docs/workflows.md +0 -18
  473. /package/dist/bun/{register-bedrock.d.ts → runtime-setup.d.ts} +0 -0
@@ -179,6 +179,89 @@ describe('sqlite-memory-store', () => {
179
179
  assert.deepStrictEqual(getMemories(dbManager, { project: 'spoofed-project' }), []);
180
180
  });
181
181
 
182
+ it('reports a degraded result (not a swallowed success) on FTS5 index errors', () => {
183
+ // A genuine FTS5 search-index error must not look like a successful
184
+ // zero-row sync: the result carries degraded + reason so the caller can
185
+ // surface /memory-sync-markdown repair guidance.
186
+ const failingDb = {
187
+ prepare: (sql: string) => ({
188
+ get: () => undefined,
189
+ all: () => [],
190
+ run: () => {
191
+ throw new Error('fts5: table memory_fts is corrupted');
192
+ },
193
+ }),
194
+ } as never;
195
+ const stubDbManager = {
196
+ getDb: () => failingDb,
197
+ withCorruptionRecovery: <T>(operation: () => T): T => operation(),
198
+ } as unknown as DatabaseManager;
199
+
200
+ const result = reconcileMarkdownMemoryScope(
201
+ stubDbManager,
202
+ ['degraded reconcile test entry'],
203
+ 'memory',
204
+ null,
205
+ );
206
+ assert.equal(result.degraded, true);
207
+ assert.match(result.degradedReason ?? '', /fts5/);
208
+ assert.equal(result.inserted, 0);
209
+ });
210
+
211
+ it('propagates degraded from failure scopes (first reason wins)', () => {
212
+ // When multiple failure scopes are degraded, the aggregate result must
213
+ // be degraded with the first reason (not the last) so the user sees the
214
+ // original failure, not a later duplicate.
215
+ let callCount = 0;
216
+ const failingDb = {
217
+ prepare: (sql: string) => ({
218
+ get: () => undefined,
219
+ all: () => [],
220
+ run: () => {
221
+ callCount++;
222
+ throw new Error(`fts5: error #${callCount}`);
223
+ },
224
+ }),
225
+ } as never;
226
+ const stubDbManager = {
227
+ getDb: () => failingDb,
228
+ withCorruptionRecovery: <T>(operation: () => T): T => operation(),
229
+ } as unknown as DatabaseManager;
230
+
231
+ const result = reconcileMarkdownFailureScopes(
232
+ stubDbManager,
233
+ [
234
+ 'failure entry one — Project: project-a <!-- created=2026-01-01 -->',
235
+ 'failure entry two — Project: project-b <!-- created=2026-01-01 -->',
236
+ ],
237
+ );
238
+ assert.equal(result.degraded, true);
239
+ assert.match(result.degradedReason ?? '', /fts5: error #1/);
240
+ });
241
+
242
+ it('still propagates corruption errors instead of degrading (recovery must run)', () => {
243
+ // Corruption signals are NOT FTS5 errors: they must escape so
244
+ // DatabaseManager quarantines + rebuilds, never a degraded zero-result.
245
+ const failingDb = {
246
+ prepare: () => ({
247
+ get: () => undefined,
248
+ all: () => [],
249
+ run: () => {
250
+ throw new Error('database disk image is malformed');
251
+ },
252
+ }),
253
+ } as never;
254
+ const stubDbManager = {
255
+ getDb: () => failingDb,
256
+ withCorruptionRecovery: <T>(operation: () => T): T => operation(),
257
+ } as unknown as DatabaseManager;
258
+
259
+ assert.throws(
260
+ () => reconcileMarkdownMemoryScope(stubDbManager, ['corruption test entry'], 'memory', null),
261
+ /malformed/,
262
+ );
263
+ });
264
+
182
265
  it('prunes only absent rows in the exact target and project scope', () => {
183
266
  addMemory(dbManager, 'kept global memory', 'memory', null);
184
267
  addMemory(dbManager, 'orphaned global memory', 'memory', null);
@@ -333,6 +416,18 @@ describe('sqlite-memory-store', () => {
333
416
  addMemory(dbManager, 'timezone: AEST', 'user');
334
417
  });
335
418
 
419
+ it('degrades an all-stop-word query to the LIKE fallback instead of []', () => {
420
+ // "the" is a stop word and "and"/"or" connectors, so FTS5 normalization
421
+ // leaves nothing to match. The query must fall through to the scoped
422
+ // literal fallback (which still searches the raw terms) rather than
423
+ // hard-return an empty result set.
424
+ addMemory(dbManager, 'the build passes after restart');
425
+
426
+ const results = searchMemories(dbManager, 'the and or');
427
+ assert.ok(results.length > 0, 'all-stop-word query must reach the LIKE fallback, not []');
428
+ assert.ok(results.some(r => r.content.includes('the')));
429
+ });
430
+
336
431
  it('should find memories by keyword', () => {
337
432
  const results = searchMemories(dbManager, 'pnpm');
338
433
  assert.ok(results.length > 0);
@@ -344,6 +439,36 @@ describe('sqlite-memory-store', () => {
344
439
  assert.ok(results.length > 0);
345
440
  assert.ok(results.some(r => r.content.includes('Prisma')));
346
441
  });
442
+
443
+ it('returns only project-attributed memories for target "project"', () => {
444
+ const results = searchMemories(dbManager, 'Prisma', { target: 'project' });
445
+
446
+ assert.ok(results.length > 0);
447
+ assert.ok(results.every((r) => r.project === 'project-a'));
448
+ assert.ok(results.every((r) => r.target === 'memory'));
449
+ });
450
+
451
+ it('keeps target "memory" matching both global and project-attributed memories', () => {
452
+ const global = searchMemories(dbManager, 'pnpm', { target: 'memory' });
453
+ const project = searchMemories(dbManager, 'Prisma', { target: 'memory' });
454
+
455
+ assert.ok(global.some((r) => r.project === null));
456
+ assert.ok(project.length > 0);
457
+ assert.ok(project.every((r) => r.project === 'project-a'));
458
+ });
459
+
460
+ it('combines target "project" with an explicit project filter', () => {
461
+ addMemory(dbManager, 'uses Bun with PostgreSQL', 'memory', 'project-b');
462
+
463
+ const named = searchMemories(dbManager, 'PostgreSQL', { target: 'project', project: 'project-b' });
464
+ const anyProject = searchMemories(dbManager, 'PostgreSQL', { target: 'project' });
465
+ const globalOnly = searchMemories(dbManager, 'PostgreSQL', { target: 'project', project: null });
466
+
467
+ assert.ok(named.length > 0);
468
+ assert.ok(named.every((r) => r.project === 'project-b'));
469
+ assert.ok(anyProject.some((r) => r.project === 'project-a'));
470
+ assert.strictEqual(globalOnly.length, 0);
471
+ });
347
472
  it('finds pure CJK substrings with the trigram tokenizer', () => {
348
473
  addMemory(dbManager, '设备清单包含 NAS 和备份策略');
349
474
 
@@ -370,6 +495,17 @@ describe('sqlite-memory-store', () => {
370
495
  assert.ok(results.some((result) => result.content.includes('设备清单')));
371
496
  });
372
497
 
498
+ it('applies target "project" in the CJK literal fallback path', () => {
499
+ addMemory(dbManager, '项目约定使用 pnpm', 'memory', 'project-a');
500
+ addMemory(dbManager, '项目全局笔记');
501
+
502
+ const results = searchMemories(dbManager, '项目', { target: 'project' });
503
+
504
+ assert.ok(results.length > 0);
505
+ assert.ok(results.every((r) => r.project === 'project-a'));
506
+ assert.ok(results.every((r) => r.target === 'memory'));
507
+ });
508
+
373
509
 
374
510
  it('should match multi-word queries without requiring an exact phrase', () => {
375
511
  const results = searchMemories(dbManager, 'gpu issue');
@@ -456,6 +592,45 @@ describe('sqlite-memory-store', () => {
456
592
  const results = searchMemories(dbManager, 'AND OR NOT');
457
593
  assert.strictEqual(results.length, 0);
458
594
  });
595
+
596
+ it('ranks a dense old match above a fresher, more diluted one (BM25 before recency)', () => {
597
+ addMemory(dbManager, 'deploy target is the staging cluster');
598
+ addMemory(
599
+ dbManager,
600
+ 'unrelated retrospective notes that mention deploy once among a great many other words about hiring, budgets, roadmaps, vendor calls, office moves and quarterly planning for the staging of a conference'
601
+ );
602
+ const db = dbManager.getDb();
603
+ db.prepare("UPDATE memories SET last_referenced = '2025-01-01' WHERE content LIKE 'deploy target%'").run();
604
+ db.prepare("UPDATE memories SET last_referenced = '2026-08-30' WHERE content LIKE 'unrelated retrospective%'").run();
605
+
606
+ const results = searchMemories(dbManager, 'deploy staging');
607
+
608
+ // Both rows match; recency ordering would put the long fresh note first.
609
+ assert.strictEqual(results.length, 2);
610
+ assert.ok(results[0].content.startsWith('deploy target is the staging cluster'));
611
+ });
612
+
613
+ it('still broadens a two-term natural-language query through the OR fallback', () => {
614
+ // Neither "dark" nor "chocolate" co-occur, so the implicit-AND query
615
+ // misses and only the OR fallback can recover this row. The existing
616
+ // fallback test uses three terms; this pins the two-term case.
617
+ addMemory(dbManager, 'user prefers dark mode UI theme', 'user');
618
+
619
+ const results = searchMemories(dbManager, 'dark chocolate', { target: 'user' });
620
+
621
+ assert.ok(results.some((r) => r.content.includes('dark mode')));
622
+ });
623
+
624
+ it('recovers a natural-language query whose raw FTS5 form fails to parse', () => {
625
+ // "DO NOT USE FIND /" passes through as raw FTS5 syntax and throws;
626
+ // runSearch must catch that and let the natural-language retry run.
627
+ addMemory(dbManager, 'Never search whole filesystem from root. Do not run find /.', 'user');
628
+
629
+ assert.doesNotThrow(() => searchMemories(dbManager, 'DO NOT USE FIND /', { target: 'user' }));
630
+ const results = searchMemories(dbManager, 'DO NOT USE FIND /', { target: 'user' });
631
+
632
+ assert.ok(results.some((r) => r.content.includes('find /')));
633
+ });
459
634
  });
460
635
 
461
636
  describe('getMemories', () => {
@@ -127,12 +127,12 @@ describe("sqlite-native loader", () => {
127
127
  it("formats actionable ABI recovery text", () => {
128
128
  const message = formatBetterSqlite3AbiError({
129
129
  originalError: new Error("NODE_MODULE_VERSION 115"),
130
- packageRoot: "/Users/me/.pi/agent/npm/node_modules/better-sqlite3",
130
+ packageRoot: "/Users/me/.selesai/agent/npm/node_modules/better-sqlite3",
131
131
  rebuildAttempted: true,
132
132
  rebuildDetail: "exit 1",
133
133
  });
134
134
  assert.match(message, /NODE_MODULE_VERSION/);
135
- assert.match(message, /\/Users\/me\/\.pi\/agent\/npm\/node_modules\/better-sqlite3/);
135
+ assert.match(message, /\/Users\/me\/\.selesai\/agent\/npm\/node_modules\/better-sqlite3/);
136
136
  assert.match(message, /npm rebuild better-sqlite3/);
137
137
  assert.match(message, /Homebrew/);
138
138
  });
@@ -66,6 +66,28 @@ describe('registerMemorySearchTool', () => {
66
66
  dbManager.close();
67
67
  });
68
68
 
69
+ it('accepts target "project" as a filter and shows the schema value', async () => {
70
+ const dbManager = makeDbManager();
71
+ addMemory(dbManager, 'project deployment convention', 'memory', 'project-a');
72
+ addMemory(dbManager, 'global deployment convention');
73
+ addMemory(dbManager, 'project failure deployment lesson', 'failure', 'project-a');
74
+
75
+ let captured: any;
76
+ registerMemorySearchTool({ registerTool: (def: any) => { captured = def; } } as any, dbManager);
77
+
78
+ assert.ok(captured.parameters.properties.target.enum.includes('project'));
79
+
80
+ const result = await captured.execute('tc-1', { query: 'deployment', target: 'project' });
81
+ const text = result.content[0].text;
82
+
83
+ assert.strictEqual(result.details.success, true);
84
+ assert.strictEqual(result.details.count, 1);
85
+ assert.match(text, /scope=project:project-a \[target=project\]/);
86
+ assert.doesNotMatch(text, /scope=global/);
87
+
88
+ dbManager.close();
89
+ });
90
+
69
91
  it('keeps copied results reversible when a project name contains brackets', async () => {
70
92
  const dbManager = makeDbManager();
71
93
  addMemory(dbManager, 'literal project entry', 'memory', 'foo] bar');
@@ -9,7 +9,7 @@ import path from "node:path";
9
9
  import { registerMemoryTool } from "../../src/tools/memory-tool.js";
10
10
  import { MemoryStore } from "../../src/store/memory-store.js";
11
11
  import { DatabaseManager } from "../../src/store/db.js";
12
- import { getMemories, syncMemoryEntry } from "../../src/store/sqlite-memory-store.js";
12
+ import { getMemories, searchMemories, syncMemoryEntry } from "../../src/store/sqlite-memory-store.js";
13
13
  import { ENTRY_DELIMITER, MEMORY_FILE } from "../../src/constants.js";
14
14
  import { Value } from "typebox/value";
15
15
 
@@ -147,6 +147,42 @@ describe("registerMemoryTool", () => {
147
147
  assert.strictEqual(results[0].content, 'Entry one');
148
148
  });
149
149
 
150
+ it("lands over-cap policy-only adds in searchable SQLite", async () => {
151
+ let capturedResult: any;
152
+ const mockPi = {
153
+ registerTool: (def: any) => {
154
+ if (!capturedResult || def.name === "memory_add") capturedResult = def;
155
+ },
156
+ } as unknown as ExtensionAPI;
157
+ const store = new MemoryStore({
158
+ memoryMode: "policy-only",
159
+ memoryCharLimit: 40,
160
+ userCharLimit: 5000,
161
+ projectCharLimit: 5000,
162
+ nudgeInterval: 10,
163
+ reviewEnabled: false,
164
+ flushOnCompact: false,
165
+ flushOnShutdown: false,
166
+ flushMinTurns: 6,
167
+ autoConsolidate: false,
168
+ correctionDetection: false,
169
+ failureInjectionEnabled: true,
170
+ failureInjectionMaxAgeDays: 7,
171
+ failureInjectionMaxEntries: 5,
172
+ nudgeToolCalls: 15,
173
+ consolidationTimeoutMs: 60000,
174
+ memoryDir: tmpDir,
175
+ });
176
+ await store.loadFromDisk();
177
+ registerMemoryTool(mockPi, store, null, dbManager);
178
+ const first = await capturedResult.execute("tc-1", { action: "add", target: "memory", content: "alpha entry" }, undefined as any, undefined as any, undefined as any);
179
+ assert.strictEqual(first.details.success, true);
180
+ const second = await capturedResult.execute("tc-2", { action: "add", target: "memory", content: "beta entry past the tiny cap" }, undefined as any, undefined as any, undefined as any);
181
+ assert.strictEqual(second.details.success, true);
182
+ const results = searchMemories(dbManager, "beta entry past the tiny cap", { target: "memory" });
183
+ assert.ok(results.some((r) => r.content.includes("beta entry past the tiny cap")));
184
+ });
185
+
150
186
  it("reports the matching target when replace is sent to the wrong target", async () => {
151
187
  let removeTool: any;
152
188
  const mockPi = {
@@ -4,6 +4,19 @@ All notable changes to the `pi-intercom` extension will be documented in this fi
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.13.0] - 2026-09-02
8
+
9
+ ### Highlights
10
+ - You can now give the current session a friendly alias from pi-intercom.
11
+ - Aliases show up right away in the session list, messages, replies, overlays, and incoming-message displays.
12
+ - Windows broker startup is more reliable with non-ASCII profile paths and stricter Windows Script Host setups.
13
+
14
+ ### Added
15
+ - Added `/alias <name>` plus the interactive `/alias` and `/alias menu` forms for naming the current session. Thanks to [@yceachan](https://github.com/yceachan) for issue #122.
16
+
17
+ ### Fixed
18
+ - Fixed hidden Windows broker startup when the user profile path contains non-ASCII characters or Windows Script Host cannot infer the VBScript engine. Thanks to [@maelo1028](https://github.com/maelo1028) for issue #121 and [@Agustin-Prieto](https://github.com/Agustin-Prieto) for issue #123.
19
+
7
20
  ## [0.12.1] - 2026-08-29
8
21
 
9
22
  ### Highlights
@@ -58,6 +58,20 @@ The session list only shows intercom-connected sessions, not every open Selesai
58
58
 
59
59
  If a session is unnamed, pi-intercom exposes a collision-resistant runtime-only fallback alias like `subagent-chat-1a2b3c4d-5e6f-7a8b` so other connected sessions can target it. That alias is not persisted as the Selesai session title or treated as a reconnect identity, so `selesai --resume` can keep showing the transcript snippet without allowing a different unnamed process to inherit queued mail.
60
60
 
61
+ ### Name your current session
62
+
63
+ Use `/alias <name>` as a pi-intercom-friendly way to name the current session:
64
+
65
+ ```text
66
+ /alias api-worker
67
+ ```
68
+
69
+ The alias is Selesai's session name, so it is persisted in the session and immediately
70
+ published to pi-intercom peers. Session lists, send/reply results, overlays, and
71
+ incoming message headers use it when available. In an interactive UI, `/alias`
72
+ or `/alias menu` opens an input for the current session's alias; it does not
73
+ rename other sessions. Use `/alias <name>` in non-UI modes.
74
+
61
75
  ## Quick Start
62
76
 
63
77
  ### From the Keyboard
@@ -135,11 +149,11 @@ The most natural use of pi-intercom is splitting a task between two sessions —
135
149
 
136
150
  ### Setup
137
151
 
138
- Open two terminals and start pi in each. Name them so they can find each other:
152
+ Open two terminals and start Selesai in each. Name them so they can find each other:
139
153
 
140
154
  ```
141
155
  # Terminal 1 # Terminal 2
142
- /name planner /name worker
156
+ /alias planner /alias worker
143
157
  ```
144
158
 
145
159
  Verify they see each other from either session:
@@ -1,7 +1,7 @@
1
1
  import test from "node:test";
2
2
  import assert from "node:assert/strict";
3
3
  import path from "node:path";
4
- import { cpSync, existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
4
+ import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
5
5
  import { tmpdir } from "node:os";
6
6
  import { fileURLToPath, pathToFileURL } from "node:url";
7
7
  import {
@@ -12,6 +12,7 @@ import {
12
12
  getWindowsBrokerCommandLine,
13
13
  getWindowsHiddenLauncherPath,
14
14
  isBrokerHealthOkMessage,
15
+ writeWindowsHiddenLauncher,
15
16
  } from "./spawn.ts";
16
17
 
17
18
  test("getTsxCliPath resolves tsx cli via module resolution", () => {
@@ -80,6 +81,21 @@ test("getWindowsHiddenLauncherScript runs the broker command without showing a c
80
81
  assert.match(script, /, 0, False/);
81
82
  });
82
83
 
84
+ test("writeWindowsHiddenLauncher writes a UTF-16LE script with a BOM", () => {
85
+ const intercomDir = mkdtempSync(path.join(tmpdir(), "pi-intercom-用户-"));
86
+ const launcherPath = path.join(intercomDir, "broker-launch.vbs");
87
+ const commandLine = '"C:/Users/用户/node.exe" "C:/repo/用户/broker.ts"';
88
+
89
+ try {
90
+ writeWindowsHiddenLauncher(commandLine, launcherPath);
91
+ const contents = readFileSync(launcherPath);
92
+ assert.deepEqual([...contents.subarray(0, 2)], [0xff, 0xfe]);
93
+ assert.equal(contents.toString("utf16le"), `\uFEFF${getWindowsHiddenLauncherScript(commandLine)}`);
94
+ } finally {
95
+ rmSync(intercomDir, { recursive: true, force: true });
96
+ }
97
+ });
98
+
83
99
  test("getBrokerLaunchSpec uses wscript launcher on Windows without writing files", () => {
84
100
  const intercomDir = mkdtempSync(path.join(tmpdir(), "pi-intercom-"));
85
101
 
@@ -94,7 +110,7 @@ test("getBrokerLaunchSpec uses wscript launcher on Windows without writing files
94
110
  "C:/Program Files/nodejs/node.exe",
95
111
  );
96
112
  assert.equal(spec.command, "wscript.exe");
97
- assert.deepEqual(spec.args, [path.join(intercomDir, "broker-launch.vbs")]);
113
+ assert.deepEqual(spec.args, ["//E:VBScript", path.join(intercomDir, "broker-launch.vbs")]);
98
114
  assert.equal(spec.kind, "windows-launcher");
99
115
  const expectedTsxPath = getTsxCliPath("C:/repo");
100
116
  assert.equal(spec.launcherCommandLine, `"C:/Program Files/nodejs/node.exe" "${expectedTsxPath}" "C:/repo/broker.ts"`);
@@ -131,6 +147,7 @@ test("getBrokerLaunchSpec uses custom broker command on Windows", () => {
131
147
  try {
132
148
  const spec = getBrokerLaunchSpec("C:/repo/broker.ts", "bun", ["--smol"], "C:/repo", "win32", intercomDir, "C:/Program Files/nodejs/node.exe");
133
149
  assert.equal(spec.command, "wscript.exe");
150
+ assert.deepEqual(spec.args, ["//E:VBScript", path.join(intercomDir, "broker-launch.vbs")]);
134
151
  assert.equal(spec.kind, "windows-launcher");
135
152
  assert.equal(spec.launcherCommandLine, `"bun" "--smol" "C:/repo/broker.ts"`);
136
153
  } finally {
@@ -120,13 +120,13 @@ export function isBrokerHealthOkMessage(message: unknown, requestId: string): bo
120
120
  && response.version === INTERCOM_PROTOCOL_VERSION;
121
121
  }
122
122
 
123
- function writeWindowsHiddenLauncher(
123
+ export function writeWindowsHiddenLauncher(
124
124
  commandLine: string,
125
125
  launcherPath: string = getWindowsHiddenLauncherPath(),
126
126
  ): string {
127
127
  ensureIntercomRuntimeDir(dirname(launcherPath));
128
- writeFileSync(launcherPath, getWindowsHiddenLauncherScript(commandLine), {
129
- encoding: "utf-8",
128
+ writeFileSync(launcherPath, `\uFEFF${getWindowsHiddenLauncherScript(commandLine)}`, {
129
+ encoding: "utf16le",
130
130
  mode: INTERCOM_RUNTIME_FILE_MODE,
131
131
  });
132
132
  restrictIntercomRuntimeFile(launcherPath);
@@ -147,7 +147,7 @@ export function getBrokerLaunchSpec(
147
147
  return {
148
148
  kind: "windows-launcher",
149
149
  command: "wscript.exe",
150
- args: [launcherPath],
150
+ args: ["//E:VBScript", launcherPath],
151
151
  launcherPath,
152
152
  launcherCommandLine: getWindowsBrokerCommandLine(brokerPath, extensionDir, nodePath, brokerCommand, brokerArgs),
153
153
  captureStartupStderr: false,
@@ -761,7 +761,7 @@ export default function piIntercomExtension(pi: ExtensionAPI) {
761
761
  if (!liveContext) return;
762
762
  if (!liveContext.hasUI) {
763
763
  // Command handlers return void and print mode supplies a no-op UI. Keep
764
- // alias guidance visible without injecting a synthetic Pi message.
764
+ // alias guidance visible without injecting a synthetic Selesai message.
765
765
  console.error(message);
766
766
  return;
767
767
  }
@@ -183,11 +183,13 @@ function createExtensionHarness(sessionName: string | (() => string) = "child-wo
183
183
  const lifecycleHandlers = new Map<string, Array<(event: unknown, ctx: unknown) => unknown>>();
184
184
  const commands = new Map<string, (args: string, ctx: unknown) => unknown>();
185
185
  const tools: CapturedTool[] = [];
186
+ let currentSessionName = typeof sessionName === "function" ? sessionName() : sessionName;
186
187
  let activeToolNames = [...(options.activeTools ?? [])];
187
188
  const entries: Array<{ type: string; data: unknown }> = [];
188
189
  const sentMessages: Array<{ message: { customType?: string; content?: string; details?: unknown }; options?: { triggerTurn?: boolean; deliverAs?: string }; activeTools: string[] }> = [];
189
190
  const pi = {
190
- getSessionName: () => typeof sessionName === "function" ? sessionName() : sessionName,
191
+ getSessionName: () => typeof sessionName === "function" ? sessionName() : currentSessionName,
192
+ setSessionName: (name: string) => { currentSessionName = name; },
191
193
  events: {
192
194
  on: (channel: string, handler: (payload: unknown) => void) => {
193
195
  events.on(channel, handler);
@@ -1330,7 +1332,7 @@ test("intercom-id inserts a stable handoff snippet into the editor", { concurren
1330
1332
  piIntercomExtension(harness.pi as never);
1331
1333
  await harness.emitLifecycle("session_start");
1332
1334
  await harness.commands.get("intercom-id")!("", harness.ctx);
1333
- assert.match(editorText, /Existing note\n\nUse pi-intercom: intercom\(\{ action: "send", to: "session-child-test", message: "\.\.\." \}\)/);
1335
+ assert.match(editorText, /Existing note\n\nUse pi-intercom: intercom\(\{ action: "send", to: "session-child-test", message: "\.\.\." \}\)/);
1334
1336
  assert.match(notifications.at(-1) ?? "", /Inserted intercom contact target: session-child-test/);
1335
1337
  await harness.emitLifecycle("session_shutdown");
1336
1338
  } finally {
@@ -1338,6 +1340,123 @@ test("intercom-id inserts a stable handoff snippet into the editor", { concurren
1338
1340
  }
1339
1341
  });
1340
1342
 
1343
+ test("alias names the current session, opens the local input menu, and appears in intercom displays", { concurrency: false }, async () => {
1344
+ const { planner, orchestrator, cleanup } = await setupClients();
1345
+ const { default: piIntercomExtension } = await import("./index.ts");
1346
+ const inputCalls: Array<[string, string | undefined]> = [];
1347
+ const inputValues = ["menu-worker", "no-arg-worker"];
1348
+ const harness = createExtensionHarness("alias-worker", {
1349
+ hasUI: true,
1350
+ ui: {
1351
+ input: async (title: string, placeholder?: string) => {
1352
+ inputCalls.push([title, placeholder]);
1353
+ return inputValues.shift();
1354
+ },
1355
+ notify: () => undefined,
1356
+ },
1357
+ });
1358
+
1359
+ try {
1360
+ // Disable the background name poll for this test so the broker update
1361
+ // proves that /alias synchronizes presence directly.
1362
+ await withChildOrchestratorEnv({ namePollMs: "60000" }, async () => {
1363
+ piIntercomExtension(harness.pi as never);
1364
+ await harness.emitLifecycle("session_start");
1365
+ const initial = await waitForSessionByName(planner, "alias-worker");
1366
+ const aliasCommand = harness.commands.get("alias")!;
1367
+
1368
+ await aliasCommand("direct-worker", harness.ctx);
1369
+ const direct = await waitForSessionByName(planner, "direct-worker");
1370
+ assert.equal(direct.id, initial.id);
1371
+ assert.equal(harness.pi.getSessionName(), "direct-worker");
1372
+ assert.equal(inputCalls.length, 0);
1373
+
1374
+ await aliasCommand("menu", harness.ctx);
1375
+ await waitForSessionByName(planner, "menu-worker");
1376
+ await aliasCommand("", harness.ctx);
1377
+ const current = await waitForSessionByName(planner, "no-arg-worker");
1378
+ assert.equal(current.id, initial.id);
1379
+ assert.deepEqual(inputCalls, [
1380
+ ["Set session alias", "Current alias: direct-worker"],
1381
+ ["Set session alias", "Current alias: menu-worker"],
1382
+ ]);
1383
+
1384
+ const intercomTool = harness.tools.find((tool) => tool.name === "intercom")!;
1385
+ const listed = await intercomTool.execute("alias-list", { action: "list" }, new AbortController().signal, undefined, harness.ctx);
1386
+ assert.match(listed.content[0]?.text ?? "", /no-arg-worker/);
1387
+
1388
+ orchestrator.updatePresence({ name: "alias-orchestrator" });
1389
+ await waitForSessionByName(planner, "alias-orchestrator");
1390
+ const outgoing = once(orchestrator, "message") as Promise<[SessionInfo, Message]>;
1391
+ const sendResult = await intercomTool.execute("alias-send", {
1392
+ action: "send",
1393
+ to: "alias-orchestrator",
1394
+ message: "Alias display check.",
1395
+ }, new AbortController().signal, undefined, harness.ctx);
1396
+ assert.equal(sendResult.content[0]?.text, "Message sent to alias-orchestrator");
1397
+ assert.equal((await outgoing)[1].content.text, "Alias display check.");
1398
+
1399
+ const askId = "alias-reply-ask";
1400
+ assert.equal((await orchestrator.send(initial.id, {
1401
+ messageId: askId,
1402
+ text: "Reply using the alias.",
1403
+ expectsReply: true,
1404
+ })).delivered, true);
1405
+ await new Promise((resolve) => setTimeout(resolve, 25));
1406
+ const replyReceived = waitForReply(orchestrator, askId);
1407
+ const replyResult = await intercomTool.execute("alias-reply", {
1408
+ action: "reply",
1409
+ replyTo: askId,
1410
+ message: "Alias reply display check.",
1411
+ }, new AbortController().signal, undefined, harness.ctx);
1412
+ assert.equal(replyResult.content[0]?.text, "Reply sent to alias-orchestrator");
1413
+ assert.equal((await replyReceived).message.content.text, "Alias reply display check.");
1414
+ });
1415
+ } finally {
1416
+ await harness.emitLifecycle("session_shutdown");
1417
+ await cleanup();
1418
+ }
1419
+ });
1420
+
1421
+ test("alias reports no-UI usage and current alias without hanging", { concurrency: false }, async () => {
1422
+ const { planner, cleanup } = await setupClients();
1423
+ const { default: piIntercomExtension } = await import("./index.ts");
1424
+ const output: string[] = [];
1425
+ const previousConsoleError = console.error;
1426
+ console.error = (...args: unknown[]) => {
1427
+ output.push(args.map((value) => String(value)).join(" "));
1428
+ };
1429
+ const harness = createExtensionHarness("no-ui-worker");
1430
+
1431
+ try {
1432
+ await withChildOrchestratorEnv({ namePollMs: "60000" }, async () => {
1433
+ piIntercomExtension(harness.pi as never);
1434
+ await harness.emitLifecycle("session_start");
1435
+ const initial = await waitForSessionByName(planner, "no-ui-worker");
1436
+ const aliasCommand = harness.commands.get("alias")!;
1437
+
1438
+ await aliasCommand("no-ui-renamed", harness.ctx);
1439
+ const renamed = await waitForSessionByName(planner, "no-ui-renamed");
1440
+ assert.equal(renamed.id, initial.id);
1441
+ assert.equal(harness.pi.getSessionName(), "no-ui-renamed");
1442
+ assert.deepEqual(output, ["Session alias set: no-ui-renamed"]);
1443
+
1444
+ output.length = 0;
1445
+ await aliasCommand("", harness.ctx);
1446
+ assert.deepEqual(output, ["Session alias: no-ui-renamed"]);
1447
+
1448
+ output.length = 0;
1449
+ await aliasCommand("menu", harness.ctx);
1450
+ assert.deepEqual(output, ["The alias menu requires an interactive UI; use /alias <name>."]);
1451
+ assert.equal(harness.pi.getSessionName(), "no-ui-renamed");
1452
+ });
1453
+ } finally {
1454
+ console.error = previousConsoleError;
1455
+ await harness.emitLifecycle("session_shutdown");
1456
+ await cleanup();
1457
+ }
1458
+ });
1459
+
1341
1460
  test("intercom tool shows unique ID prefixes when names collide", { concurrency: false }, async () => {
1342
1461
  const { cleanup } = await setupClients();
1343
1462
  const { default: piIntercomExtension } = await import("./index.ts");
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-intercom",
3
- "version": "0.12.1",
3
+ "version": "0.13.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -90,7 +90,7 @@ test("openProjectPane opens a Herdr pane and runs pi in the project", async () =
90
90
  assert.equal(launched.paneId, "pane-1");
91
91
  assert.equal(launched.herdrVersion, "herdr 0.7.5");
92
92
  assert.deepEqual(calls[1], ["pane", "split", "--current", "--direction", "right", "--cwd", launched.projectRoot]);
93
- assert.deepEqual(calls[2], ["pane", "run", "pane-1", "'pi'"]);
93
+ assert.deepEqual(calls[2], ["pane", "run", "pane-1", "selesai"]);
94
94
  } finally {
95
95
  rmSync(root, { recursive: true, force: true });
96
96
  }
@@ -171,11 +171,6 @@ function extractPaneId(value: unknown): string | undefined {
171
171
  return undefined;
172
172
  }
173
173
 
174
- function shellQuote(value: string): string {
175
- if (process.platform === "win32") return `"${value.replaceAll('"', '\\"')}"`;
176
- return `'${value.replaceAll("'", "'\\''")}'`;
177
- }
178
-
179
174
  function resolveProjectRoot(cwd: string): string {
180
175
  const resolved = resolve(cwd);
181
176
  const stat = statSync(resolved);
@@ -242,7 +237,7 @@ export async function openProjectPane(input: {
242
237
  const paneId = extractPaneId(split.data);
243
238
  if (!paneId) throw new Error("Herdr project pane error (PANE_GONE): pane split returned no pane id.");
244
239
 
245
- const command = shellQuote(process.env.SELESAI_INTERCOM_BINARY?.trim() || process.env.SELESAI_BIN?.trim() || "selesai");
240
+ const command = process.env.SELESAI_INTERCOM_BINARY?.trim() || process.env.SELESAI_BIN?.trim() || "selesai";
246
241
  const started = await client.run(["pane", "run", paneId, command], { timeoutMs: 15_000, signal: input.signal });
247
242
  if (started.ok === false) {
248
243
  await client.run(["pane", "close", paneId], { timeoutMs: 5_000 });