@intrect/openswarm 0.5.0 → 0.8.1

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 (226) hide show
  1. package/LICENSE +21 -674
  2. package/README.md +97 -35
  3. package/config.example.yaml +8 -2
  4. package/dist/adapters/agenticLoop.d.ts +15 -1
  5. package/dist/adapters/agenticLoop.d.ts.map +1 -1
  6. package/dist/adapters/agenticLoop.js +62 -4
  7. package/dist/adapters/agenticLoop.js.map +1 -1
  8. package/dist/adapters/chatStream.d.ts +55 -0
  9. package/dist/adapters/chatStream.d.ts.map +1 -0
  10. package/dist/adapters/chatStream.js +116 -0
  11. package/dist/adapters/chatStream.js.map +1 -0
  12. package/dist/adapters/codex.d.ts +6 -0
  13. package/dist/adapters/codex.d.ts.map +1 -1
  14. package/dist/adapters/codex.js +27 -1
  15. package/dist/adapters/codex.js.map +1 -1
  16. package/dist/adapters/codexModels.d.ts +20 -0
  17. package/dist/adapters/codexModels.d.ts.map +1 -0
  18. package/dist/adapters/codexModels.js +195 -0
  19. package/dist/adapters/codexModels.js.map +1 -0
  20. package/dist/adapters/codexResponses.d.ts +97 -0
  21. package/dist/adapters/codexResponses.d.ts.map +1 -0
  22. package/dist/adapters/codexResponses.js +302 -0
  23. package/dist/adapters/codexResponses.js.map +1 -0
  24. package/dist/adapters/gpt.d.ts.map +1 -1
  25. package/dist/adapters/gpt.js +17 -131
  26. package/dist/adapters/gpt.js.map +1 -1
  27. package/dist/adapters/index.d.ts +7 -0
  28. package/dist/adapters/index.d.ts.map +1 -1
  29. package/dist/adapters/index.js +11 -0
  30. package/dist/adapters/index.js.map +1 -1
  31. package/dist/adapters/local.d.ts.map +1 -1
  32. package/dist/adapters/local.js +17 -125
  33. package/dist/adapters/local.js.map +1 -1
  34. package/dist/adapters/openrouter.d.ts +5 -24
  35. package/dist/adapters/openrouter.d.ts.map +1 -1
  36. package/dist/adapters/openrouter.js +20 -121
  37. package/dist/adapters/openrouter.js.map +1 -1
  38. package/dist/adapters/resultParsing.d.ts +6 -0
  39. package/dist/adapters/resultParsing.d.ts.map +1 -0
  40. package/dist/adapters/resultParsing.js +139 -0
  41. package/dist/adapters/resultParsing.js.map +1 -0
  42. package/dist/adapters/tools.d.ts +0 -6
  43. package/dist/adapters/tools.d.ts.map +1 -1
  44. package/dist/adapters/tools.js +57 -3
  45. package/dist/adapters/tools.js.map +1 -1
  46. package/dist/adapters/types.d.ts +21 -1
  47. package/dist/adapters/types.d.ts.map +1 -1
  48. package/dist/adapters/webTools.d.ts +9 -0
  49. package/dist/adapters/webTools.d.ts.map +1 -0
  50. package/dist/adapters/webTools.js +195 -0
  51. package/dist/adapters/webTools.js.map +1 -0
  52. package/dist/agents/pairPipeline.d.ts +26 -1
  53. package/dist/agents/pairPipeline.d.ts.map +1 -1
  54. package/dist/agents/pairPipeline.js +82 -14
  55. package/dist/agents/pairPipeline.js.map +1 -1
  56. package/dist/agents/reflection.d.ts +56 -0
  57. package/dist/agents/reflection.d.ts.map +1 -0
  58. package/dist/agents/reflection.js +120 -0
  59. package/dist/agents/reflection.js.map +1 -0
  60. package/dist/agents/worker.d.ts +2 -0
  61. package/dist/agents/worker.d.ts.map +1 -1
  62. package/dist/agents/worker.js +1 -0
  63. package/dist/agents/worker.js.map +1 -1
  64. package/dist/auth/index.d.ts +1 -0
  65. package/dist/auth/index.d.ts.map +1 -1
  66. package/dist/auth/index.js +1 -0
  67. package/dist/auth/index.js.map +1 -1
  68. package/dist/auth/linearPkce.d.ts +22 -0
  69. package/dist/auth/linearPkce.d.ts.map +1 -0
  70. package/dist/auth/linearPkce.js +208 -0
  71. package/dist/auth/linearPkce.js.map +1 -0
  72. package/dist/auth/oauthPkce.d.ts.map +1 -1
  73. package/dist/auth/oauthPkce.js +18 -5
  74. package/dist/auth/oauthPkce.js.map +1 -1
  75. package/dist/auth/oauthStore.d.ts.map +1 -1
  76. package/dist/auth/oauthStore.js +10 -2
  77. package/dist/auth/oauthStore.js.map +1 -1
  78. package/dist/automation/autonomousRunner.d.ts +6 -6
  79. package/dist/automation/autonomousRunner.d.ts.map +1 -1
  80. package/dist/automation/autonomousRunner.js +15 -13
  81. package/dist/automation/autonomousRunner.js.map +1 -1
  82. package/dist/automation/backlogGrooming.d.ts +21 -0
  83. package/dist/automation/backlogGrooming.d.ts.map +1 -0
  84. package/dist/automation/backlogGrooming.js +80 -0
  85. package/dist/automation/backlogGrooming.js.map +1 -0
  86. package/dist/automation/localCI.d.ts +24 -0
  87. package/dist/automation/localCI.d.ts.map +1 -0
  88. package/dist/automation/localCI.js +84 -0
  89. package/dist/automation/localCI.js.map +1 -0
  90. package/dist/automation/runnerExecution.d.ts +33 -7
  91. package/dist/automation/runnerExecution.d.ts.map +1 -1
  92. package/dist/automation/runnerExecution.js +202 -154
  93. package/dist/automation/runnerExecution.js.map +1 -1
  94. package/dist/automation/runnerTypes.d.ts +5 -1
  95. package/dist/automation/runnerTypes.d.ts.map +1 -1
  96. package/dist/automation/taskSource.d.ts +101 -0
  97. package/dist/automation/taskSource.d.ts.map +1 -0
  98. package/dist/automation/taskSource.js +136 -0
  99. package/dist/automation/taskSource.js.map +1 -0
  100. package/dist/automation/workerAuditLog.d.ts +29 -0
  101. package/dist/automation/workerAuditLog.d.ts.map +1 -0
  102. package/dist/automation/workerAuditLog.js +82 -0
  103. package/dist/automation/workerAuditLog.js.map +1 -0
  104. package/dist/cli/authHandler.d.ts +6 -0
  105. package/dist/cli/authHandler.d.ts.map +1 -1
  106. package/dist/cli/authHandler.js +37 -2
  107. package/dist/cli/authHandler.js.map +1 -1
  108. package/dist/cli/daemon.d.ts +5 -0
  109. package/dist/cli/daemon.d.ts.map +1 -1
  110. package/dist/cli/daemon.js +13 -0
  111. package/dist/cli/daemon.js.map +1 -1
  112. package/dist/cli/doctorHandler.d.ts +2 -0
  113. package/dist/cli/doctorHandler.d.ts.map +1 -0
  114. package/dist/cli/doctorHandler.js +114 -0
  115. package/dist/cli/doctorHandler.js.map +1 -0
  116. package/dist/cli/initWizard.d.ts +13 -0
  117. package/dist/cli/initWizard.d.ts.map +1 -0
  118. package/dist/cli/initWizard.js +334 -0
  119. package/dist/cli/initWizard.js.map +1 -0
  120. package/dist/cli.js +110 -37
  121. package/dist/cli.js.map +1 -1
  122. package/dist/core/config.d.ts +50 -2
  123. package/dist/core/config.d.ts.map +1 -1
  124. package/dist/core/config.js +69 -10
  125. package/dist/core/config.js.map +1 -1
  126. package/dist/core/envFile.d.ts +6 -0
  127. package/dist/core/envFile.d.ts.map +1 -1
  128. package/dist/core/envFile.js +39 -1
  129. package/dist/core/envFile.js.map +1 -1
  130. package/dist/core/providerOverride.d.ts +6 -0
  131. package/dist/core/providerOverride.d.ts.map +1 -0
  132. package/dist/core/providerOverride.js +37 -0
  133. package/dist/core/providerOverride.js.map +1 -0
  134. package/dist/core/service.d.ts.map +1 -1
  135. package/dist/core/service.js +41 -18
  136. package/dist/core/service.js.map +1 -1
  137. package/dist/core/types.d.ts +16 -2
  138. package/dist/core/types.d.ts.map +1 -1
  139. package/dist/discord/discordHandlers.d.ts.map +1 -1
  140. package/dist/discord/discordHandlers.js +15 -12
  141. package/dist/discord/discordHandlers.js.map +1 -1
  142. package/dist/index.js +12 -1
  143. package/dist/index.js.map +1 -1
  144. package/dist/issues/sqliteStore.d.ts.map +1 -1
  145. package/dist/issues/sqliteStore.js +7 -2
  146. package/dist/issues/sqliteStore.js.map +1 -1
  147. package/dist/knowledge/scanner.d.ts.map +1 -1
  148. package/dist/knowledge/scanner.js +5 -0
  149. package/dist/knowledge/scanner.js.map +1 -1
  150. package/dist/linear/linear.d.ts +45 -2
  151. package/dist/linear/linear.d.ts.map +1 -1
  152. package/dist/linear/linear.js +154 -3
  153. package/dist/linear/linear.js.map +1 -1
  154. package/dist/locale/prompts/en.d.ts.map +1 -1
  155. package/dist/locale/prompts/en.js +14 -2
  156. package/dist/locale/prompts/en.js.map +1 -1
  157. package/dist/locale/prompts/ko.d.ts.map +1 -1
  158. package/dist/locale/prompts/ko.js +14 -2
  159. package/dist/locale/prompts/ko.js.map +1 -1
  160. package/dist/mcp/mcpClient.d.ts +27 -0
  161. package/dist/mcp/mcpClient.d.ts.map +1 -0
  162. package/dist/mcp/mcpClient.js +145 -0
  163. package/dist/mcp/mcpClient.js.map +1 -0
  164. package/dist/memory/memoryCore.d.ts.map +1 -1
  165. package/dist/memory/memoryCore.js +8 -2
  166. package/dist/memory/memoryCore.js.map +1 -1
  167. package/dist/notify/notifier.d.ts +26 -0
  168. package/dist/notify/notifier.d.ts.map +1 -0
  169. package/dist/notify/notifier.js +131 -0
  170. package/dist/notify/notifier.js.map +1 -0
  171. package/dist/orchestration/conflictDetector.d.ts +5 -2
  172. package/dist/orchestration/conflictDetector.d.ts.map +1 -1
  173. package/dist/orchestration/conflictDetector.js +35 -6
  174. package/dist/orchestration/conflictDetector.js.map +1 -1
  175. package/dist/orchestration/decisionEngine.d.ts +20 -0
  176. package/dist/orchestration/decisionEngine.d.ts.map +1 -1
  177. package/dist/orchestration/decisionEngine.js +45 -0
  178. package/dist/orchestration/decisionEngine.js.map +1 -1
  179. package/dist/support/banner.d.ts +7 -0
  180. package/dist/support/banner.d.ts.map +1 -0
  181. package/dist/support/banner.js +32 -0
  182. package/dist/support/banner.js.map +1 -0
  183. package/dist/support/chat.js +28 -5
  184. package/dist/support/chat.js.map +1 -1
  185. package/dist/support/chatBackend.d.ts +6 -0
  186. package/dist/support/chatBackend.d.ts.map +1 -1
  187. package/dist/support/chatBackend.js +68 -0
  188. package/dist/support/chatBackend.js.map +1 -1
  189. package/dist/support/chatTui.d.ts.map +1 -1
  190. package/dist/support/chatTui.js +202 -9
  191. package/dist/support/chatTui.js.map +1 -1
  192. package/dist/support/colors.d.ts +15 -0
  193. package/dist/support/colors.d.ts.map +1 -0
  194. package/dist/support/colors.js +23 -0
  195. package/dist/support/colors.js.map +1 -0
  196. package/dist/support/planCommand.d.ts +17 -0
  197. package/dist/support/planCommand.d.ts.map +1 -0
  198. package/dist/support/planCommand.js +114 -0
  199. package/dist/support/planCommand.js.map +1 -0
  200. package/dist/support/planner.d.ts +9 -2
  201. package/dist/support/planner.d.ts.map +1 -1
  202. package/dist/support/planner.js +43 -111
  203. package/dist/support/planner.js.map +1 -1
  204. package/dist/support/promptHelper.d.ts +24 -0
  205. package/dist/support/promptHelper.d.ts.map +1 -0
  206. package/dist/support/promptHelper.js +94 -0
  207. package/dist/support/promptHelper.js.map +1 -0
  208. package/dist/support/rateLimiter.d.ts.map +1 -1
  209. package/dist/support/rateLimiter.js +6 -0
  210. package/dist/support/rateLimiter.js.map +1 -1
  211. package/dist/support/repoMetadata.d.ts +7 -0
  212. package/dist/support/repoMetadata.d.ts.map +1 -1
  213. package/dist/support/repoMetadata.js +13 -1
  214. package/dist/support/repoMetadata.js.map +1 -1
  215. package/dist/support/web.d.ts.map +1 -1
  216. package/dist/support/web.js +143 -65
  217. package/dist/support/web.js.map +1 -1
  218. package/dist/support/worktreeManager.d.ts +6 -1
  219. package/dist/support/worktreeManager.d.ts.map +1 -1
  220. package/dist/support/worktreeManager.js +23 -1
  221. package/dist/support/worktreeManager.js.map +1 -1
  222. package/dist/taskState/store.d.ts +1 -0
  223. package/dist/taskState/store.d.ts.map +1 -1
  224. package/dist/taskState/store.js +22 -1
  225. package/dist/taskState/store.js.map +1 -1
  226. package/package.json +4 -2
@@ -3,14 +3,19 @@ import type { TaskItem, DecisionResult } from '../orchestration/decisionEngine.j
3
3
  import type { ExecutorResult } from '../orchestration/workflow.js';
4
4
  import type { PipelineResult } from '../agents/pairPipeline.js';
5
5
  import type { DefaultRolesConfig, JobProfile } from '../core/types.js';
6
+ import type { SubTask } from '../support/planner.js';
6
7
  import { type DraftAnalysis } from '../agents/draftAnalyzer.js';
7
- type DiscordSendFn = (content: string | {
8
- embeds: EmbedBuilder[];
9
- }) => Promise<void>;
10
- export declare function setDiscordReporter(sendFn: DiscordSendFn): void;
8
+ import type { Notifier } from '../notify/notifier.js';
9
+ import type { ITaskSource } from './taskSource.js';
10
+ export declare function setNotifier(n: Notifier): void;
11
+ /**
12
+ * Send an outbound notification. Name kept for call-site stability — it is now
13
+ * backend-agnostic (routes to the configured Notifier, not necessarily Discord).
14
+ */
11
15
  export declare function reportToDiscord(message: string | EmbedBuilder): Promise<void>;
12
- type LinearFetchFn = () => Promise<TaskItem[]>;
13
- export declare function setLinearFetcher(fetchFn: LinearFetchFn): void;
16
+ export declare function setTaskSource(source: ITaskSource): void;
17
+ /** Accessor for callers outside this module (autonomousRunner). */
18
+ export declare function getTaskSource(): ITaskSource | null;
14
19
  export declare function fetchLinearTasks(): Promise<{
15
20
  tasks: TaskItem[];
16
21
  error?: string;
@@ -40,9 +45,31 @@ export interface ExecutionContext {
40
45
  scheduleNextHeartbeat?: () => void;
41
46
  /** Pipeline guards configuration */
42
47
  guards?: Partial<import('../core/types.js').PipelineGuardsConfig>;
48
+ /** Max objective self-repair attempts (lint/bs/test) before giving up (default: 3) */
49
+ maxReflections?: number;
43
50
  }
44
51
  export declare function resolveProjectPath(ctx: ExecutionContext, task: TaskItem): Promise<string | null>;
45
52
  export declare function isValidProjectPath(path: string): Promise<boolean>;
53
+ /**
54
+ * Create Linear sub-issues from an (approved) decomposition: create each
55
+ * sub-issue, register tracking for limits, wire dependencies
56
+ * (ready→Todo / blocked→Backlog), sync state comments, and trigger an immediate
57
+ * heartbeat. Shared by the autonomous `decomposeTask` path and the TUI `/plan`
58
+ * dispatch endpoint so both behave identically (no logic fork). The caller must
59
+ * have already created the parent issue (`parentIssueId`).
60
+ */
61
+ export declare function createSubIssuesWithDependencies(parentIssueId: string, task: {
62
+ title: string;
63
+ issueIdentifier?: string;
64
+ parentId?: string;
65
+ linearProject?: {
66
+ id?: string;
67
+ name?: string;
68
+ };
69
+ }, subTasks: SubTask[], totalEstimatedMinutes: number, ctx: {
70
+ reportToDiscord: (msg: string) => Promise<void> | void;
71
+ scheduleNextHeartbeat?: () => void;
72
+ }, taskId: string, dailyLimit: number): Promise<boolean>;
46
73
  export declare function decomposeTask(ctx: ExecutionContext, task: TaskItem, projectPath: string, targetMinutes: number, draftAnalysis?: DraftAnalysis): Promise<boolean | 'no-decomp'>;
47
74
  export declare function executePipeline(ctx: ExecutionContext, task: TaskItem, projectPath: string): Promise<PipelineResult>;
48
75
  export declare function requestApproval(decision: DecisionResult, reportFn: (message: string | EmbedBuilder) => Promise<void>): Promise<void>;
@@ -50,5 +77,4 @@ export declare function reportExecutionResult(task: TaskItem, result: ExecutorRe
50
77
  export declare function reconcileCompletionState(task: TaskItem): Promise<void>;
51
78
  export declare function syncFailureState(task: TaskItem, reason: string): Promise<void>;
52
79
  export declare function syncSuccessState(task: TaskItem, confidence?: number): Promise<void>;
53
- export {};
54
80
  //# sourceMappingURL=runnerExecution.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runnerExecution.d.ts","sourceRoot":"","sources":["../../src/automation/runnerExecution.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runnerExecution.d.ts","sourceRoot":"","sources":["../../src/automation/runnerExecution.ts"],"names":[],"mappings":"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"}
@@ -4,12 +4,12 @@
4
4
  // ============================================
5
5
  import { EmbedBuilder } from 'discord.js';
6
6
  import { createPipelineFromConfig, buildTaskPrefix } from '../agents/pairPipeline.js';
7
+ import { buildWorkerStartComment, buildWorkerCompleteComment } from './workerAuditLog.js';
7
8
  import { formatParsedTaskSummary, loadParsedTask } from '../orchestration/taskParser.js';
8
9
  import { saveCognitiveMemory } from '../memory/index.js';
9
10
  import * as workerAgent from '../agents/worker.js';
10
11
  import * as reviewerAgent from '../agents/reviewer.js';
11
12
  import * as projectMapper from '../support/projectMapper.js';
12
- import * as linear from '../linear/index.js';
13
13
  import * as planner from '../support/planner.js';
14
14
  import { analyzeIssue } from '../knowledge/index.js';
15
15
  import { runDraftAnalysis } from '../agents/draftAnalyzer.js';
@@ -18,49 +18,45 @@ import { broadcastEvent } from '../core/eventHub.js';
18
18
  import { buildBranchName, createWorktree, commitAndCreatePR, removeWorktree, } from '../support/worktreeManager.js';
19
19
  import { getDecompositionDepth, getChildrenCount, getDailyCreationCount, canCreateMoreIssues, registerDecomposition, } from './runnerState.js';
20
20
  import { buildTaskStateSyncComment, completeParentIfChildrenDone, markTaskBlocked, markTaskDecomposed, markTaskDone, markTaskInProgress, releaseDependentTasks, upsertTaskState, } from '../taskState/store.js';
21
- let discordSend = null;
22
- export function setDiscordReporter(sendFn) {
23
- discordSend = sendFn;
24
- console.log('[AutonomousRunner] Discord reporter registered');
21
+ // Notifier (outbound notifications — Discord/Slack/Telegram/webhook, INT-1576)
22
+ let notifier = null;
23
+ export function setNotifier(n) {
24
+ notifier = n;
25
+ console.log('[AutonomousRunner] Notifier registered');
25
26
  }
27
+ /**
28
+ * Send an outbound notification. Name kept for call-site stability — it is now
29
+ * backend-agnostic (routes to the configured Notifier, not necessarily Discord).
30
+ */
26
31
  export async function reportToDiscord(message) {
27
- if (!discordSend) {
28
- console.log('[AutonomousRunner] No Discord reporter, logging instead:', typeof message === 'string' ? message : message.data.title);
32
+ if (!notifier) {
33
+ console.log('[AutonomousRunner] No notifier, logging instead:', typeof message === 'string' ? message : message.data.title);
29
34
  return;
30
35
  }
31
- try {
32
- if (typeof message === 'string') {
33
- // Convert plain text to Embed for consistent Discord UI
34
- const embed = new EmbedBuilder()
35
- .setDescription(message)
36
- .setColor(0x00ff41) // OpenSwarm green
37
- .setTimestamp();
38
- await discordSend({ embeds: [embed] });
39
- }
40
- else {
41
- await discordSend({ embeds: [message] });
42
- }
43
- }
44
- catch (error) {
45
- console.error('[AutonomousRunner] Discord report failed:', error);
46
- }
36
+ await notifier.notify(message);
37
+ }
38
+ // Task source (Linear OR local SQLite INT-1577). Injected at service start;
39
+ // the runner routes all task tracking through it instead of importing linear.* .
40
+ let taskSource = null;
41
+ export function setTaskSource(source) {
42
+ taskSource = source;
43
+ console.log(`[AutonomousRunner] Task source registered (${source.kind})`);
47
44
  }
48
- let linearFetch = null;
49
- export function setLinearFetcher(fetchFn) {
50
- linearFetch = fetchFn;
51
- console.log('[AutonomousRunner] Linear fetcher registered');
45
+ /** Accessor for callers outside this module (autonomousRunner). */
46
+ export function getTaskSource() {
47
+ return taskSource;
52
48
  }
53
49
  // Track consecutive fetch failures for visibility
54
50
  let fetchFailureCount = 0;
55
51
  export async function fetchLinearTasks() {
56
- if (!linearFetch) {
57
- console.log('[AutonomousRunner] No Linear fetcher registered');
58
- return { tasks: [], error: 'No Linear fetcher registered' };
52
+ if (!taskSource) {
53
+ console.log('[AutonomousRunner] No task source registered');
54
+ return { tasks: [], error: 'No task source registered' };
59
55
  }
60
56
  try {
61
- const tasks = await linearFetch();
57
+ const tasks = await taskSource.fetchTasks();
62
58
  if (fetchFailureCount > 0) {
63
- console.log(`[AutonomousRunner] Linear fetch recovered after ${fetchFailureCount} failures`);
59
+ console.log(`[AutonomousRunner] Task fetch recovered after ${fetchFailureCount} failures`);
64
60
  }
65
61
  fetchFailureCount = 0;
66
62
  return { tasks };
@@ -68,7 +64,7 @@ export async function fetchLinearTasks() {
68
64
  catch (error) {
69
65
  fetchFailureCount++;
70
66
  const msg = error instanceof Error ? error.message : String(error);
71
- console.error(`[AutonomousRunner] Linear fetch failed (${fetchFailureCount}x consecutive): ${msg}`);
67
+ console.error(`[AutonomousRunner] Task fetch failed (${fetchFailureCount}x consecutive): ${msg}`);
72
68
  return { tasks: [], error: msg };
73
69
  }
74
70
  }
@@ -141,6 +137,127 @@ export async function isValidProjectPath(path) {
141
137
  }
142
138
  }
143
139
  // Task Decomposition
140
+ /**
141
+ * Create Linear sub-issues from an (approved) decomposition: create each
142
+ * sub-issue, register tracking for limits, wire dependencies
143
+ * (ready→Todo / blocked→Backlog), sync state comments, and trigger an immediate
144
+ * heartbeat. Shared by the autonomous `decomposeTask` path and the TUI `/plan`
145
+ * dispatch endpoint so both behave identically (no logic fork). The caller must
146
+ * have already created the parent issue (`parentIssueId`).
147
+ */
148
+ export async function createSubIssuesWithDependencies(parentIssueId, task, subTasks, totalEstimatedMinutes, ctx, taskId, dailyLimit) {
149
+ const createdSubIssues = [];
150
+ for (const [index, subTask] of subTasks.entries()) {
151
+ const depsStr = subTask.dependencies?.length
152
+ ? `\n\n${t('runner.decomposition.prerequisite', { deps: subTask.dependencies.join(', ') })}`
153
+ : '';
154
+ const fileScope = (subTask.fileScope ?? []).filter((f) => typeof f === 'string' && f.trim().length > 0);
155
+ const scopeStr = fileScope.length
156
+ ? `\n\nFile scope: ${fileScope.join(', ')}`
157
+ : '';
158
+ const subDescription = `${subTask.description}\n\n` +
159
+ `${t('runner.decomposition.estimatedTime', { n: String(subTask.estimatedMinutes) })}${depsStr}${scopeStr}\n\n` +
160
+ t('runner.decomposition.autoDecomposed', { parentTitle: task.title });
161
+ const subResult = taskSource
162
+ ? await taskSource.createSubIssue(parentIssueId, subTask.title, subDescription, {
163
+ priority: subTask.priority,
164
+ projectId: task.linearProject?.id,
165
+ estimatedMinutes: subTask.estimatedMinutes,
166
+ })
167
+ : { error: 'No task source registered' };
168
+ if ('error' in subResult) {
169
+ console.error(`[AutonomousRunner] Failed to create sub-issue: ${subResult.error}`);
170
+ continue;
171
+ }
172
+ createdSubIssues.push({
173
+ id: subResult.id,
174
+ identifier: subResult.identifier,
175
+ title: subResult.title,
176
+ dependencies: subTask.dependencies || [],
177
+ topoRank: index,
178
+ estimatedMinutes: subTask.estimatedMinutes,
179
+ fileScope,
180
+ });
181
+ console.log(`[AutonomousRunner] Created sub-issue: ${subResult.identifier}`);
182
+ }
183
+ if (createdSubIssues.length === 0) {
184
+ console.error('[AutonomousRunner] No sub-issues created');
185
+ broadcastEvent({ type: 'pipeline:stage', data: { taskId, stage: 'decompose', status: 'fail' } });
186
+ return false;
187
+ }
188
+ // Register decomposition in tracking (for limits)
189
+ registerDecomposition(parentIssueId, task.parentId, // Parent ID if this task is also a sub-issue
190
+ createdSubIssues.map(s => s.id));
191
+ console.log(`[AutonomousRunner] Registered decomposition: parent=${parentIssueId}, children=${createdSubIssues.length}, daily=${getDailyCreationCount()}/${dailyLimit}`);
192
+ await taskSource?.markAsDecomposed(parentIssueId, createdSubIssues.length, totalEstimatedMinutes);
193
+ const childIdByTitle = new Map(createdSubIssues.map((subIssue) => [subIssue.title, subIssue.id]));
194
+ const parentState = markTaskDecomposed(parentIssueId, {
195
+ issueIdentifier: task.issueIdentifier,
196
+ title: task.title,
197
+ projectId: task.linearProject?.id,
198
+ projectName: task.linearProject?.name,
199
+ parentIssueId: task.parentId,
200
+ childIssueIds: createdSubIssues.map((subIssue) => subIssue.id),
201
+ });
202
+ await taskSource?.addComment(parentIssueId, buildTaskStateSyncComment(parentState, 'Parent task decomposed'));
203
+ const subIssueList = createdSubIssues
204
+ .map((s, i) => `${i + 1}. ${s.identifier}: ${s.title}`)
205
+ .join('\n');
206
+ await ctx.reportToDiscord(t('runner.decomposition.completed', {
207
+ original: task.issueIdentifier || parentIssueId || '',
208
+ count: String(createdSubIssues.length),
209
+ list: subIssueList,
210
+ totalMinutes: String(totalEstimatedMinutes),
211
+ }));
212
+ broadcastEvent({ type: 'pipeline:stage', data: { taskId, stage: 'decompose', status: 'complete' } });
213
+ // Log each sub-issue as a log line for the dashboard
214
+ for (const s of createdSubIssues) {
215
+ broadcastEvent({ type: 'log', data: { taskId, stage: 'decompose', line: `↳ ${s.identifier}: ${s.title}` } });
216
+ }
217
+ console.log(`[AutonomousRunner] Decomposition complete: ${createdSubIssues.length} sub-issues created`);
218
+ for (const subIssue of createdSubIssues) {
219
+ const dependencyIssueIds = subIssue.dependencies
220
+ .map((title) => childIdByTitle.get(title))
221
+ .filter((value) => Boolean(value));
222
+ const isReady = dependencyIssueIds.length === 0;
223
+ const childState = upsertTaskState(subIssue.id, {
224
+ issueIdentifier: subIssue.identifier,
225
+ title: subIssue.title,
226
+ projectId: task.linearProject?.id,
227
+ projectName: task.linearProject?.name,
228
+ parentIssueId: parentIssueId,
229
+ dependencyIssueIds,
230
+ dependencyTitles: subIssue.dependencies,
231
+ fileScope: subIssue.fileScope,
232
+ topoRank: subIssue.topoRank,
233
+ execution: {
234
+ status: isReady ? 'todo' : 'blocked',
235
+ blockedReason: isReady ? undefined : `Waiting on dependencies: ${dependencyIssueIds.join(', ')}`,
236
+ retryCount: 0,
237
+ },
238
+ linearState: isReady ? 'Todo' : 'Backlog',
239
+ });
240
+ try {
241
+ if (isReady) {
242
+ await taskSource?.updateState(subIssue.id, 'Todo');
243
+ console.log(`[AutonomousRunner] Moved ${subIssue.identifier} to Todo`);
244
+ }
245
+ else {
246
+ console.log(`[AutonomousRunner] Keeping ${subIssue.identifier} in Backlog until dependencies resolve`);
247
+ }
248
+ await taskSource?.addComment(subIssue.id, buildTaskStateSyncComment(childState, isReady ? 'Task ready after decomposition' : 'Task blocked by decomposition dependency'));
249
+ }
250
+ catch (err) {
251
+ console.warn(`[AutonomousRunner] Failed to initialize ${subIssue.identifier} state:`, err);
252
+ }
253
+ }
254
+ // Trigger immediate heartbeat to pick up newly created sub-issues
255
+ if (ctx.scheduleNextHeartbeat) {
256
+ console.log('[AutonomousRunner] Scheduling immediate heartbeat to process sub-issues...');
257
+ ctx.scheduleNextHeartbeat();
258
+ }
259
+ return true;
260
+ }
144
261
  export async function decomposeTask(ctx, task, projectPath, targetMinutes, draftAnalysis) {
145
262
  console.log(`[AutonomousRunner] Decomposing task: ${task.title}`);
146
263
  const taskId = task.issueId || task.id;
@@ -158,8 +275,8 @@ export async function decomposeTask(ctx, task, projectPath, targetMinutes, draft
158
275
  console.log(`[AutonomousRunner] Decomposition depth limit reached: ${currentDepth}/${maxDepth}`);
159
276
  if (autoBacklog && task.issueId) {
160
277
  try {
161
- await linear.updateIssueState(task.issueId, 'Backlog');
162
- await linear.addComment(task.issueId, `⚠️ **Auto-moved to Backlog**\n\n` +
278
+ await taskSource?.updateState(task.issueId, 'Backlog');
279
+ await taskSource?.addComment(task.issueId, `⚠️ **Auto-moved to Backlog**\n\n` +
163
280
  `Reason: Decomposition depth limit reached (${currentDepth}/${maxDepth})\n\n` +
164
281
  `This task has been nested too deeply. Please review and simplify the task structure, ` +
165
282
  `or handle it manually.`);
@@ -177,8 +294,8 @@ export async function decomposeTask(ctx, task, projectPath, targetMinutes, draft
177
294
  console.log(`[AutonomousRunner] Children count limit reached: ${childrenCount}/${maxChildren}`);
178
295
  if (autoBacklog) {
179
296
  try {
180
- await linear.updateIssueState(task.issueId, 'Backlog');
181
- await linear.addComment(task.issueId, `⚠️ **Auto-moved to Backlog**\n\n` +
297
+ await taskSource?.updateState(task.issueId, 'Backlog');
298
+ await taskSource?.addComment(task.issueId, `⚠️ **Auto-moved to Backlog**\n\n` +
182
299
  `Reason: Too many sub-issues already created (${childrenCount}/${maxChildren})\n\n` +
183
300
  `This task has generated too many sub-issues. Please review the decomposition strategy, ` +
184
301
  `or handle it manually.`);
@@ -223,7 +340,9 @@ export async function decomposeTask(ctx, task, projectPath, targetMinutes, draft
223
340
  projectPath,
224
341
  projectName: task.linearProject?.name,
225
342
  targetMinutes,
226
- model: ctx.plannerModel ?? 'claude-opus-4-7',
343
+ // Planner runs through the configured adapter loop now (not claude -p);
344
+ // leave model unset to use the adapter default when no planner model is configured.
345
+ model: ctx.plannerModel,
227
346
  timeoutMs: ctx.plannerTimeoutMs ?? 600000,
228
347
  onLog: (line) => broadcastEvent({ type: 'log', data: { taskId, stage: 'decompose', line } }),
229
348
  impactAnalysis: impactAnalysis ?? undefined,
@@ -253,109 +372,7 @@ export async function decomposeTask(ctx, task, projectPath, targetMinutes, draft
253
372
  console.error('[AutonomousRunner] Cannot create sub-issues: no parent issueId');
254
373
  return false;
255
374
  }
256
- const createdSubIssues = [];
257
- for (const [index, subTask] of result.subTasks.entries()) {
258
- const depsStr = subTask.dependencies?.length
259
- ? `\n\n${t('runner.decomposition.prerequisite', { deps: subTask.dependencies.join(', ') })}`
260
- : '';
261
- const subDescription = `${subTask.description}\n\n` +
262
- `${t('runner.decomposition.estimatedTime', { n: String(subTask.estimatedMinutes) })}${depsStr}\n\n` +
263
- t('runner.decomposition.autoDecomposed', { parentTitle: task.title });
264
- const subResult = await linear.createSubIssue(task.issueId, subTask.title, subDescription, {
265
- priority: subTask.priority,
266
- projectId: task.linearProject?.id,
267
- estimatedMinutes: subTask.estimatedMinutes,
268
- });
269
- if ('error' in subResult) {
270
- console.error(`[AutonomousRunner] Failed to create sub-issue: ${subResult.error}`);
271
- continue;
272
- }
273
- createdSubIssues.push({
274
- id: subResult.id,
275
- identifier: subResult.identifier,
276
- title: subResult.title,
277
- dependencies: subTask.dependencies || [],
278
- topoRank: index,
279
- estimatedMinutes: subTask.estimatedMinutes,
280
- });
281
- console.log(`[AutonomousRunner] Created sub-issue: ${subResult.identifier}`);
282
- }
283
- if (createdSubIssues.length === 0) {
284
- console.error('[AutonomousRunner] No sub-issues created');
285
- broadcastEvent({ type: 'pipeline:stage', data: { taskId, stage: 'decompose', status: 'fail' } });
286
- return false;
287
- }
288
- // Register decomposition in tracking (for limits)
289
- registerDecomposition(task.issueId, task.parentId, // Parent ID if this task is also a sub-issue
290
- createdSubIssues.map(s => s.id));
291
- console.log(`[AutonomousRunner] Registered decomposition: parent=${task.issueId}, children=${createdSubIssues.length}, daily=${getDailyCreationCount()}/${dailyLimit}`);
292
- await linear.markAsDecomposed(task.issueId, createdSubIssues.length, result.totalEstimatedMinutes);
293
- const childIdByTitle = new Map(createdSubIssues.map((subIssue) => [subIssue.title, subIssue.id]));
294
- const parentState = markTaskDecomposed(task.issueId, {
295
- issueIdentifier: task.issueIdentifier,
296
- title: task.title,
297
- projectId: task.linearProject?.id,
298
- projectName: task.linearProject?.name,
299
- parentIssueId: task.parentId,
300
- childIssueIds: createdSubIssues.map((subIssue) => subIssue.id),
301
- });
302
- await linear.addComment(task.issueId, buildTaskStateSyncComment(parentState, 'Parent task decomposed'));
303
- const subIssueList = createdSubIssues
304
- .map((s, i) => `${i + 1}. ${s.identifier}: ${s.title}`)
305
- .join('\n');
306
- await ctx.reportToDiscord(t('runner.decomposition.completed', {
307
- original: task.issueIdentifier || task.issueId || '',
308
- count: String(createdSubIssues.length),
309
- list: subIssueList,
310
- totalMinutes: String(result.totalEstimatedMinutes),
311
- }));
312
- broadcastEvent({ type: 'pipeline:stage', data: { taskId, stage: 'decompose', status: 'complete' } });
313
- // Log each sub-issue as a log line for the dashboard
314
- for (const s of createdSubIssues) {
315
- broadcastEvent({ type: 'log', data: { taskId, stage: 'decompose', line: `↳ ${s.identifier}: ${s.title}` } });
316
- }
317
- console.log(`[AutonomousRunner] Decomposition complete: ${createdSubIssues.length} sub-issues created`);
318
- for (const subIssue of createdSubIssues) {
319
- const dependencyIssueIds = subIssue.dependencies
320
- .map((title) => childIdByTitle.get(title))
321
- .filter((value) => Boolean(value));
322
- const isReady = dependencyIssueIds.length === 0;
323
- const childState = upsertTaskState(subIssue.id, {
324
- issueIdentifier: subIssue.identifier,
325
- title: subIssue.title,
326
- projectId: task.linearProject?.id,
327
- projectName: task.linearProject?.name,
328
- parentIssueId: task.issueId,
329
- dependencyIssueIds,
330
- dependencyTitles: subIssue.dependencies,
331
- topoRank: subIssue.topoRank,
332
- execution: {
333
- status: isReady ? 'todo' : 'blocked',
334
- blockedReason: isReady ? undefined : `Waiting on dependencies: ${dependencyIssueIds.join(', ')}`,
335
- retryCount: 0,
336
- },
337
- linearState: isReady ? 'Todo' : 'Backlog',
338
- });
339
- try {
340
- if (isReady) {
341
- await linear.updateIssueState(subIssue.id, 'Todo');
342
- console.log(`[AutonomousRunner] Moved ${subIssue.identifier} to Todo`);
343
- }
344
- else {
345
- console.log(`[AutonomousRunner] Keeping ${subIssue.identifier} in Backlog until dependencies resolve`);
346
- }
347
- await linear.addComment(subIssue.id, buildTaskStateSyncComment(childState, isReady ? 'Task ready after decomposition' : 'Task blocked by decomposition dependency'));
348
- }
349
- catch (err) {
350
- console.warn(`[AutonomousRunner] Failed to initialize ${subIssue.identifier} state:`, err);
351
- }
352
- }
353
- // Trigger immediate heartbeat to pick up newly created sub-issues
354
- if (ctx.scheduleNextHeartbeat) {
355
- console.log('[AutonomousRunner] Scheduling immediate heartbeat to process sub-issues...');
356
- ctx.scheduleNextHeartbeat();
357
- }
358
- return true;
375
+ return createSubIssuesWithDependencies(task.issueId, task, result.subTasks, result.totalEstimatedMinutes, ctx, taskId, dailyLimit);
359
376
  }
360
377
  // Pipeline Execution
361
378
  export async function executePipeline(ctx, task, projectPath) {
@@ -446,19 +463,50 @@ export async function executePipeline(ctx, task, projectPath) {
446
463
  projectStats: draftResult.projectStats,
447
464
  impactAnalysis: draftResult.impactAnalysis,
448
465
  registrySnapshot: draftResult.registrySnapshot,
449
- } : undefined);
466
+ } : undefined, ctx.maxReflections);
450
467
  const taskPrefix = buildTaskPrefix(task, actualPath);
451
- pipeline.on('stage:start', ({ stage }) => {
468
+ pipeline.on('stage:start', ({ stage, context, model }) => {
452
469
  console.log(`[${taskPrefix}] Stage started: ${stage}`);
470
+ // Audit trail: comment the worker instruction (prompt summary, target
471
+ // files, model/effort) on each worker run. Non-blocking — fire & forget.
472
+ if (stage === 'worker' && task.issueId) {
473
+ const draft = context?.config?.draftAnalysis;
474
+ const body = buildWorkerStartComment({
475
+ attempt: context?.currentIteration ?? 1,
476
+ maxAttempts: ctx.pairMaxAttempts ?? 3,
477
+ taskTitle: task.title,
478
+ taskGoal: draft?.intentSummary || task.description,
479
+ targetFiles: draft?.relevantFiles,
480
+ model: model || context?.config?.roles?.worker?.model,
481
+ maxTurns: context?.config?.roles?.worker?.maxTurns,
482
+ isRevision: (context?.currentIteration ?? 1) > 1,
483
+ });
484
+ void taskSource?.addComment(task.issueId, body).catch((err) => console.error(`[${taskPrefix}] Worker start audit comment failed:`, err));
485
+ }
453
486
  });
454
487
  const taskReportCtx = {
455
488
  issueIdentifier: task.issueIdentifier || task.issueId,
456
489
  projectName: task.linearProject?.name,
457
490
  projectPath: actualPath,
458
491
  };
459
- pipeline.on('stage:complete', async ({ stage, result }) => {
492
+ pipeline.on('stage:complete', async ({ stage, result, context }) => {
460
493
  console.log(`[${taskPrefix}] Stage completed: ${stage}, success=${result.success}`);
461
494
  await reportStageResult(stage, result, ctx.reportToDiscord, taskReportCtx);
495
+ // Audit trail: comment the actions taken (files changed, commands run,
496
+ // confidence, halt reason) on each worker run.
497
+ if (stage === 'worker' && task.issueId) {
498
+ try {
499
+ await taskSource?.addComment(task.issueId, buildWorkerCompleteComment({
500
+ attempt: context?.currentIteration ?? 1,
501
+ maxAttempts: ctx.pairMaxAttempts ?? 3,
502
+ result: result.result,
503
+ durationSec: Math.floor((result.duration ?? 0) / 1000),
504
+ }));
505
+ }
506
+ catch (err) {
507
+ console.error(`[${taskPrefix}] Worker complete audit comment failed:`, err);
508
+ }
509
+ }
462
510
  });
463
511
  pipeline.on('revision:start', ({ stage }) => {
464
512
  void ctx.reportToDiscord(t('runner.pipeline.revisionNeeded', { stage }));
@@ -469,7 +517,7 @@ export async function executePipeline(ctx, task, projectPath) {
469
517
  // Report to Linear
470
518
  if (task.issueId && ctx.guards?.haltToLinear) {
471
519
  try {
472
- await linear.logHalt(task.issueId, sessionId, confidence, iteration, haltReason);
520
+ await taskSource?.logHalt(task.issueId, sessionId, confidence, iteration, haltReason);
473
521
  }
474
522
  catch (err) {
475
523
  console.error(`[${taskPrefix}] Linear logHalt failed:`, err);
@@ -507,13 +555,13 @@ export async function executePipeline(ctx, task, projectPath) {
507
555
  branchName: worktreeInfo?.branchName,
508
556
  worktreePath: actualPath,
509
557
  });
510
- await linear.logPairStart(task.issueId, sessionId, projectPath);
511
- await linear.addComment(task.issueId, buildTaskStateSyncComment(inProgressState, 'Task execution started'));
558
+ await taskSource?.logPairStart(task.issueId, sessionId, projectPath);
559
+ await taskSource?.addComment(task.issueId, buildTaskStateSyncComment(inProgressState, 'Task execution started'));
512
560
  }
513
561
  catch (err) {
514
562
  console.error(`[${taskPrefix}] Linear logPairStart failed:`, err);
515
563
  // Continue pipeline even if this fails
516
- await linear.updateIssueState(task.issueId, 'In Progress');
564
+ await taskSource?.updateState(task.issueId, 'In Progress');
517
565
  }
518
566
  }
519
567
  // Run pipeline in worktree path
@@ -657,8 +705,8 @@ export async function reconcileCompletionState(task) {
657
705
  const released = releaseDependentTasks(task.issueId);
658
706
  for (const child of released) {
659
707
  try {
660
- await linear.updateIssueState(child.issueId, 'Todo');
661
- await linear.addComment(child.issueId, buildTaskStateSyncComment(child, 'Task unblocked and ready'));
708
+ await taskSource?.updateState(child.issueId, 'Todo');
709
+ await taskSource?.addComment(child.issueId, buildTaskStateSyncComment(child, 'Task unblocked and ready'));
662
710
  }
663
711
  catch (err) {
664
712
  console.warn(`[AutonomousRunner] Failed to release dependent task ${child.issueId}:`, err);
@@ -668,8 +716,8 @@ export async function reconcileCompletionState(task) {
668
716
  if (!parent)
669
717
  return;
670
718
  try {
671
- await linear.updateIssueState(parent.issueId, 'Done');
672
- await linear.addComment(parent.issueId, buildTaskStateSyncComment(parent, 'All child tasks completed'));
719
+ await taskSource?.updateState(parent.issueId, 'Done');
720
+ await taskSource?.addComment(parent.issueId, buildTaskStateSyncComment(parent, 'All child tasks completed'));
673
721
  }
674
722
  catch (err) {
675
723
  console.warn(`[AutonomousRunner] Failed to complete parent task ${parent.issueId}:`, err);
@@ -680,7 +728,7 @@ export async function syncFailureState(task, reason) {
680
728
  return;
681
729
  const state = markTaskBlocked(task.issueId, reason, task.blockedBy || [], task.linearState);
682
730
  try {
683
- await linear.addComment(task.issueId, buildTaskStateSyncComment(state, 'Task blocked'));
731
+ await taskSource?.addComment(task.issueId, buildTaskStateSyncComment(state, 'Task blocked'));
684
732
  }
685
733
  catch (err) {
686
734
  console.warn(`[AutonomousRunner] Failed to sync blocked state for ${task.issueId}:`, err);
@@ -695,7 +743,7 @@ export async function syncSuccessState(task, confidence) {
695
743
  confidence,
696
744
  });
697
745
  try {
698
- await linear.addComment(task.issueId, buildTaskStateSyncComment(state, 'Task completed'));
746
+ await taskSource?.addComment(task.issueId, buildTaskStateSyncComment(state, 'Task completed'));
699
747
  }
700
748
  catch (err) {
701
749
  console.warn(`[AutonomousRunner] Failed to sync success state for ${task.issueId}:`, err);