@ilya-lesikov/pi-pi 0.1.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 (271) hide show
  1. package/3p/pi-ask-user/index.ts +1835 -0
  2. package/3p/pi-ask-user/package.json +50 -0
  3. package/3p/pi-ask-user/single-select-layout.ts +203 -0
  4. package/3p/pi-lsp/extensions/lsp/client.ts +542 -0
  5. package/3p/pi-lsp/extensions/lsp/config.ts +135 -0
  6. package/3p/pi-lsp/extensions/lsp/effects/command.ts +42 -0
  7. package/3p/pi-lsp/extensions/lsp/effects/filesystem.ts +50 -0
  8. package/3p/pi-lsp/extensions/lsp/effects/runtime.ts +21 -0
  9. package/3p/pi-lsp/extensions/lsp/errors.ts +113 -0
  10. package/3p/pi-lsp/extensions/lsp/formatting.ts +315 -0
  11. package/3p/pi-lsp/extensions/lsp/index.ts +231 -0
  12. package/3p/pi-lsp/extensions/lsp/protocol.ts +209 -0
  13. package/3p/pi-lsp/extensions/lsp/retry.ts +39 -0
  14. package/3p/pi-lsp/extensions/lsp/tools/programs.ts +293 -0
  15. package/3p/pi-lsp/extensions/lsp/tools.ts +89 -0
  16. package/3p/pi-lsp/extensions/lsp/types.ts +243 -0
  17. package/3p/pi-lsp/package.json +54 -0
  18. package/3p/pi-plannotator/AGENTS.md +583 -0
  19. package/3p/pi-plannotator/apps/pi-extension/README.md +228 -0
  20. package/3p/pi-plannotator/apps/pi-extension/assistant-message.ts +128 -0
  21. package/3p/pi-plannotator/apps/pi-extension/config.test.ts +166 -0
  22. package/3p/pi-plannotator/apps/pi-extension/config.ts +318 -0
  23. package/3p/pi-plannotator/apps/pi-extension/current-pi-session.ts +147 -0
  24. package/3p/pi-plannotator/apps/pi-extension/index.ts +1279 -0
  25. package/3p/pi-plannotator/apps/pi-extension/package.json +56 -0
  26. package/3p/pi-plannotator/apps/pi-extension/plannotator-browser.test.ts +13 -0
  27. package/3p/pi-plannotator/apps/pi-extension/plannotator-browser.ts +616 -0
  28. package/3p/pi-plannotator/apps/pi-extension/plannotator-events.ts +342 -0
  29. package/3p/pi-plannotator/apps/pi-extension/plannotator.json +12 -0
  30. package/3p/pi-plannotator/apps/pi-extension/server/agent-jobs.ts +515 -0
  31. package/3p/pi-plannotator/apps/pi-extension/server/ai-runtime.ts +169 -0
  32. package/3p/pi-plannotator/apps/pi-extension/server/annotations.ts +85 -0
  33. package/3p/pi-plannotator/apps/pi-extension/server/external-annotations.ts +189 -0
  34. package/3p/pi-plannotator/apps/pi-extension/server/handlers.ts +210 -0
  35. package/3p/pi-plannotator/apps/pi-extension/server/helpers.ts +78 -0
  36. package/3p/pi-plannotator/apps/pi-extension/server/ide.ts +46 -0
  37. package/3p/pi-plannotator/apps/pi-extension/server/integrations.ts +195 -0
  38. package/3p/pi-plannotator/apps/pi-extension/server/network.test.ts +158 -0
  39. package/3p/pi-plannotator/apps/pi-extension/server/network.ts +268 -0
  40. package/3p/pi-plannotator/apps/pi-extension/server/pr.ts +126 -0
  41. package/3p/pi-plannotator/apps/pi-extension/server/project.ts +64 -0
  42. package/3p/pi-plannotator/apps/pi-extension/server/reference.ts +362 -0
  43. package/3p/pi-plannotator/apps/pi-extension/server/serverAnnotate.ts +199 -0
  44. package/3p/pi-plannotator/apps/pi-extension/server/serverPlan.ts +505 -0
  45. package/3p/pi-plannotator/apps/pi-extension/server/serverReview.ts +1229 -0
  46. package/3p/pi-plannotator/apps/pi-extension/server/vcs.ts +121 -0
  47. package/3p/pi-plannotator/apps/pi-extension/server.test.ts +966 -0
  48. package/3p/pi-plannotator/apps/pi-extension/server.ts +44 -0
  49. package/3p/pi-plannotator/apps/pi-extension/tool-scope.test.ts +88 -0
  50. package/3p/pi-plannotator/apps/pi-extension/tool-scope.ts +39 -0
  51. package/3p/pi-plannotator/apps/pi-extension/tsconfig.json +16 -0
  52. package/3p/pi-plannotator/apps/pi-extension/vendor.sh +48 -0
  53. package/3p/pi-plannotator/package.json +53 -0
  54. package/3p/pi-plannotator/packages/ai/ai.test.ts +1407 -0
  55. package/3p/pi-plannotator/packages/ai/base-session.ts +94 -0
  56. package/3p/pi-plannotator/packages/ai/context.ts +250 -0
  57. package/3p/pi-plannotator/packages/ai/endpoints.ts +326 -0
  58. package/3p/pi-plannotator/packages/ai/index.ts +105 -0
  59. package/3p/pi-plannotator/packages/ai/package.json +21 -0
  60. package/3p/pi-plannotator/packages/ai/provider.ts +103 -0
  61. package/3p/pi-plannotator/packages/ai/providers/claude-agent-sdk.ts +447 -0
  62. package/3p/pi-plannotator/packages/ai/providers/codex-sdk.ts +430 -0
  63. package/3p/pi-plannotator/packages/ai/providers/command-path.ts +115 -0
  64. package/3p/pi-plannotator/packages/ai/providers/opencode-sdk.ts +546 -0
  65. package/3p/pi-plannotator/packages/ai/providers/pi-events.ts +110 -0
  66. package/3p/pi-plannotator/packages/ai/providers/pi-sdk-node.ts +425 -0
  67. package/3p/pi-plannotator/packages/ai/providers/pi-sdk.ts +469 -0
  68. package/3p/pi-plannotator/packages/ai/session-manager.ts +195 -0
  69. package/3p/pi-plannotator/packages/ai/tsconfig.json +15 -0
  70. package/3p/pi-plannotator/packages/ai/types.ts +379 -0
  71. package/3p/pi-plannotator/packages/server/agent-jobs.ts +538 -0
  72. package/3p/pi-plannotator/packages/server/agent-review-message.test.ts +135 -0
  73. package/3p/pi-plannotator/packages/server/agent-review-message.ts +243 -0
  74. package/3p/pi-plannotator/packages/server/ai-runtime.ts +108 -0
  75. package/3p/pi-plannotator/packages/server/annotate.ts +401 -0
  76. package/3p/pi-plannotator/packages/server/browser.test.ts +87 -0
  77. package/3p/pi-plannotator/packages/server/browser.ts +245 -0
  78. package/3p/pi-plannotator/packages/server/claude-review.ts +352 -0
  79. package/3p/pi-plannotator/packages/server/code-nav.ts +73 -0
  80. package/3p/pi-plannotator/packages/server/codex-review-schema.json +41 -0
  81. package/3p/pi-plannotator/packages/server/codex-review.ts +330 -0
  82. package/3p/pi-plannotator/packages/server/config.ts +8 -0
  83. package/3p/pi-plannotator/packages/server/draft.ts +1 -0
  84. package/3p/pi-plannotator/packages/server/editor-annotations.ts +76 -0
  85. package/3p/pi-plannotator/packages/server/external-annotations.test.ts +18 -0
  86. package/3p/pi-plannotator/packages/server/external-annotations.ts +207 -0
  87. package/3p/pi-plannotator/packages/server/git.ts +141 -0
  88. package/3p/pi-plannotator/packages/server/goal-setup.test.ts +55 -0
  89. package/3p/pi-plannotator/packages/server/goal-setup.ts +248 -0
  90. package/3p/pi-plannotator/packages/server/ide.ts +43 -0
  91. package/3p/pi-plannotator/packages/server/image.test.ts +63 -0
  92. package/3p/pi-plannotator/packages/server/image.ts +66 -0
  93. package/3p/pi-plannotator/packages/server/index.ts +648 -0
  94. package/3p/pi-plannotator/packages/server/integrations.test.ts +172 -0
  95. package/3p/pi-plannotator/packages/server/integrations.ts +214 -0
  96. package/3p/pi-plannotator/packages/server/jj.test.ts +69 -0
  97. package/3p/pi-plannotator/packages/server/jj.ts +86 -0
  98. package/3p/pi-plannotator/packages/server/p4.ts +417 -0
  99. package/3p/pi-plannotator/packages/server/package.json +40 -0
  100. package/3p/pi-plannotator/packages/server/path-utils.ts +18 -0
  101. package/3p/pi-plannotator/packages/server/pr.ts +146 -0
  102. package/3p/pi-plannotator/packages/server/project.test.ts +115 -0
  103. package/3p/pi-plannotator/packages/server/project.ts +45 -0
  104. package/3p/pi-plannotator/packages/server/reference-handlers.ts +404 -0
  105. package/3p/pi-plannotator/packages/server/remote.test.ts +150 -0
  106. package/3p/pi-plannotator/packages/server/remote.ts +74 -0
  107. package/3p/pi-plannotator/packages/server/repo.ts +80 -0
  108. package/3p/pi-plannotator/packages/server/resolve-file.test.ts +310 -0
  109. package/3p/pi-plannotator/packages/server/review-workspace.test.ts +1032 -0
  110. package/3p/pi-plannotator/packages/server/review-workspace.ts +48 -0
  111. package/3p/pi-plannotator/packages/server/review.ts +1318 -0
  112. package/3p/pi-plannotator/packages/server/sessions.ts +111 -0
  113. package/3p/pi-plannotator/packages/server/share-url.ts +53 -0
  114. package/3p/pi-plannotator/packages/server/shared-handlers.test.ts +43 -0
  115. package/3p/pi-plannotator/packages/server/shared-handlers.ts +177 -0
  116. package/3p/pi-plannotator/packages/server/storage.test.ts +176 -0
  117. package/3p/pi-plannotator/packages/server/storage.ts +17 -0
  118. package/3p/pi-plannotator/packages/server/tour/tour-review.test.ts +146 -0
  119. package/3p/pi-plannotator/packages/server/tour/tour-review.ts +604 -0
  120. package/3p/pi-plannotator/packages/server/tsconfig.json +15 -0
  121. package/3p/pi-plannotator/packages/server/vcs.test.ts +48 -0
  122. package/3p/pi-plannotator/packages/server/vcs.ts +80 -0
  123. package/3p/pi-plannotator/packages/shared/agent-jobs.ts +132 -0
  124. package/3p/pi-plannotator/packages/shared/agents.ts +53 -0
  125. package/3p/pi-plannotator/packages/shared/annotate-args.test.ts +386 -0
  126. package/3p/pi-plannotator/packages/shared/annotate-args.ts +107 -0
  127. package/3p/pi-plannotator/packages/shared/at-reference.test.ts +99 -0
  128. package/3p/pi-plannotator/packages/shared/at-reference.ts +52 -0
  129. package/3p/pi-plannotator/packages/shared/checklist.ts +52 -0
  130. package/3p/pi-plannotator/packages/shared/code-file.test.ts +112 -0
  131. package/3p/pi-plannotator/packages/shared/code-file.ts +41 -0
  132. package/3p/pi-plannotator/packages/shared/code-nav.test.ts +515 -0
  133. package/3p/pi-plannotator/packages/shared/code-nav.ts +436 -0
  134. package/3p/pi-plannotator/packages/shared/compress.ts +51 -0
  135. package/3p/pi-plannotator/packages/shared/config.ts +262 -0
  136. package/3p/pi-plannotator/packages/shared/crypto.test.ts +172 -0
  137. package/3p/pi-plannotator/packages/shared/crypto.ts +97 -0
  138. package/3p/pi-plannotator/packages/shared/data-dir.ts +42 -0
  139. package/3p/pi-plannotator/packages/shared/diff-paths.test.ts +30 -0
  140. package/3p/pi-plannotator/packages/shared/diff-paths.ts +137 -0
  141. package/3p/pi-plannotator/packages/shared/draft.ts +64 -0
  142. package/3p/pi-plannotator/packages/shared/external-annotation.ts +397 -0
  143. package/3p/pi-plannotator/packages/shared/extract-code-paths.test.ts +59 -0
  144. package/3p/pi-plannotator/packages/shared/extract-code-paths.ts +66 -0
  145. package/3p/pi-plannotator/packages/shared/favicon.ts +5 -0
  146. package/3p/pi-plannotator/packages/shared/feedback-templates.test.ts +65 -0
  147. package/3p/pi-plannotator/packages/shared/feedback-templates.ts +29 -0
  148. package/3p/pi-plannotator/packages/shared/goal-setup.test.ts +231 -0
  149. package/3p/pi-plannotator/packages/shared/goal-setup.ts +336 -0
  150. package/3p/pi-plannotator/packages/shared/html-to-markdown.test.ts +62 -0
  151. package/3p/pi-plannotator/packages/shared/html-to-markdown.ts +32 -0
  152. package/3p/pi-plannotator/packages/shared/improvement-hooks.test.ts +135 -0
  153. package/3p/pi-plannotator/packages/shared/improvement-hooks.ts +115 -0
  154. package/3p/pi-plannotator/packages/shared/integrations-common.ts +243 -0
  155. package/3p/pi-plannotator/packages/shared/jj-core.test.ts +236 -0
  156. package/3p/pi-plannotator/packages/shared/jj-core.ts +433 -0
  157. package/3p/pi-plannotator/packages/shared/package.json +55 -0
  158. package/3p/pi-plannotator/packages/shared/pfm-reminder.test.ts +88 -0
  159. package/3p/pi-plannotator/packages/shared/pfm-reminder.ts +80 -0
  160. package/3p/pi-plannotator/packages/shared/pr-github.ts +661 -0
  161. package/3p/pi-plannotator/packages/shared/pr-gitlab.test.ts +202 -0
  162. package/3p/pi-plannotator/packages/shared/pr-gitlab.ts +620 -0
  163. package/3p/pi-plannotator/packages/shared/pr-provider.test.ts +266 -0
  164. package/3p/pi-plannotator/packages/shared/pr-provider.ts +123 -0
  165. package/3p/pi-plannotator/packages/shared/pr-stack.test.ts +104 -0
  166. package/3p/pi-plannotator/packages/shared/pr-stack.ts +194 -0
  167. package/3p/pi-plannotator/packages/shared/pr-types.ts +326 -0
  168. package/3p/pi-plannotator/packages/shared/project.ts +71 -0
  169. package/3p/pi-plannotator/packages/shared/prompts-integration.test.ts +421 -0
  170. package/3p/pi-plannotator/packages/shared/prompts.test.ts +504 -0
  171. package/3p/pi-plannotator/packages/shared/prompts.ts +247 -0
  172. package/3p/pi-plannotator/packages/shared/reference-common.ts +87 -0
  173. package/3p/pi-plannotator/packages/shared/repo.ts +71 -0
  174. package/3p/pi-plannotator/packages/shared/resolve-file.test.ts +113 -0
  175. package/3p/pi-plannotator/packages/shared/resolve-file.ts +509 -0
  176. package/3p/pi-plannotator/packages/shared/review-args.test.ts +64 -0
  177. package/3p/pi-plannotator/packages/shared/review-args.ts +85 -0
  178. package/3p/pi-plannotator/packages/shared/review-core.test.ts +286 -0
  179. package/3p/pi-plannotator/packages/shared/review-core.ts +895 -0
  180. package/3p/pi-plannotator/packages/shared/review-workspace-node.ts +230 -0
  181. package/3p/pi-plannotator/packages/shared/review-workspace.ts +436 -0
  182. package/3p/pi-plannotator/packages/shared/semantic-diff-types.ts +76 -0
  183. package/3p/pi-plannotator/packages/shared/semantic-diff.test.ts +322 -0
  184. package/3p/pi-plannotator/packages/shared/semantic-diff.ts +520 -0
  185. package/3p/pi-plannotator/packages/shared/storage.ts +378 -0
  186. package/3p/pi-plannotator/packages/shared/tour.ts +61 -0
  187. package/3p/pi-plannotator/packages/shared/tsconfig.json +15 -0
  188. package/3p/pi-plannotator/packages/shared/types.ts +29 -0
  189. package/3p/pi-plannotator/packages/shared/url-to-markdown.test.ts +177 -0
  190. package/3p/pi-plannotator/packages/shared/url-to-markdown.ts +351 -0
  191. package/3p/pi-plannotator/packages/shared/vcs-core.test.ts +332 -0
  192. package/3p/pi-plannotator/packages/shared/vcs-core.ts +482 -0
  193. package/3p/pi-plannotator/packages/shared/worktree-pool.test.ts +162 -0
  194. package/3p/pi-plannotator/packages/shared/worktree-pool.ts +103 -0
  195. package/3p/pi-plannotator/packages/shared/worktree.ts +119 -0
  196. package/3p/pi-subagents/package.json +50 -0
  197. package/3p/pi-subagents/src/agent-manager.ts +413 -0
  198. package/3p/pi-subagents/src/agent-runner.ts +502 -0
  199. package/3p/pi-subagents/src/agent-types.ts +248 -0
  200. package/3p/pi-subagents/src/context.ts +58 -0
  201. package/3p/pi-subagents/src/cross-extension-rpc.ts +135 -0
  202. package/3p/pi-subagents/src/custom-agents.ts +137 -0
  203. package/3p/pi-subagents/src/default-agents.ts +144 -0
  204. package/3p/pi-subagents/src/env.ts +33 -0
  205. package/3p/pi-subagents/src/group-join.ts +141 -0
  206. package/3p/pi-subagents/src/index.ts +1811 -0
  207. package/3p/pi-subagents/src/invocation-config.ts +40 -0
  208. package/3p/pi-subagents/src/memory.ts +165 -0
  209. package/3p/pi-subagents/src/model-resolver.ts +81 -0
  210. package/3p/pi-subagents/src/output-file.ts +77 -0
  211. package/3p/pi-subagents/src/prompts.ts +85 -0
  212. package/3p/pi-subagents/src/skill-loader.ts +79 -0
  213. package/3p/pi-subagents/src/types.ts +111 -0
  214. package/3p/pi-subagents/src/ui/agent-widget.ts +496 -0
  215. package/3p/pi-subagents/src/ui/conversation-viewer.ts +250 -0
  216. package/3p/pi-subagents/src/worktree.ts +162 -0
  217. package/3p/pi-tasks/package.json +52 -0
  218. package/3p/pi-tasks/src/auto-clear.ts +91 -0
  219. package/3p/pi-tasks/src/index.ts +1150 -0
  220. package/3p/pi-tasks/src/process-tracker.ts +140 -0
  221. package/3p/pi-tasks/src/reminder-cadence.ts +90 -0
  222. package/3p/pi-tasks/src/task-store.ts +324 -0
  223. package/3p/pi-tasks/src/tasks-config.ts +27 -0
  224. package/3p/pi-tasks/src/types.ts +40 -0
  225. package/3p/pi-tasks/src/ui/settings-menu.ts +152 -0
  226. package/3p/pi-tasks/src/ui/task-widget.ts +296 -0
  227. package/AGENTS.md +28 -0
  228. package/LICENSE +201 -0
  229. package/extensions/orchestrator/agents/brainstorm-reviewer.ts +77 -0
  230. package/extensions/orchestrator/agents/code-reviewer.ts +89 -0
  231. package/extensions/orchestrator/agents/explore.ts +33 -0
  232. package/extensions/orchestrator/agents/librarian.ts +43 -0
  233. package/extensions/orchestrator/agents/plan-reviewer.ts +75 -0
  234. package/extensions/orchestrator/agents/planner.ts +61 -0
  235. package/extensions/orchestrator/agents/registry.ts +156 -0
  236. package/extensions/orchestrator/agents/task.ts +50 -0
  237. package/extensions/orchestrator/agents/tool-routing.ts +84 -0
  238. package/extensions/orchestrator/ast-search.ts +85 -0
  239. package/extensions/orchestrator/cbm.ts +330 -0
  240. package/extensions/orchestrator/command-handlers.test.ts +163 -0
  241. package/extensions/orchestrator/command-handlers.ts +116 -0
  242. package/extensions/orchestrator/commands.test.ts +81 -0
  243. package/extensions/orchestrator/commands.ts +75 -0
  244. package/extensions/orchestrator/config.test.ts +221 -0
  245. package/extensions/orchestrator/config.ts +230 -0
  246. package/extensions/orchestrator/context.test.ts +293 -0
  247. package/extensions/orchestrator/context.ts +206 -0
  248. package/extensions/orchestrator/event-handlers.test.ts +190 -0
  249. package/extensions/orchestrator/event-handlers.ts +1416 -0
  250. package/extensions/orchestrator/exa.ts +104 -0
  251. package/extensions/orchestrator/flant-infra.ts +486 -0
  252. package/extensions/orchestrator/index.ts +80 -0
  253. package/extensions/orchestrator/integration.test.ts +1214 -0
  254. package/extensions/orchestrator/orchestrator.test.ts +252 -0
  255. package/extensions/orchestrator/orchestrator.ts +538 -0
  256. package/extensions/orchestrator/phases/brainstorm.test.ts +15 -0
  257. package/extensions/orchestrator/phases/brainstorm.ts +273 -0
  258. package/extensions/orchestrator/phases/implementation.ts +40 -0
  259. package/extensions/orchestrator/phases/machine.test.ts +293 -0
  260. package/extensions/orchestrator/phases/machine.ts +209 -0
  261. package/extensions/orchestrator/phases/planning.ts +255 -0
  262. package/extensions/orchestrator/phases/review.ts +193 -0
  263. package/extensions/orchestrator/plannotator.ts +56 -0
  264. package/extensions/orchestrator/pp-menu.ts +866 -0
  265. package/extensions/orchestrator/state.test.ts +343 -0
  266. package/extensions/orchestrator/state.ts +237 -0
  267. package/extensions/orchestrator/validate-artifacts.test.ts +88 -0
  268. package/extensions/orchestrator/validate-artifacts.ts +272 -0
  269. package/extensions/orchestrator/vendor.d.ts +26 -0
  270. package/package.json +73 -0
  271. package/scripts/postinstall.sh +18 -0
@@ -0,0 +1,252 @@
1
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "fs";
2
+ import { tmpdir } from "os";
3
+ import { join } from "path";
4
+ import { afterEach, describe, expect, it, vi } from "vitest";
5
+ import { Orchestrator, deepReviewConfig, ensureGitignore, type ActiveTask } from "./orchestrator.js";
6
+
7
+ const tempDirs: string[] = [];
8
+
9
+ function makeTempDir(): string {
10
+ const dir = mkdtempSync(join(tmpdir(), "pi-pi-orchestrator-test-"));
11
+ tempDirs.push(dir);
12
+ return dir;
13
+ }
14
+
15
+ function makePi(overrides: Record<string, unknown> = {}): any {
16
+ return {
17
+ getAllTools: vi.fn().mockReturnValue([]),
18
+ events: {
19
+ emit: vi.fn(),
20
+ on: vi.fn(),
21
+ },
22
+ sendMessage: vi.fn(),
23
+ setModel: vi.fn(),
24
+ setThinkingLevel: vi.fn(),
25
+ setSessionName: vi.fn(),
26
+ sendUserMessage: vi.fn(),
27
+ ...overrides,
28
+ };
29
+ }
30
+
31
+ function makeActiveTask(release: (() => Promise<void>) | null): ActiveTask {
32
+ return {
33
+ dir: "/tmp/task",
34
+ type: "implement",
35
+ state: {
36
+ phase: "brainstorm",
37
+ step: "llm_work",
38
+ reviewCycle: null,
39
+ reviewPass: 0,
40
+ from: null,
41
+ description: "Task",
42
+ startedAt: new Date().toISOString(),
43
+ },
44
+ release,
45
+ taskId: "123",
46
+ modifiedFiles: new Set(),
47
+ reviewPass: 0,
48
+ description: "Task",
49
+ };
50
+ }
51
+
52
+ afterEach(() => {
53
+ vi.restoreAllMocks();
54
+ for (const dir of tempDirs.splice(0)) {
55
+ rmSync(dir, { recursive: true, force: true });
56
+ }
57
+ });
58
+
59
+ describe("Orchestrator.truncateResult", () => {
60
+ it("returns empty string for empty input", () => {
61
+ const orchestrator = new Orchestrator(makePi());
62
+ expect(orchestrator.truncateResult(" \n\t ")).toBe("");
63
+ });
64
+
65
+ it("returns trimmed short input unchanged", () => {
66
+ const orchestrator = new Orchestrator(makePi());
67
+ expect(orchestrator.truncateResult("\nhello\nworld\n")).toBe("hello\nworld");
68
+ });
69
+
70
+ it("truncates output longer than 20 lines", () => {
71
+ const orchestrator = new Orchestrator(makePi());
72
+ const input = Array.from({ length: 21 }, (_, i) => `line-${i + 1}`).join("\n");
73
+
74
+ const expected = Array.from({ length: 20 }, (_, i) => `line-${i + 1}`).join("\n") + "\n…(truncated)";
75
+ expect(orchestrator.truncateResult(input)).toBe(expected);
76
+ });
77
+
78
+ it("truncates output longer than 2000 chars", () => {
79
+ const orchestrator = new Orchestrator(makePi());
80
+ const input = "x".repeat(2050);
81
+ const result = orchestrator.truncateResult(input);
82
+
83
+ expect(result).toBe("x".repeat(2000) + "\n…(truncated)");
84
+ });
85
+ });
86
+
87
+ describe("Orchestrator.taskIdFromDir", () => {
88
+ it("extracts numeric prefix from directory basename", () => {
89
+ const orchestrator = new Orchestrator(makePi());
90
+ expect(orchestrator.taskIdFromDir("/tmp/.pp/state/implement/123456789012_add-feature")).toBe("123456789012");
91
+ });
92
+ });
93
+
94
+ describe("deepReviewConfig", () => {
95
+ it("upgrades reviewer thinking levels", () => {
96
+ const config = {
97
+ mainModel: {
98
+ implement: { model: "a/impl", thinking: "high" },
99
+ debug: { model: "a/debug", thinking: "high" },
100
+ brainstorm: { model: "a/brain", thinking: "high" },
101
+ },
102
+ planners: {},
103
+ planReviewers: {
104
+ low: { enabled: true, model: "x/p1", thinking: "low" },
105
+ medium: { enabled: true, model: "x/p2", thinking: "medium" },
106
+ high: { enabled: true, model: "x/p3", thinking: "high" },
107
+ other: { enabled: true, model: "x/p4", thinking: "off" },
108
+ },
109
+ brainstormReviewers: {
110
+ low: { enabled: true, model: "x/b1", thinking: "low" },
111
+ medium: { enabled: true, model: "x/b2", thinking: "medium" },
112
+ high: { enabled: true, model: "x/b3", thinking: "high" },
113
+ other: { enabled: true, model: "x/b4", thinking: "off" },
114
+ },
115
+ codeReviewers: {
116
+ low: { enabled: true, model: "x/1", thinking: "low" },
117
+ medium: { enabled: true, model: "x/2", thinking: "medium" },
118
+ high: { enabled: true, model: "x/3", thinking: "high" },
119
+ other: { enabled: true, model: "x/4", thinking: "off" },
120
+ },
121
+ agents: {
122
+ explore: { model: "x/e", thinking: "low" },
123
+ librarian: { model: "x/l", thinking: "medium" },
124
+ task: { model: "x/t", thinking: "medium" },
125
+ },
126
+ commands: { afterEdit: [], afterImplement: [] },
127
+ timeouts: {
128
+ afterEdit: 1,
129
+ afterImplement: 1,
130
+ agentSpawn: 1,
131
+ agentReadyPing: 1,
132
+ lockStale: 1,
133
+ lockUpdate: 1,
134
+ },
135
+ autoCommit: true,
136
+ };
137
+
138
+ const upgraded = deepReviewConfig(config as any);
139
+
140
+ expect(upgraded.codeReviewers.low.thinking).toBe("medium");
141
+ expect(upgraded.codeReviewers.medium.thinking).toBe("high");
142
+ expect(upgraded.codeReviewers.high.thinking).toBe("xhigh");
143
+ expect(upgraded.codeReviewers.other.thinking).toBe("high");
144
+ expect(upgraded.brainstormReviewers.low.thinking).toBe("medium");
145
+ expect(upgraded.brainstormReviewers.medium.thinking).toBe("high");
146
+ expect(upgraded.brainstormReviewers.high.thinking).toBe("xhigh");
147
+ expect(upgraded.brainstormReviewers.other.thinking).toBe("high");
148
+ expect(upgraded.planReviewers.low.thinking).toBe("medium");
149
+ expect(upgraded.planReviewers.medium.thinking).toBe("high");
150
+ expect(upgraded.planReviewers.high.thinking).toBe("xhigh");
151
+ expect(upgraded.planReviewers.other.thinking).toBe("high");
152
+ });
153
+ });
154
+
155
+ describe("ensureGitignore", () => {
156
+ it("creates .pp/.gitignore with required entries", () => {
157
+ const cwd = makeTempDir();
158
+
159
+ ensureGitignore(cwd);
160
+
161
+ const gitignorePath = join(cwd, ".pp", ".gitignore");
162
+ expect(existsSync(gitignorePath)).toBe(true);
163
+ expect(readFileSync(gitignorePath, "utf-8")).toBe("state/\nconfig.json\n");
164
+ });
165
+
166
+ it("adds missing entries and does not duplicate existing ones", () => {
167
+ const cwd = makeTempDir();
168
+ const gitignorePath = join(cwd, ".pp", ".gitignore");
169
+
170
+ mkdirSync(join(cwd, ".pp"), { recursive: true });
171
+ writeFileSync(gitignorePath, "state/\n", "utf-8");
172
+
173
+ ensureGitignore(cwd);
174
+ ensureGitignore(cwd);
175
+
176
+ const lines = readFileSync(gitignorePath, "utf-8").trim().split("\n");
177
+ expect(lines.filter((line) => line === "state/")).toHaveLength(1);
178
+ expect(lines.filter((line) => line === "config.json")).toHaveLength(1);
179
+ });
180
+ });
181
+
182
+ describe("Orchestrator.checkForConflictingExtensions", () => {
183
+ it("detects duplicate bundled tools", () => {
184
+ const pi = makePi({
185
+ getAllTools: vi.fn().mockReturnValue([
186
+ { name: "Agent" },
187
+ { name: "Agent" },
188
+ { name: "TaskCreate" },
189
+ { name: "TaskCreate" },
190
+ { name: "CustomTool" },
191
+ ]),
192
+ });
193
+ const orchestrator = new Orchestrator(pi);
194
+
195
+ expect(orchestrator.checkForConflictingExtensions().sort()).toEqual(["Agent", "TaskCreate"]);
196
+ });
197
+
198
+ it("returns empty array when no duplicates exist", () => {
199
+ const pi = makePi({
200
+ getAllTools: vi.fn().mockReturnValue([
201
+ { name: "Agent" },
202
+ { name: "TaskCreate" },
203
+ { name: "CustomTool" },
204
+ ]),
205
+ });
206
+ const orchestrator = new Orchestrator(pi);
207
+
208
+ expect(orchestrator.checkForConflictingExtensions()).toEqual([]);
209
+ });
210
+ });
211
+
212
+ describe("Orchestrator.abortAllSubagents", () => {
213
+ it("emits stop events for all spawned subagents and clears the set", () => {
214
+ const emit = vi.fn();
215
+ const orchestrator = new Orchestrator(makePi({ events: { emit, on: vi.fn() } }));
216
+ orchestrator.spawnedAgentIds.add("agent-1");
217
+ orchestrator.spawnedAgentIds.add("agent-2");
218
+
219
+ orchestrator.abortAllSubagents();
220
+
221
+ expect(emit).toHaveBeenCalledTimes(2);
222
+ expect(emit).toHaveBeenCalledWith(
223
+ "subagents:rpc:stop",
224
+ expect.objectContaining({ agentId: "agent-1", requestId: expect.any(String) }),
225
+ );
226
+ expect(emit).toHaveBeenCalledWith(
227
+ "subagents:rpc:stop",
228
+ expect.objectContaining({ agentId: "agent-2", requestId: expect.any(String) }),
229
+ );
230
+ expect(orchestrator.spawnedAgentIds.size).toBe(0);
231
+ });
232
+ });
233
+
234
+ describe("Orchestrator.cleanupActive", () => {
235
+ it("releases active lock and sets active to null", async () => {
236
+ const release = vi.fn().mockResolvedValue(undefined);
237
+ const orchestrator = new Orchestrator(makePi());
238
+ orchestrator.active = makeActiveTask(release);
239
+
240
+ await orchestrator.cleanupActive();
241
+
242
+ expect(release).toHaveBeenCalledTimes(1);
243
+ expect(orchestrator.active).toBeNull();
244
+ });
245
+ it("does nothing when active task is null", async () => {
246
+ const orchestrator = new Orchestrator(makePi());
247
+ orchestrator.active = null;
248
+
249
+ await expect(orchestrator.cleanupActive()).resolves.toBeUndefined();
250
+ expect(orchestrator.active).toBeNull();
251
+ });
252
+ });