pi-loop 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 (166) hide show
  1. package/agents/code-reviewer.md +82 -0
  2. package/agents/coder.md +82 -0
  3. package/agents/decomposer.md +55 -0
  4. package/agents/judge.md +90 -0
  5. package/agents/review-optimizer.md +44 -0
  6. package/dist/agents/adapter.d.ts +9 -0
  7. package/dist/agents/adapter.d.ts.map +1 -0
  8. package/dist/agents/adapter.js +41 -0
  9. package/dist/agents/adapter.js.map +1 -0
  10. package/dist/agents/factory.d.ts +7 -0
  11. package/dist/agents/factory.d.ts.map +1 -0
  12. package/dist/agents/factory.js +49 -0
  13. package/dist/agents/factory.js.map +1 -0
  14. package/dist/agents/registry.d.ts +4 -0
  15. package/dist/agents/registry.d.ts.map +1 -0
  16. package/dist/agents/registry.js +98 -0
  17. package/dist/agents/registry.js.map +1 -0
  18. package/dist/agents/types.d.ts +21 -0
  19. package/dist/agents/types.d.ts.map +1 -0
  20. package/dist/agents/types.js +39 -0
  21. package/dist/agents/types.js.map +1 -0
  22. package/dist/cli/args.d.ts +38 -0
  23. package/dist/cli/args.d.ts.map +1 -0
  24. package/dist/cli/args.js +160 -0
  25. package/dist/cli/args.js.map +1 -0
  26. package/dist/cli/commands.d.ts +29 -0
  27. package/dist/cli/commands.d.ts.map +1 -0
  28. package/dist/cli/commands.js +362 -0
  29. package/dist/cli/commands.js.map +1 -0
  30. package/dist/cli/output.d.ts +33 -0
  31. package/dist/cli/output.d.ts.map +1 -0
  32. package/dist/cli/output.js +99 -0
  33. package/dist/cli/output.js.map +1 -0
  34. package/dist/config/defaults.d.ts +3 -0
  35. package/dist/config/defaults.d.ts.map +1 -0
  36. package/dist/config/defaults.js +31 -0
  37. package/dist/config/defaults.js.map +1 -0
  38. package/dist/config/loader.d.ts +11 -0
  39. package/dist/config/loader.d.ts.map +1 -0
  40. package/dist/config/loader.js +70 -0
  41. package/dist/config/loader.js.map +1 -0
  42. package/dist/config/types.d.ts +41 -0
  43. package/dist/config/types.d.ts.map +1 -0
  44. package/dist/config/types.js +5 -0
  45. package/dist/config/types.js.map +1 -0
  46. package/dist/core/checkpoint.d.ts +18 -0
  47. package/dist/core/checkpoint.d.ts.map +1 -0
  48. package/dist/core/checkpoint.js +32 -0
  49. package/dist/core/checkpoint.js.map +1 -0
  50. package/dist/core/judge.d.ts +11 -0
  51. package/dist/core/judge.d.ts.map +1 -0
  52. package/dist/core/judge.js +91 -0
  53. package/dist/core/judge.js.map +1 -0
  54. package/dist/core/learnings.d.ts +4 -0
  55. package/dist/core/learnings.d.ts.map +1 -0
  56. package/dist/core/learnings.js +33 -0
  57. package/dist/core/learnings.js.map +1 -0
  58. package/dist/core/orchestrator.d.ts +64 -0
  59. package/dist/core/orchestrator.d.ts.map +1 -0
  60. package/dist/core/orchestrator.js +499 -0
  61. package/dist/core/orchestrator.js.map +1 -0
  62. package/dist/core/plan.d.ts +7 -0
  63. package/dist/core/plan.d.ts.map +1 -0
  64. package/dist/core/plan.js +15 -0
  65. package/dist/core/plan.js.map +1 -0
  66. package/dist/core/readiness-policy.d.ts +11 -0
  67. package/dist/core/readiness-policy.d.ts.map +1 -0
  68. package/dist/core/readiness-policy.js +24 -0
  69. package/dist/core/readiness-policy.js.map +1 -0
  70. package/dist/core/scheduling-policy.d.ts +9 -0
  71. package/dist/core/scheduling-policy.d.ts.map +1 -0
  72. package/dist/core/scheduling-policy.js +56 -0
  73. package/dist/core/scheduling-policy.js.map +1 -0
  74. package/dist/core/task-backend.d.ts +55 -0
  75. package/dist/core/task-backend.d.ts.map +1 -0
  76. package/dist/core/task-backend.js +76 -0
  77. package/dist/core/task-backend.js.map +1 -0
  78. package/dist/core/task-state.d.ts +26 -0
  79. package/dist/core/task-state.d.ts.map +1 -0
  80. package/dist/core/task-state.js +182 -0
  81. package/dist/core/task-state.js.map +1 -0
  82. package/dist/core/wiring.d.ts +12 -0
  83. package/dist/core/wiring.d.ts.map +1 -0
  84. package/dist/core/wiring.js +131 -0
  85. package/dist/core/wiring.js.map +1 -0
  86. package/dist/git/conflict.d.ts +6 -0
  87. package/dist/git/conflict.d.ts.map +1 -0
  88. package/dist/git/conflict.js +25 -0
  89. package/dist/git/conflict.js.map +1 -0
  90. package/dist/git/repo.d.ts +13 -0
  91. package/dist/git/repo.d.ts.map +1 -0
  92. package/dist/git/repo.js +74 -0
  93. package/dist/git/repo.js.map +1 -0
  94. package/dist/git/same-branch.d.ts +9 -0
  95. package/dist/git/same-branch.d.ts.map +1 -0
  96. package/dist/git/same-branch.js +55 -0
  97. package/dist/git/same-branch.js.map +1 -0
  98. package/dist/git/worktree.d.ts +14 -0
  99. package/dist/git/worktree.d.ts.map +1 -0
  100. package/dist/git/worktree.js +78 -0
  101. package/dist/git/worktree.js.map +1 -0
  102. package/dist/index.d.ts +6 -0
  103. package/dist/index.d.ts.map +1 -0
  104. package/dist/index.js +47 -0
  105. package/dist/index.js.map +1 -0
  106. package/dist/integrations/linear/backend.d.ts +38 -0
  107. package/dist/integrations/linear/backend.d.ts.map +1 -0
  108. package/dist/integrations/linear/backend.js +374 -0
  109. package/dist/integrations/linear/backend.js.map +1 -0
  110. package/dist/integrations/linear/client.d.ts +19 -0
  111. package/dist/integrations/linear/client.d.ts.map +1 -0
  112. package/dist/integrations/linear/client.js +86 -0
  113. package/dist/integrations/linear/client.js.map +1 -0
  114. package/dist/integrations/linear/comment-templates.d.ts +14 -0
  115. package/dist/integrations/linear/comment-templates.d.ts.map +1 -0
  116. package/dist/integrations/linear/comment-templates.js +50 -0
  117. package/dist/integrations/linear/comment-templates.js.map +1 -0
  118. package/dist/integrations/linear/contract.d.ts +15 -0
  119. package/dist/integrations/linear/contract.d.ts.map +1 -0
  120. package/dist/integrations/linear/contract.js +86 -0
  121. package/dist/integrations/linear/contract.js.map +1 -0
  122. package/dist/integrations/linear/types.d.ts +39 -0
  123. package/dist/integrations/linear/types.d.ts.map +1 -0
  124. package/dist/integrations/linear/types.js +2 -0
  125. package/dist/integrations/linear/types.js.map +1 -0
  126. package/dist/swarm/pool.d.ts +33 -0
  127. package/dist/swarm/pool.d.ts.map +1 -0
  128. package/dist/swarm/pool.js +182 -0
  129. package/dist/swarm/pool.js.map +1 -0
  130. package/dist/swarm/scheduler.d.ts +38 -0
  131. package/dist/swarm/scheduler.d.ts.map +1 -0
  132. package/dist/swarm/scheduler.js +191 -0
  133. package/dist/swarm/scheduler.js.map +1 -0
  134. package/dist/swarm/worker.d.ts +49 -0
  135. package/dist/swarm/worker.d.ts.map +1 -0
  136. package/dist/swarm/worker.js +180 -0
  137. package/dist/swarm/worker.js.map +1 -0
  138. package/dist/tools/bash-tool.d.ts +24 -0
  139. package/dist/tools/bash-tool.d.ts.map +1 -0
  140. package/dist/tools/bash-tool.js +177 -0
  141. package/dist/tools/bash-tool.js.map +1 -0
  142. package/dist/tools/file-tools.d.ts +3 -0
  143. package/dist/tools/file-tools.d.ts.map +1 -0
  144. package/dist/tools/file-tools.js +68 -0
  145. package/dist/tools/file-tools.js.map +1 -0
  146. package/dist/tools/git-tools.d.ts +3 -0
  147. package/dist/tools/git-tools.d.ts.map +1 -0
  148. package/dist/tools/git-tools.js +44 -0
  149. package/dist/tools/git-tools.js.map +1 -0
  150. package/dist/tools/learnings-tool.d.ts +3 -0
  151. package/dist/tools/learnings-tool.d.ts.map +1 -0
  152. package/dist/tools/learnings-tool.js +48 -0
  153. package/dist/tools/learnings-tool.js.map +1 -0
  154. package/dist/tools/plan-tool.d.ts +3 -0
  155. package/dist/tools/plan-tool.d.ts.map +1 -0
  156. package/dist/tools/plan-tool.js +24 -0
  157. package/dist/tools/plan-tool.js.map +1 -0
  158. package/dist/tools/task-tools.d.ts +3 -0
  159. package/dist/tools/task-tools.d.ts.map +1 -0
  160. package/dist/tools/task-tools.js +108 -0
  161. package/dist/tools/task-tools.js.map +1 -0
  162. package/dist/tools/test-tool.d.ts +3 -0
  163. package/dist/tools/test-tool.d.ts.map +1 -0
  164. package/dist/tools/test-tool.js +43 -0
  165. package/dist/tools/test-tool.js.map +1 -0
  166. package/package.json +47 -0
@@ -0,0 +1,86 @@
1
+ const SECTION_ORDER = ["goal", "acceptance criteria", "constraints", "test plan", "stop conditions"];
2
+ export function parseAgentContract(description) {
3
+ const content = description ?? "";
4
+ const sections = extractSections(content);
5
+ return {
6
+ goal: sections.goal.join("\n").trim(),
7
+ acceptanceCriteria: normalizeListItems(sections["acceptance criteria"]),
8
+ constraints: normalizeListItems(sections.constraints),
9
+ testPlan: normalizeListItems(sections["test plan"]),
10
+ stopConditions: normalizeListItems(sections["stop conditions"]),
11
+ };
12
+ }
13
+ export function validateAgentContract(description) {
14
+ const contract = parseAgentContract(description);
15
+ const reasons = [];
16
+ if (!contract.goal)
17
+ reasons.push("Missing Goal section");
18
+ if (contract.acceptanceCriteria.length === 0)
19
+ reasons.push("Missing Acceptance Criteria");
20
+ if (contract.constraints.length === 0)
21
+ reasons.push("Missing Constraints");
22
+ if (contract.testPlan.length === 0)
23
+ reasons.push("Missing Test Plan");
24
+ if (contract.stopConditions.length === 0)
25
+ reasons.push("Missing Stop Conditions");
26
+ if (contract.testPlan.length > 0) {
27
+ const hasCommand = contract.testPlan.some((line) => /(npm|npx|pnpm|yarn|vitest|pytest|go test|cargo test|make)/i.test(line));
28
+ if (!hasCommand) {
29
+ reasons.push("Test Plan should include runnable test commands");
30
+ }
31
+ }
32
+ const ambiguousTokens = ["tbd", "todo", "to be decided"];
33
+ const hasAmbiguousStopCondition = contract.stopConditions.some((line) => ambiguousTokens.some((token) => line.toLowerCase().includes(token)));
34
+ if (hasAmbiguousStopCondition) {
35
+ reasons.push("Stop Conditions contain ambiguous placeholder text");
36
+ }
37
+ return {
38
+ valid: reasons.length === 0,
39
+ reasons,
40
+ contract,
41
+ };
42
+ }
43
+ function extractSections(markdown) {
44
+ const sections = {
45
+ goal: [],
46
+ "acceptance criteria": [],
47
+ constraints: [],
48
+ "test plan": [],
49
+ "stop conditions": [],
50
+ };
51
+ let activeSection = null;
52
+ for (const rawLine of markdown.split("\n")) {
53
+ const normalizedHeading = normalizeHeading(rawLine);
54
+ if (isSectionHeading(normalizedHeading)) {
55
+ activeSection = normalizedHeading;
56
+ continue;
57
+ }
58
+ if (activeSection) {
59
+ sections[activeSection].push(rawLine);
60
+ }
61
+ }
62
+ return sections;
63
+ }
64
+ function normalizeHeading(line) {
65
+ return line
66
+ .trim()
67
+ .replace(/^#+\s*/, "")
68
+ .replace(/^\*\*(.+)\*\*:?\s*$/, "$1")
69
+ .replace(/:$/, "")
70
+ .trim()
71
+ .toLowerCase();
72
+ }
73
+ function isSectionHeading(value) {
74
+ return SECTION_ORDER.includes(value);
75
+ }
76
+ function normalizeListItems(lines) {
77
+ return lines
78
+ .map((line) => line.trim())
79
+ .filter(Boolean)
80
+ .map((line) => line
81
+ .replace(/^[-*]\s+/, "")
82
+ .replace(/^\d+\.\s+/, "")
83
+ .trim())
84
+ .filter(Boolean);
85
+ }
86
+ //# sourceMappingURL=contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../../../src/integrations/linear/contract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ export interface LinearIssueState {
2
+ id: string;
3
+ name: string;
4
+ type?: string;
5
+ }
6
+ export interface LinearLabel {
7
+ id: string;
8
+ name: string;
9
+ }
10
+ export interface LinearCycleRef {
11
+ id: string;
12
+ name: string;
13
+ }
14
+ export interface LinearIssue {
15
+ id: string;
16
+ identifier: string;
17
+ title: string;
18
+ description: string;
19
+ priority: number;
20
+ createdAt: string;
21
+ updatedAt: string;
22
+ state: LinearIssueState;
23
+ labels: LinearLabel[];
24
+ cycle?: LinearCycleRef;
25
+ }
26
+ export interface LinearIssueConnection {
27
+ nodes: LinearIssue[];
28
+ pageInfo: {
29
+ hasNextPage: boolean;
30
+ endCursor?: string;
31
+ };
32
+ }
33
+ export interface LinearStateConnection {
34
+ nodes: LinearIssueState[];
35
+ }
36
+ export interface LinearLabelConnection {
37
+ nodes: LinearLabel[];
38
+ }
39
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/integrations/linear/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,cAAc,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACrC,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,QAAQ,EAAE;QACT,WAAW,EAAE,OAAO,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACF;AAED,MAAM,WAAW,qBAAqB;IACrC,KAAK,EAAE,gBAAgB,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,qBAAqB;IACrC,KAAK,EAAE,WAAW,EAAE,CAAC;CACrB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/integrations/linear/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Concurrent worker pool management.
3
+ */
4
+ import type { PiLoopConfig } from "../config/types.js";
5
+ import type { Task } from "../core/task-state.js";
6
+ import type { ParallelismMode } from "./scheduler.js";
7
+ import type { WorkerDeps } from "./worker.js";
8
+ export interface BatchResult {
9
+ taskId: string;
10
+ success: boolean;
11
+ commitHash?: string;
12
+ error?: string;
13
+ attempts: number;
14
+ changedFiles: string[];
15
+ }
16
+ export interface PoolConfig {
17
+ maxConcurrency: number;
18
+ mode: ParallelismMode;
19
+ repoRoot: string;
20
+ worktreeBaseDir: string;
21
+ piLoopConfig: PiLoopConfig;
22
+ }
23
+ /**
24
+ * Runs tasks in parallel according to mode:
25
+ * - sequential: run one at a time
26
+ * - worktree: create worktree per task, run in parallel, merge back
27
+ * - same-branch: run all in same dir with pull-rebase-push cycle
28
+ *
29
+ * Manages concurrency via a semaphore pattern.
30
+ */
31
+ export declare function executeBatch(tasks: Task[], poolConfig: PoolConfig, workerFactory: (taskId: string, workDir: string) => WorkerDeps): Promise<BatchResult[]>;
32
+ export declare function buildTaskBranchName(task: Task, config: PiLoopConfig): string;
33
+ //# sourceMappingURL=pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../../src/swarm/pool.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAIlD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,MAAM,WAAW,WAAW;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,YAAY,CAAC;CAC3B;AAkCD;;;;;;;GAOG;AACH,wBAAsB,YAAY,CACjC,KAAK,EAAE,IAAI,EAAE,EACb,UAAU,EAAE,UAAU,EACtB,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,UAAU,GAC5D,OAAO,CAAC,WAAW,EAAE,CAAC,CAWxB;AAkJD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,CAY5E"}
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Concurrent worker pool management.
3
+ */
4
+ import { getCurrentBranch, gitExec } from "../git/repo.js";
5
+ import { commitAndPush, pullLatest, rebaseAndRetry } from "../git/same-branch.js";
6
+ import { createWorktree, mergeWorktree, removeWorktree } from "../git/worktree.js";
7
+ import { runWorker } from "./worker.js";
8
+ /**
9
+ * Simple semaphore for controlling concurrency.
10
+ */
11
+ class Semaphore {
12
+ max;
13
+ current = 0;
14
+ waiting = [];
15
+ constructor(max) {
16
+ this.max = max;
17
+ }
18
+ async acquire() {
19
+ if (this.current < this.max) {
20
+ this.current++;
21
+ return;
22
+ }
23
+ return new Promise((resolve) => {
24
+ this.waiting.push(resolve);
25
+ });
26
+ }
27
+ release() {
28
+ if (this.waiting.length > 0) {
29
+ const next = this.waiting.shift();
30
+ if (next) {
31
+ next();
32
+ }
33
+ }
34
+ else {
35
+ this.current--;
36
+ }
37
+ }
38
+ }
39
+ /**
40
+ * Runs tasks in parallel according to mode:
41
+ * - sequential: run one at a time
42
+ * - worktree: create worktree per task, run in parallel, merge back
43
+ * - same-branch: run all in same dir with pull-rebase-push cycle
44
+ *
45
+ * Manages concurrency via a semaphore pattern.
46
+ */
47
+ export async function executeBatch(tasks, poolConfig, workerFactory) {
48
+ if (tasks.length === 0)
49
+ return [];
50
+ switch (poolConfig.mode) {
51
+ case "sequential":
52
+ return executeSequential(tasks, poolConfig, workerFactory);
53
+ case "worktree":
54
+ return executeWorktree(tasks, poolConfig, workerFactory);
55
+ case "same-branch":
56
+ return executeSameBranch(tasks, poolConfig, workerFactory);
57
+ }
58
+ }
59
+ async function executeSequential(tasks, poolConfig, workerFactory) {
60
+ const results = [];
61
+ for (const task of tasks) {
62
+ const deps = workerFactory(task.id, poolConfig.repoRoot);
63
+ const result = await runSingleWorker(task, poolConfig, deps);
64
+ results.push(result);
65
+ }
66
+ return results;
67
+ }
68
+ async function executeWorktree(tasks, poolConfig, workerFactory) {
69
+ const semaphore = new Semaphore(poolConfig.maxConcurrency);
70
+ const baseBranch = await getCurrentBranch(poolConfig.repoRoot);
71
+ const promises = tasks.map(async (task) => {
72
+ await semaphore.acquire();
73
+ let worktreePath;
74
+ const taskBranch = buildTaskBranchName(task, poolConfig.piLoopConfig);
75
+ try {
76
+ worktreePath = await createWorktree(poolConfig.repoRoot, task.id, baseBranch, poolConfig.worktreeBaseDir, taskBranch);
77
+ const deps = workerFactory(task.id, worktreePath);
78
+ const result = await runSingleWorker(task, poolConfig, deps);
79
+ // Merge successful work back to base branch
80
+ if (result.success) {
81
+ const mergeResult = await mergeWorktree(poolConfig.repoRoot, taskBranch, baseBranch);
82
+ if (!mergeResult.success) {
83
+ // Abort the failed merge so the repo is clean
84
+ await gitExec(["merge", "--abort"], poolConfig.repoRoot);
85
+ return {
86
+ ...result,
87
+ success: false,
88
+ error: `Merge conflict in: ${mergeResult.conflictFiles?.join(", ") ?? "unknown files"}`,
89
+ };
90
+ }
91
+ }
92
+ return result;
93
+ }
94
+ catch (err) {
95
+ return {
96
+ taskId: task.id,
97
+ success: false,
98
+ error: err instanceof Error ? err.message : String(err),
99
+ attempts: 1,
100
+ changedFiles: [],
101
+ };
102
+ }
103
+ finally {
104
+ if (worktreePath) {
105
+ try {
106
+ await removeWorktree(poolConfig.repoRoot, worktreePath, taskBranch);
107
+ }
108
+ catch {
109
+ // Best-effort cleanup
110
+ }
111
+ }
112
+ semaphore.release();
113
+ }
114
+ });
115
+ return Promise.all(promises);
116
+ }
117
+ async function executeSameBranch(tasks, poolConfig, workerFactory) {
118
+ const semaphore = new Semaphore(poolConfig.maxConcurrency);
119
+ // Pull latest before starting parallel work
120
+ await pullLatest(poolConfig.repoRoot);
121
+ const promises = tasks.map(async (task) => {
122
+ await semaphore.acquire();
123
+ try {
124
+ const deps = workerFactory(task.id, poolConfig.repoRoot);
125
+ const result = await runSingleWorker(task, poolConfig, deps);
126
+ // Commit and push successful work
127
+ if (result.success) {
128
+ const pushResult = await commitAndPush(poolConfig.repoRoot, `task(${task.id}): ${task.title?.slice(0, 72) ?? task.id}`, poolConfig.piLoopConfig.git.commitPrefix);
129
+ if (!pushResult.success && pushResult.needsRebase) {
130
+ const rebased = await rebaseAndRetry(poolConfig.repoRoot, 3);
131
+ if (!rebased) {
132
+ return {
133
+ ...result,
134
+ success: false,
135
+ error: "Push failed after rebase retries",
136
+ };
137
+ }
138
+ }
139
+ }
140
+ return result;
141
+ }
142
+ finally {
143
+ semaphore.release();
144
+ }
145
+ });
146
+ return Promise.all(promises);
147
+ }
148
+ async function runSingleWorker(task, poolConfig, deps) {
149
+ try {
150
+ const result = await runWorker(task, poolConfig.piLoopConfig, deps);
151
+ return {
152
+ taskId: result.taskId,
153
+ success: result.success,
154
+ commitHash: result.commitHash,
155
+ error: result.rejection,
156
+ attempts: result.attempts,
157
+ changedFiles: result.changedFiles,
158
+ };
159
+ }
160
+ catch (err) {
161
+ return {
162
+ taskId: task.id,
163
+ success: false,
164
+ error: err instanceof Error ? err.message : String(err),
165
+ attempts: 1,
166
+ changedFiles: [],
167
+ };
168
+ }
169
+ }
170
+ export function buildTaskBranchName(task, config) {
171
+ if (config.taskBackend !== "linear") {
172
+ return `pi-loop/${task.id}`;
173
+ }
174
+ const slug = task.title
175
+ .toLowerCase()
176
+ .replace(/[^a-z0-9]+/g, "-")
177
+ .replace(/(^-|-$)/g, "")
178
+ .slice(0, 32);
179
+ const suffix = slug || "task";
180
+ return `pi-loop/${task.id}-${suffix}`;
181
+ }
182
+ //# sourceMappingURL=pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pool.js","sourceRoot":"","sources":["../../src/swarm/pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Dependency graph construction and batch dispatch scheduling.
3
+ */
4
+ import type { Task } from "../core/task-state.js";
5
+ export interface DependencyGraph {
6
+ nodes: Map<string, Task>;
7
+ edges: Map<string, Set<string>>;
8
+ }
9
+ export type ParallelismMode = "sequential" | "worktree" | "same-branch";
10
+ /**
11
+ * Creates a DAG from task dependencies.
12
+ * Throws if circular dependencies are detected.
13
+ */
14
+ export declare function buildDependencyGraph(tasks: Task[]): DependencyGraph;
15
+ /**
16
+ * Returns tasks whose dependencies are ALL in completedIds AND whose status is "pending".
17
+ */
18
+ export declare function getReadyBatch(graph: DependencyGraph, completedIds: Set<string>): Task[];
19
+ /**
20
+ * Groups tasks into batches where tasks in the same batch are unlikely
21
+ * to touch the same files. Uses keyword extraction from task titles to estimate overlap.
22
+ * Tasks sharing >50% keywords go in different batches.
23
+ *
24
+ * When fileHints is provided (from previous commit history), uses actual file paths
25
+ * instead of keyword heuristics for more accurate grouping.
26
+ */
27
+ export declare function groupNonOverlapping(tasks: Task[], fileHints?: Map<string, string[]>): Task[][];
28
+ /**
29
+ * Selects parallelism mode based on concurrency level.
30
+ * 1=sequential, 2-8=worktree, 9+=same-branch
31
+ */
32
+ export declare function selectParallelismMode(concurrency: number): ParallelismMode;
33
+ /**
34
+ * Detects circular dependencies using DFS.
35
+ * Returns the cycle path if found, null if no cycles exist.
36
+ */
37
+ export declare function detectCircularDeps(graph: DependencyGraph): string[] | null;
38
+ //# sourceMappingURL=scheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/swarm/scheduler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAElD,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACzB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;CAChC;AAED,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,UAAU,GAAG,aAAa,CAAC;AAExE;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,eAAe,CAiBnE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC5B,KAAK,EAAE,eAAe,EACtB,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,GACvB,IAAI,EAAE,CA0BR;AAuCD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAClC,KAAK,EAAE,IAAI,EAAE,EACb,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAC/B,IAAI,EAAE,EAAE,CA+CV;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,CAI1E;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,EAAE,GAAG,IAAI,CAiB1E"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Dependency graph construction and batch dispatch scheduling.
3
+ */
4
+ /**
5
+ * Creates a DAG from task dependencies.
6
+ * Throws if circular dependencies are detected.
7
+ */
8
+ export function buildDependencyGraph(tasks) {
9
+ const nodes = new Map();
10
+ const edges = new Map();
11
+ for (const task of tasks) {
12
+ nodes.set(task.id, task);
13
+ edges.set(task.id, new Set(task.dependencies));
14
+ }
15
+ const graph = { nodes, edges };
16
+ const cycle = detectCircularDeps(graph);
17
+ if (cycle) {
18
+ throw new Error(`Circular dependency detected: ${cycle.join(" \u2192 ")}`);
19
+ }
20
+ return graph;
21
+ }
22
+ /**
23
+ * Returns tasks whose dependencies are ALL in completedIds AND whose status is "pending".
24
+ */
25
+ export function getReadyBatch(graph, completedIds) {
26
+ const ready = [];
27
+ for (const [taskId, node] of graph.nodes) {
28
+ if (node.status !== "pending")
29
+ continue;
30
+ const deps = graph.edges.get(taskId);
31
+ if (!deps || deps.size === 0) {
32
+ ready.push(node);
33
+ continue;
34
+ }
35
+ let allDepsComplete = true;
36
+ for (const depId of deps) {
37
+ if (!completedIds.has(depId)) {
38
+ allDepsComplete = false;
39
+ break;
40
+ }
41
+ }
42
+ if (allDepsComplete) {
43
+ ready.push(node);
44
+ }
45
+ }
46
+ return ready;
47
+ }
48
+ /**
49
+ * Extracts keywords from a task title for overlap estimation.
50
+ */
51
+ function extractKeywords(title) {
52
+ const stopWords = new Set([
53
+ "a", "an", "the", "and", "or", "but", "in", "on", "at", "to",
54
+ "for", "of", "with", "by", "from", "as", "is", "was", "are",
55
+ "be", "been", "being", "have", "has", "had", "do", "does",
56
+ "did", "will", "would", "could", "should", "may", "might",
57
+ "shall", "can", "need", "must", "it", "its", "this", "that",
58
+ ]);
59
+ return new Set(title
60
+ .toLowerCase()
61
+ .replace(/[^a-z0-9\s]/g, " ")
62
+ .split(/\s+/)
63
+ .filter((word) => word.length > 1 && !stopWords.has(word)));
64
+ }
65
+ /**
66
+ * Computes keyword overlap ratio between two sets.
67
+ * Returns a value between 0 and 1.
68
+ */
69
+ function keywordOverlap(a, b) {
70
+ if (a.size === 0 || b.size === 0)
71
+ return 0;
72
+ let shared = 0;
73
+ for (const word of a) {
74
+ if (b.has(word))
75
+ shared++;
76
+ }
77
+ const minSize = Math.min(a.size, b.size);
78
+ return minSize === 0 ? 0 : shared / minSize;
79
+ }
80
+ /**
81
+ * Groups tasks into batches where tasks in the same batch are unlikely
82
+ * to touch the same files. Uses keyword extraction from task titles to estimate overlap.
83
+ * Tasks sharing >50% keywords go in different batches.
84
+ *
85
+ * When fileHints is provided (from previous commit history), uses actual file paths
86
+ * instead of keyword heuristics for more accurate grouping.
87
+ */
88
+ export function groupNonOverlapping(tasks, fileHints) {
89
+ if (tasks.length === 0)
90
+ return [];
91
+ if (tasks.length === 1)
92
+ return [[tasks[0]]];
93
+ const OVERLAP_THRESHOLD = 0.5;
94
+ const batches = [];
95
+ // Build overlap data: either from file hints or keyword extraction
96
+ const overlapData = new Map();
97
+ for (const task of tasks) {
98
+ const hints = fileHints?.get(task.id);
99
+ if (hints && hints.length > 0) {
100
+ overlapData.set(task.id, new Set(hints));
101
+ }
102
+ else {
103
+ overlapData.set(task.id, extractKeywords(task.title));
104
+ }
105
+ }
106
+ for (const task of tasks) {
107
+ const taskData = overlapData.get(task.id);
108
+ let placed = false;
109
+ for (const batch of batches) {
110
+ let overlaps = false;
111
+ for (const existing of batch) {
112
+ const existingData = overlapData.get(existing.id);
113
+ if (keywordOverlap(taskData, existingData) > OVERLAP_THRESHOLD) {
114
+ overlaps = true;
115
+ break;
116
+ }
117
+ }
118
+ if (!overlaps) {
119
+ batch.push(task);
120
+ placed = true;
121
+ break;
122
+ }
123
+ }
124
+ if (!placed) {
125
+ batches.push([task]);
126
+ }
127
+ }
128
+ return batches;
129
+ }
130
+ /**
131
+ * Selects parallelism mode based on concurrency level.
132
+ * 1=sequential, 2-8=worktree, 9+=same-branch
133
+ */
134
+ export function selectParallelismMode(concurrency) {
135
+ if (concurrency <= 1)
136
+ return "sequential";
137
+ if (concurrency <= 8)
138
+ return "worktree";
139
+ return "same-branch";
140
+ }
141
+ /**
142
+ * Detects circular dependencies using DFS.
143
+ * Returns the cycle path if found, null if no cycles exist.
144
+ */
145
+ export function detectCircularDeps(graph) {
146
+ // Color states: 0=unvisited, 1=in current path, 2=fully processed
147
+ const color = new Map();
148
+ const parent = new Map();
149
+ for (const nodeId of graph.nodes.keys()) {
150
+ color.set(nodeId, 0);
151
+ }
152
+ for (const nodeId of graph.nodes.keys()) {
153
+ if (color.get(nodeId) === 0) {
154
+ const cycle = dfsVisit(nodeId, graph, color, parent);
155
+ if (cycle)
156
+ return cycle;
157
+ }
158
+ }
159
+ return null;
160
+ }
161
+ function dfsVisit(nodeId, graph, color, parent) {
162
+ // 0=unvisited, 1=in path, 2=done
163
+ color.set(nodeId, 1);
164
+ const deps = graph.edges.get(nodeId);
165
+ if (deps) {
166
+ for (const depId of deps) {
167
+ if (!graph.nodes.has(depId))
168
+ continue;
169
+ if (color.get(depId) === 1) {
170
+ // Found a cycle -- reconstruct the path
171
+ const cycle = [depId, nodeId];
172
+ let current = nodeId;
173
+ while (parent.has(current) && parent.get(current) !== depId) {
174
+ current = parent.get(current);
175
+ cycle.push(current);
176
+ }
177
+ cycle.push(depId);
178
+ return cycle.reverse();
179
+ }
180
+ if (color.get(depId) === 0) {
181
+ parent.set(depId, nodeId);
182
+ const cycle = dfsVisit(depId, graph, color, parent);
183
+ if (cycle)
184
+ return cycle;
185
+ }
186
+ }
187
+ }
188
+ color.set(nodeId, 2);
189
+ return null;
190
+ }
191
+ //# sourceMappingURL=scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/swarm/scheduler.ts"],"names":[],"mappings":"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"}