@backburner/cli 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 (202) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +329 -0
  3. package/dist/src/agents/antigravity-launch.js +162 -0
  4. package/dist/src/agents/antigravity.js +251 -0
  5. package/dist/src/agents/claude-launch.js +117 -0
  6. package/dist/src/agents/claude.js +271 -0
  7. package/dist/src/agents/codex-launch.js +82 -0
  8. package/dist/src/agents/codex.js +261 -0
  9. package/dist/src/agents/composite-runner.js +13 -0
  10. package/dist/src/agents/extraction.js +442 -0
  11. package/dist/src/agents/failure-feedback.js +132 -0
  12. package/dist/src/agents/gemini-launch.js +96 -0
  13. package/dist/src/agents/gemini.js +392 -0
  14. package/dist/src/agents/job-agent-assignments.js +180 -0
  15. package/dist/src/agents/lifecycle-feedback.js +147 -0
  16. package/dist/src/agents/limit-detector.js +83 -0
  17. package/dist/src/agents/opencode-launch.js +138 -0
  18. package/dist/src/agents/opencode.js +156 -0
  19. package/dist/src/agents/plan-breakdown-feedback.js +97 -0
  20. package/dist/src/agents/pool.js +168 -0
  21. package/dist/src/agents/prompt.js +462 -0
  22. package/dist/src/agents/provider-sessions.js +105 -0
  23. package/dist/src/agents/review-feedback.js +255 -0
  24. package/dist/src/agents/selection.js +113 -0
  25. package/dist/src/agents/service.js +1087 -0
  26. package/dist/src/agents/types.js +1 -0
  27. package/dist/src/agents/wave-assessment-feedback.js +69 -0
  28. package/dist/src/attention/derive.js +337 -0
  29. package/dist/src/capabilities/index.js +2 -0
  30. package/dist/src/capabilities/projection.js +183 -0
  31. package/dist/src/capabilities/types.js +1 -0
  32. package/dist/src/capabilities/validator.js +87 -0
  33. package/dist/src/cli/commands/broker-smoke.js +96 -0
  34. package/dist/src/cli/commands/broker.js +56 -0
  35. package/dist/src/cli/commands/init.js +4 -0
  36. package/dist/src/cli/commands/journal.js +43 -0
  37. package/dist/src/cli/commands/run-loop.js +56 -0
  38. package/dist/src/cli/commands/run.js +1241 -0
  39. package/dist/src/cli/commands/tui.js +187 -0
  40. package/dist/src/cli/dispatcher.js +51 -0
  41. package/dist/src/cli/errors.js +2 -0
  42. package/dist/src/cli/init.js +92 -0
  43. package/dist/src/cli/options.js +86 -0
  44. package/dist/src/cli/output.js +231 -0
  45. package/dist/src/cli/run-journal.js +342 -0
  46. package/dist/src/cli/run-types.js +1 -0
  47. package/dist/src/cli/run.js +32 -0
  48. package/dist/src/cli/runtime/dispatch-lifecycle.js +772 -0
  49. package/dist/src/cli/runtime/provider-runtime-types.js +1 -0
  50. package/dist/src/cli/runtime/provider-runtime.js +152 -0
  51. package/dist/src/cli/runtime/provider-tools.js +73 -0
  52. package/dist/src/cli/runtime/providers/antigravity.js +26 -0
  53. package/dist/src/cli/runtime/providers/claude.js +20 -0
  54. package/dist/src/cli/runtime/providers/codex.js +20 -0
  55. package/dist/src/cli/runtime/providers/gemini.js +20 -0
  56. package/dist/src/cli/runtime/providers/opencode.js +20 -0
  57. package/dist/src/cli/runtime/run-context.js +131 -0
  58. package/dist/src/cli/tui/index.js +3 -0
  59. package/dist/src/cli/tui/screen.js +388 -0
  60. package/dist/src/cli/tui/tracker.js +558 -0
  61. package/dist/src/cli/tui/types.js +1 -0
  62. package/dist/src/cli/tui/views.js +1006 -0
  63. package/dist/src/config/loader.js +136 -0
  64. package/dist/src/config/schemas.js +403 -0
  65. package/dist/src/config/types.js +1 -0
  66. package/dist/src/context/types.js +331 -0
  67. package/dist/src/domain/entities.js +1 -0
  68. package/dist/src/git/backburner-git-tool-service.js +680 -0
  69. package/dist/src/git/gitops-lifecycle.js +56 -0
  70. package/dist/src/git/merge-prep-workspace.js +357 -0
  71. package/dist/src/git/types.js +484 -0
  72. package/dist/src/github/broker-model-content.js +215 -0
  73. package/dist/src/github/broker-server.js +237 -0
  74. package/dist/src/github/broker.js +638 -0
  75. package/dist/src/github/composed.js +53 -0
  76. package/dist/src/github/gateway.js +478 -0
  77. package/dist/src/github/normalize.js +222 -0
  78. package/dist/src/github/pr-classification.js +73 -0
  79. package/dist/src/github/scoped-broker.js +35 -0
  80. package/dist/src/github/security.js +126 -0
  81. package/dist/src/github/service.js +332 -0
  82. package/dist/src/github/types.js +1 -0
  83. package/dist/src/github/utils.js +16 -0
  84. package/dist/src/journal/index.js +4 -0
  85. package/dist/src/journal/reader.js +62 -0
  86. package/dist/src/journal/renderer.js +50 -0
  87. package/dist/src/journal/service.js +72 -0
  88. package/dist/src/journal/types.js +1 -0
  89. package/dist/src/journal/writer.js +19 -0
  90. package/dist/src/mcps/bridge.js +166 -0
  91. package/dist/src/mcps/index.js +5 -0
  92. package/dist/src/mcps/reconcile.js +113 -0
  93. package/dist/src/mcps/smithery-client.js +186 -0
  94. package/dist/src/mcps/smithery.js +164 -0
  95. package/dist/src/mcps/types.js +1 -0
  96. package/dist/src/memory/json-store.js +71 -0
  97. package/dist/src/memory/prompt.js +16 -0
  98. package/dist/src/memory/scope.js +31 -0
  99. package/dist/src/memory/store.js +1 -0
  100. package/dist/src/memory/tool-service.js +142 -0
  101. package/dist/src/memory/types.js +12 -0
  102. package/dist/src/onboarding/config-writer.js +96 -0
  103. package/dist/src/onboarding/engine.js +86 -0
  104. package/dist/src/onboarding/prompt.js +102 -0
  105. package/dist/src/onboarding/services/provider-discovery.js +58 -0
  106. package/dist/src/onboarding/services/repo-discovery.js +246 -0
  107. package/dist/src/onboarding/steps/check-github-auth.js +32 -0
  108. package/dist/src/onboarding/steps/check-requirements.js +34 -0
  109. package/dist/src/onboarding/steps/configure-models.js +105 -0
  110. package/dist/src/onboarding/steps/configure-paths.js +33 -0
  111. package/dist/src/onboarding/steps/discover-providers.js +38 -0
  112. package/dist/src/onboarding/steps/discover-repos.js +39 -0
  113. package/dist/src/onboarding/steps/generate-config.js +106 -0
  114. package/dist/src/onboarding/steps/readiness-validation.js +158 -0
  115. package/dist/src/onboarding/steps/select-repos.js +76 -0
  116. package/dist/src/onboarding/steps/show-summary.js +97 -0
  117. package/dist/src/onboarding/steps/welcome.js +27 -0
  118. package/dist/src/onboarding/types.js +1 -0
  119. package/dist/src/onboarding/validators/git-access.js +63 -0
  120. package/dist/src/onboarding/validators/github-auth.js +85 -0
  121. package/dist/src/onboarding/validators/tool-checker.js +153 -0
  122. package/dist/src/onboarding/validators/workspace.js +83 -0
  123. package/dist/src/prompts/resolver.js +106 -0
  124. package/dist/src/retrospectives/candidates.js +224 -0
  125. package/dist/src/retrospectives/derive.js +169 -0
  126. package/dist/src/retrospectives/ingest.js +321 -0
  127. package/dist/src/retrospectives/management-prs.js +380 -0
  128. package/dist/src/retrospectives/proposals.js +199 -0
  129. package/dist/src/retrospectives/scopes.js +272 -0
  130. package/dist/src/retrospectives/scoring.js +171 -0
  131. package/dist/src/retrospectives/types.js +1 -0
  132. package/dist/src/state/loader.js +473 -0
  133. package/dist/src/state/types.js +15 -0
  134. package/dist/src/tasks/derivation/builders.js +70 -0
  135. package/dist/src/tasks/derivation/handlers/comment-response.js +169 -0
  136. package/dist/src/tasks/derivation/handlers/implement-plan.js +103 -0
  137. package/dist/src/tasks/derivation/handlers/index.js +54 -0
  138. package/dist/src/tasks/derivation/handlers/packet-pr-control.js +92 -0
  139. package/dist/src/tasks/derivation/handlers/packet-worktree.js +29 -0
  140. package/dist/src/tasks/derivation/handlers/plan-breakdown.js +45 -0
  141. package/dist/src/tasks/derivation/handlers/prepare-for-merge.js +91 -0
  142. package/dist/src/tasks/derivation/handlers/product-discovery.js +36 -0
  143. package/dist/src/tasks/derivation/handlers/retry-failed-task.js +125 -0
  144. package/dist/src/tasks/derivation/handlers/review-pr.js +28 -0
  145. package/dist/src/tasks/derivation/handlers/shared.js +24 -0
  146. package/dist/src/tasks/derivation/handlers/sync-parent-branch.js +100 -0
  147. package/dist/src/tasks/derivation/handlers/wave-assessment.js +223 -0
  148. package/dist/src/tasks/derivation/handlers/write-plan.js +101 -0
  149. package/dist/src/tasks/derivation/handlers/write-product-spec.js +49 -0
  150. package/dist/src/tasks/derivation/runner.js +18 -0
  151. package/dist/src/tasks/derivation/types.js +1 -0
  152. package/dist/src/tasks/derive.js +810 -0
  153. package/dist/src/tasks/mcp-skip.js +10 -0
  154. package/dist/src/tasks/retry.js +10 -0
  155. package/dist/src/tasks/task.js +184 -0
  156. package/dist/src/tasks/types.js +1 -0
  157. package/dist/src/utils/command-runner.js +192 -0
  158. package/dist/src/utils/json.js +38 -0
  159. package/dist/src/utils/logger.js +43 -0
  160. package/dist/src/utils/paths.js +38 -0
  161. package/dist/src/utils/slug.js +10 -0
  162. package/dist/src/workflows/registry.js +174 -0
  163. package/dist/src/workflows/triage.js +90 -0
  164. package/dist/src/workflows/workstream-machine/derive-events.js +121 -0
  165. package/dist/src/workflows/workstream-machine/evaluate.js +24 -0
  166. package/dist/src/workflows/workstream-machine/events.js +1 -0
  167. package/dist/src/workflows/workstream-machine/machine.js +355 -0
  168. package/dist/src/workflows/workstream-machine/selectors.js +19 -0
  169. package/dist/src/workflows/workstream-machine/types.js +1 -0
  170. package/dist/src/workstreams/branch-sync.js +87 -0
  171. package/dist/src/workstreams/derive.js +629 -0
  172. package/dist/src/workstreams/mcp-blockers.js +420 -0
  173. package/dist/src/workstreams/packet-candidates.js +42 -0
  174. package/dist/src/workstreams/packet-lifecycle-feedback.js +60 -0
  175. package/dist/src/workstreams/packet-lifecycle-report.js +199 -0
  176. package/dist/src/workstreams/packet-plan.js +597 -0
  177. package/dist/src/workstreams/packet-projections.js +190 -0
  178. package/dist/src/workstreams/parent-branch-sync-action.js +312 -0
  179. package/dist/src/workstreams/parent-branch-sync.js +148 -0
  180. package/dist/src/workstreams/phases.js +4 -0
  181. package/dist/src/workstreams/plan-breakdown-generator/export.js +19 -0
  182. package/dist/src/workstreams/plan-breakdown-generator/index.js +6 -0
  183. package/dist/src/workstreams/plan-breakdown-generator/inspect.js +50 -0
  184. package/dist/src/workstreams/plan-breakdown-generator/patch.js +139 -0
  185. package/dist/src/workstreams/plan-breakdown-generator/session.js +19 -0
  186. package/dist/src/workstreams/plan-breakdown-generator/store.js +27 -0
  187. package/dist/src/workstreams/plan-breakdown-generator/tools.js +407 -0
  188. package/dist/src/workstreams/plan-breakdown-generator/types.js +6 -0
  189. package/dist/src/workstreams/plan-breakdown-generator/validate.js +212 -0
  190. package/dist/src/workstreams/plan-breakdown-schema.js +175 -0
  191. package/dist/src/workstreams/utils.js +15 -0
  192. package/dist/src/workstreams/wave-assessment/checkpoint.js +172 -0
  193. package/dist/src/workstreams/wave-assessment/index.js +3 -0
  194. package/dist/src/workstreams/wave-assessment/session.js +84 -0
  195. package/dist/src/workstreams/wave-assessment/store.js +51 -0
  196. package/dist/src/workstreams/wave-assessment/tools.js +419 -0
  197. package/dist/src/workstreams/wave-assessment/types.js +1 -0
  198. package/dist/src/workstreams/wave-assessment/validate.js +78 -0
  199. package/dist/src/worktrees/service.js +839 -0
  200. package/dist/src/worktrees/workspace-ownership.js +34 -0
  201. package/dist/src/worktrees/workspace-recovery.js +177 -0
  202. package/package.json +61 -0
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,152 @@
1
+ import * as path from "node:path";
2
+ import { CodexCliAgent } from "../../agents/codex.js";
3
+ import { CompositeAgentRunner } from "../../agents/composite-runner.js";
4
+ import { GitHubBrokerService } from "../../github/broker.js";
5
+ import { ComposedBrokerService } from "../../github/composed.js";
6
+ import { ScopedBrokerToolService } from "../../github/scoped-broker.js";
7
+ import { createSmitheryMcpBridgeServicesFromStatuses } from "../../mcps/index.js";
8
+ import { createTeeFileLogger } from "../../utils/logger.js";
9
+ import { PlanBreakdownSessionStore } from "../../workstreams/plan-breakdown-generator/store.js";
10
+ import { PlanBreakdownToolService } from "../../workstreams/plan-breakdown-generator/tools.js";
11
+ import { WaveAssessmentSessionStore } from "../../workstreams/wave-assessment/store.js";
12
+ import { WaveAssessmentToolService } from "../../workstreams/wave-assessment/tools.js";
13
+ import { antigravityRuntimeProvider } from "./providers/antigravity.js";
14
+ import { claudeRuntimeProvider } from "./providers/claude.js";
15
+ import { codexRuntimeProvider } from "./providers/codex.js";
16
+ import { geminiRuntimeProvider } from "./providers/gemini.js";
17
+ import { openCodeRuntimeProvider } from "./providers/opencode.js";
18
+ import { buildCapabilitiesByProvider, buildEffectiveProviderBrokerToolAllowLists } from "./provider-tools.js";
19
+ const providerRuntimeDescriptors = [
20
+ codexRuntimeProvider,
21
+ geminiRuntimeProvider,
22
+ claudeRuntimeProvider,
23
+ openCodeRuntimeProvider,
24
+ antigravityRuntimeProvider
25
+ ];
26
+ export async function setupProviderRuntime(input) {
27
+ let brokerServer;
28
+ let brokerLogger;
29
+ try {
30
+ let agentRunner = input.agentRunner;
31
+ let capabilitiesByProvider;
32
+ let providerBrokerToolAllowLists;
33
+ let brokerToolScope;
34
+ const enabledProviderDescriptors = providerRuntimeDescriptors.filter((descriptor) => descriptor.isEnabled(input.config));
35
+ if (!agentRunner && enabledProviderDescriptors.length > 0) {
36
+ const brokerToolUnion = new Set();
37
+ for (const descriptor of enabledProviderDescriptors) {
38
+ descriptor.toolAllowList(input.config).forEach((toolName) => brokerToolUnion.add(toolName));
39
+ }
40
+ brokerLogger = createTeeFileLogger(input.logger, path.join(input.logDir, "github-broker.log"));
41
+ const githubBrokerService = new GitHubBrokerService(input.gitHubGateway, input.config.repos, brokerLogger, Array.from(brokerToolUnion));
42
+ const planBreakdownSessionStore = new PlanBreakdownSessionStore(input.logDir);
43
+ const planBreakdownToolService = new PlanBreakdownToolService(planBreakdownSessionStore, input.logger);
44
+ const waveAssessmentSessionStore = new WaveAssessmentSessionStore(input.logDir);
45
+ const waveAssessmentToolService = new WaveAssessmentToolService(waveAssessmentSessionStore, input.logger);
46
+ let smitheryBridgeServices = [];
47
+ try {
48
+ smitheryBridgeServices = await createSmitheryMcpBridgeServicesFromStatuses(input.currentMcpStatuses, { apiKey: process.env.SMITHERY_API_KEY }, undefined, Array.from(brokerToolUnion));
49
+ }
50
+ catch (err) {
51
+ input.logger.warn(`Failed to initialize Smithery MCP bridge tools: ${err instanceof Error ? err.message : String(err)}`);
52
+ }
53
+ const brokerService = new ComposedBrokerService([
54
+ githubBrokerService,
55
+ ...smitheryBridgeServices,
56
+ planBreakdownToolService,
57
+ waveAssessmentToolService,
58
+ input.memoryToolService,
59
+ input.backburnerGitToolService
60
+ ]);
61
+ brokerToolScope = new ScopedBrokerToolService(brokerService);
62
+ brokerServer = await input.startBrokerServer({
63
+ brokerService: brokerToolScope,
64
+ host: "127.0.0.1",
65
+ port: input.brokerPort,
66
+ logger: brokerLogger
67
+ });
68
+ const composite = new CompositeAgentRunner();
69
+ const planBreakdownTools = [
70
+ "plan_breakdown.start_session",
71
+ "plan_breakdown.apply_patch",
72
+ "plan_breakdown.inspect_session",
73
+ "plan_breakdown.validate_session",
74
+ "plan_breakdown.export_session"
75
+ ];
76
+ const memoryTools = ["memory_search", "memory_add"];
77
+ const waveAssessmentTools = [
78
+ "wave_assessment.start_session",
79
+ "wave_assessment.add_finding",
80
+ "wave_assessment.complete_session",
81
+ "wave_assessment.export_session"
82
+ ];
83
+ const backburnerGitTools = input.backburnerGitToolService.listTools().map((tool) => tool.name);
84
+ const extraTools = [...planBreakdownTools, ...waveAssessmentTools, ...memoryTools, ...backburnerGitTools];
85
+ const providerBrokerToolAllowListsForRun = new Map();
86
+ for (const descriptor of enabledProviderDescriptors) {
87
+ providerBrokerToolAllowListsForRun.set(descriptor.provider, [
88
+ ...descriptor.toolAllowList(input.config),
89
+ ...extraTools
90
+ ]);
91
+ }
92
+ const registeredPublicBrokerToolNames = brokerService.listTools().map((tool) => tool.name);
93
+ capabilitiesByProvider = buildCapabilitiesByProvider({
94
+ capabilities: input.config.capabilities,
95
+ mcps: input.config.mcps,
96
+ mcpStatuses: input.currentMcpStatuses,
97
+ enabledAgents: input.config.agents.filter((agent) => agent.enabled),
98
+ providerBrokerToolAllowLists: providerBrokerToolAllowListsForRun,
99
+ registeredPublicBrokerToolNames
100
+ });
101
+ const effectiveProviderBrokerToolAllowListsForRun = buildEffectiveProviderBrokerToolAllowLists({
102
+ declaredMcps: input.config.mcps,
103
+ enabledAgents: input.config.agents.filter((agent) => agent.enabled),
104
+ providerBrokerToolAllowLists: providerBrokerToolAllowListsForRun,
105
+ capabilitiesByProvider,
106
+ registeredPublicBrokerToolNames,
107
+ internalAlwaysAllowedTools: extraTools
108
+ });
109
+ providerBrokerToolAllowLists = effectiveProviderBrokerToolAllowListsForRun;
110
+ for (const descriptor of enabledProviderDescriptors) {
111
+ descriptor.register({
112
+ composite,
113
+ commandRunner: input.commandRunner,
114
+ config: input.config,
115
+ logDir: input.logDir,
116
+ logger: input.logger,
117
+ serverUrl: brokerServer.url,
118
+ toolAllowList: effectiveProviderBrokerToolAllowListsForRun.get(descriptor.provider) ?? [],
119
+ planBreakdownSessionStore,
120
+ waveAssessmentSessionStore
121
+ });
122
+ }
123
+ agentRunner = composite;
124
+ }
125
+ if (!agentRunner) {
126
+ agentRunner = new CodexCliAgent({
127
+ commandRunner: input.commandRunner,
128
+ logDir: input.logDir,
129
+ logger: input.logger,
130
+ planBreakdownSessionStore: new PlanBreakdownSessionStore(input.logDir),
131
+ waveAssessmentSessionStore: new WaveAssessmentSessionStore(input.logDir)
132
+ });
133
+ }
134
+ return {
135
+ agentRunner,
136
+ ...(capabilitiesByProvider ? { capabilitiesByProvider } : {}),
137
+ ...(providerBrokerToolAllowLists ? { providerBrokerToolAllowLists } : {}),
138
+ ...(brokerToolScope ? { brokerToolScope } : {}),
139
+ ...(brokerServer ? { brokerServer } : {}),
140
+ ...(brokerLogger ? { brokerLogger } : {})
141
+ };
142
+ }
143
+ catch (error) {
144
+ if (brokerServer) {
145
+ await brokerServer.close();
146
+ }
147
+ if (brokerLogger) {
148
+ await brokerLogger.close();
149
+ }
150
+ throw error;
151
+ }
152
+ }
@@ -0,0 +1,73 @@
1
+ import { deriveProjectedCapabilityToolNames, projectCapabilities } from "../../capabilities/projection.js";
2
+ export function buildCapabilitiesByProvider(input) {
3
+ const projections = new Map();
4
+ if (input.capabilities.sensors.length === 0 && input.capabilities.controllers.length === 0) {
5
+ return projections;
6
+ }
7
+ for (const agent of input.enabledAgents) {
8
+ const providerAllowList = input.providerBrokerToolAllowLists.get(agent.provider);
9
+ if (!providerAllowList) {
10
+ continue;
11
+ }
12
+ projections.set(agent.provider, projectCapabilities({
13
+ capabilities: input.capabilities,
14
+ declaredMcps: input.mcps,
15
+ mcpStatuses: input.mcpStatuses,
16
+ registeredPublicBrokerToolNames: input.registeredPublicBrokerToolNames,
17
+ providerRunAllowList: providerAllowList
18
+ }));
19
+ }
20
+ return projections;
21
+ }
22
+ export function buildEffectiveProviderBrokerToolAllowLists(input) {
23
+ const projectedToolsByProvider = new Map();
24
+ for (const [provider, capabilities] of input.capabilitiesByProvider.entries()) {
25
+ projectedToolsByProvider.set(provider, new Set(deriveProjectedCapabilityToolNames(capabilities)));
26
+ }
27
+ const registeredTools = new Set(input.registeredPublicBrokerToolNames);
28
+ const internalTools = new Set(input.internalAlwaysAllowedTools);
29
+ const hostedMcpHandles = new Set(input.declaredMcps.map((mcp) => mcp.handle));
30
+ const effective = new Map();
31
+ for (const agent of input.enabledAgents) {
32
+ if (effective.has(agent.provider)) {
33
+ continue;
34
+ }
35
+ const providerAllowList = input.providerBrokerToolAllowLists.get(agent.provider) ?? [];
36
+ const providerAllowedRegisteredTools = input.registeredPublicBrokerToolNames.filter((toolName) => providerAllowListAllowsTool(providerAllowList, toolName, hostedMcpHandles));
37
+ const projectedTools = projectedToolsByProvider.get(agent.provider) ?? new Set();
38
+ const effectiveTools = new Set();
39
+ for (const toolName of input.internalAlwaysAllowedTools) {
40
+ effectiveTools.add(toolName);
41
+ }
42
+ for (const toolName of providerAllowedRegisteredTools) {
43
+ if (internalTools.has(toolName)) {
44
+ effectiveTools.add(toolName);
45
+ continue;
46
+ }
47
+ if (!isDeclaredHostedMcpTool(toolName, hostedMcpHandles)) {
48
+ effectiveTools.add(toolName);
49
+ continue;
50
+ }
51
+ if (projectedTools.has(toolName)) {
52
+ effectiveTools.add(toolName);
53
+ }
54
+ }
55
+ effective.set(agent.provider, [...effectiveTools].filter((toolName) => internalTools.has(toolName) || registeredTools.has(toolName)));
56
+ }
57
+ return effective;
58
+ }
59
+ function providerAllowListAllowsTool(providerAllowList, publicToolName, hostedMcpHandles) {
60
+ if (isDeclaredHostedMcpTool(publicToolName, hostedMcpHandles)) {
61
+ return providerAllowList.includes(publicToolName);
62
+ }
63
+ return providerAllowList.some((allowedToolName) => {
64
+ if (allowedToolName === publicToolName || allowedToolName === "*") {
65
+ return true;
66
+ }
67
+ return allowedToolName.endsWith(".*") && publicToolName.startsWith(allowedToolName.slice(0, -1));
68
+ });
69
+ }
70
+ function isDeclaredHostedMcpTool(publicToolName, hostedMcpHandles) {
71
+ const dotIndex = publicToolName.indexOf(".");
72
+ return dotIndex > 0 && hostedMcpHandles.has(publicToolName.slice(0, dotIndex));
73
+ }
@@ -0,0 +1,26 @@
1
+ import { AntigravityCliAgent } from "../../../agents/antigravity.js";
2
+ export const antigravityRuntimeProvider = {
3
+ provider: "antigravity",
4
+ isEnabled: (config) => config.agents.some((agent) => agent.enabled && agent.provider === "antigravity"),
5
+ toolAllowList: (config) => config.antigravity.githubBroker.toolAllowList,
6
+ register: (input) => {
7
+ input.composite.register("antigravity", new AntigravityCliAgent({
8
+ commandRunner: input.commandRunner,
9
+ logDir: input.logDir,
10
+ logger: input.logger,
11
+ ...(process.env.BACKBURNER_ANTIGRAVITY_CONFIG_HOME
12
+ ? { configHome: process.env.BACKBURNER_ANTIGRAVITY_CONFIG_HOME }
13
+ : {}),
14
+ ...(process.env.BACKBURNER_GEMINI_CONFIG_HOME
15
+ ? { legacyGeminiConfigHome: process.env.BACKBURNER_GEMINI_CONFIG_HOME }
16
+ : {}),
17
+ githubBroker: {
18
+ serverName: input.config.antigravity.githubBroker.serverName,
19
+ serverUrl: input.serverUrl,
20
+ toolAllowList: [...input.toolAllowList]
21
+ },
22
+ planBreakdownSessionStore: input.planBreakdownSessionStore,
23
+ waveAssessmentSessionStore: input.waveAssessmentSessionStore
24
+ }));
25
+ }
26
+ };
@@ -0,0 +1,20 @@
1
+ import { ClaudeCodeCliAgent } from "../../../agents/claude.js";
2
+ export const claudeRuntimeProvider = {
3
+ provider: "claude",
4
+ isEnabled: (config) => config.agents.some((agent) => agent.enabled && agent.provider === "claude"),
5
+ toolAllowList: (config) => config.claude.githubBroker.toolAllowList,
6
+ register: (input) => {
7
+ input.composite.register("claude", new ClaudeCodeCliAgent({
8
+ commandRunner: input.commandRunner,
9
+ logDir: input.logDir,
10
+ logger: input.logger,
11
+ githubBroker: {
12
+ serverName: input.config.claude.githubBroker.serverName,
13
+ serverUrl: input.serverUrl,
14
+ toolAllowList: [...input.toolAllowList]
15
+ },
16
+ planBreakdownSessionStore: input.planBreakdownSessionStore,
17
+ waveAssessmentSessionStore: input.waveAssessmentSessionStore
18
+ }));
19
+ }
20
+ };
@@ -0,0 +1,20 @@
1
+ import { CodexCliAgent } from "../../../agents/codex.js";
2
+ export const codexRuntimeProvider = {
3
+ provider: "codex",
4
+ isEnabled: (config) => config.agents.some((agent) => agent.enabled && agent.provider === "codex"),
5
+ toolAllowList: (config) => config.codex.githubBroker.toolAllowList,
6
+ register: (input) => {
7
+ input.composite.register("codex", new CodexCliAgent({
8
+ commandRunner: input.commandRunner,
9
+ logDir: input.logDir,
10
+ logger: input.logger,
11
+ githubBroker: {
12
+ serverName: input.config.codex.githubBroker.serverName,
13
+ serverUrl: input.serverUrl,
14
+ toolAllowList: [...input.toolAllowList]
15
+ },
16
+ planBreakdownSessionStore: input.planBreakdownSessionStore,
17
+ waveAssessmentSessionStore: input.waveAssessmentSessionStore
18
+ }));
19
+ }
20
+ };
@@ -0,0 +1,20 @@
1
+ import { GeminiCliAgent } from "../../../agents/gemini.js";
2
+ export const geminiRuntimeProvider = {
3
+ provider: "gemini",
4
+ isEnabled: (config) => config.agents.some((agent) => agent.enabled && agent.provider === "gemini"),
5
+ toolAllowList: (config) => config.gemini.githubBroker.toolAllowList,
6
+ register: (input) => {
7
+ input.composite.register("gemini", new GeminiCliAgent({
8
+ commandRunner: input.commandRunner,
9
+ logDir: input.logDir,
10
+ logger: input.logger,
11
+ githubBroker: {
12
+ serverName: input.config.gemini.githubBroker.serverName,
13
+ serverUrl: input.serverUrl,
14
+ toolAllowList: [...input.toolAllowList]
15
+ },
16
+ planBreakdownSessionStore: input.planBreakdownSessionStore,
17
+ waveAssessmentSessionStore: input.waveAssessmentSessionStore
18
+ }));
19
+ }
20
+ };
@@ -0,0 +1,20 @@
1
+ import { OpenCodeCliAgent } from "../../../agents/opencode.js";
2
+ export const openCodeRuntimeProvider = {
3
+ provider: "opencode",
4
+ isEnabled: (config) => config.agents.some((agent) => agent.enabled && agent.provider === "opencode"),
5
+ toolAllowList: (config) => config.opencode.githubBroker.toolAllowList,
6
+ register: (input) => {
7
+ input.composite.register("opencode", new OpenCodeCliAgent({
8
+ commandRunner: input.commandRunner,
9
+ logDir: input.logDir,
10
+ logger: input.logger,
11
+ githubBroker: {
12
+ serverName: input.config.opencode.githubBroker.serverName,
13
+ serverUrl: input.serverUrl,
14
+ toolAllowList: [...input.toolAllowList]
15
+ },
16
+ planBreakdownSessionStore: input.planBreakdownSessionStore,
17
+ waveAssessmentSessionStore: input.waveAssessmentSessionStore
18
+ }));
19
+ }
20
+ };
@@ -0,0 +1,131 @@
1
+ import * as path from "node:path";
2
+ import { AgentPool } from "../../agents/pool.js";
3
+ import { loadConfig } from "../../config/loader.js";
4
+ import { GitCliGateway, LocalRepoSyncService } from "../../git/types.js";
5
+ import { GitOpsLifecycleService } from "../../git/gitops-lifecycle.js";
6
+ import { MergePrepWorkspaceService } from "../../git/merge-prep-workspace.js";
7
+ import { BackburnerGitToolService } from "../../git/backburner-git-tool-service.js";
8
+ import { GhCliGitHubGateway } from "../../github/gateway.js";
9
+ import { GitHubScanService } from "../../github/service.js";
10
+ import { parseGitHubRemoteUrl } from "../../github/utils.js";
11
+ import { JournalService } from "../../journal/index.js";
12
+ import { JsonJobMemoryStore } from "../../memory/json-store.js";
13
+ import { JobMemoryToolService } from "../../memory/tool-service.js";
14
+ import { createSmitheryMcpResolverFromEnv, reconcileMcpStatus } from "../../mcps/index.js";
15
+ import { StateStore } from "../../state/loader.js";
16
+ import { ExecFileCommandRunner } from "../../utils/command-runner.js";
17
+ import { defaultStderrLogger } from "../../utils/logger.js";
18
+ import { defaultBackburnerCodeRoot, defaultBackburnerManagementRoot, defaultBackburnerOutputsRoot, resolveOutputsStateRoot, resolveOutputsLogsRoot, resolveOutputsJournalRoot } from "../../utils/paths.js";
19
+ import { TriageFollowUpService } from "../../workflows/triage.js";
20
+ import { ImplementationWorkflowService } from "../../worktrees/service.js";
21
+ import { WorkspaceRecoveryService } from "../../worktrees/workspace-recovery.js";
22
+ import { DEFAULT_GITHUB_BROKER_PORT as CLI_DEFAULT_GITHUB_BROKER_PORT, readNumberFlag, readOptionalStringFlag, readStringFlag } from "../options.js";
23
+ export async function createRunContext(input) {
24
+ const { rest, options } = input;
25
+ const managementDir = path.resolve(options.managementDir ?? readStringFlag(rest, "--management-dir", defaultBackburnerManagementRoot()));
26
+ const configuredOutputsDir = options.outputsDir ?? readOptionalStringFlag(rest, "--outputs-dir");
27
+ const outputsDir = path.resolve(configuredOutputsDir ?? defaultBackburnerOutputsRoot());
28
+ const useLegacyStateDirWithoutOutputs = options.stateDir !== undefined && configuredOutputsDir === undefined;
29
+ const logger = options.logger ?? defaultStderrLogger;
30
+ const codeRoot = path.resolve(readOptionalStringFlag(rest, "--code-root") ?? defaultBackburnerCodeRoot());
31
+ const brokerPort = readNumberFlag(rest, "--broker-port", CLI_DEFAULT_GITHUB_BROKER_PORT);
32
+ const commandRunner = options.commandRunner ?? new ExecFileCommandRunner();
33
+ const gitGateway = options.gitGateway ?? new GitCliGateway(commandRunner);
34
+ const gitOpsLifecycle = options.gitOpsLifecycleService ?? new GitOpsLifecycleService(gitGateway);
35
+ const workspaceRecoveryService = options.workspaceRecoveryService ?? new WorkspaceRecoveryService();
36
+ logger.info(`Preparing management root ${managementDir}`);
37
+ const managementGitOps = await gitOpsLifecycle.prepareManagementRoot(managementDir);
38
+ logger.info(`Loading orchestrator config from ${managementDir}`);
39
+ const config = await loadConfig(managementDir);
40
+ const agentPool = new AgentPool(config.maxConcurrentAgents);
41
+ logger.info(`Agent pool: maxConcurrentAgents=${agentPool.maxConcurrent}`);
42
+ let outputsGitOpsPrepared;
43
+ if (useLegacyStateDirWithoutOutputs) {
44
+ logger.info(`Skipping outputs root GitOps because explicit state is stored at ${options.stateDir}`);
45
+ outputsGitOpsPrepared = { status: "skipped_not_git" };
46
+ }
47
+ else {
48
+ logger.info(`Preparing outputs root ${outputsDir}`);
49
+ outputsGitOpsPrepared = await gitOpsLifecycle.prepareOutputsRoot(outputsDir);
50
+ }
51
+ const stateDir = path.resolve(options.stateDir ?? resolveOutputsStateRoot(outputsDir));
52
+ const defaultLogDir = options.stateDir !== undefined ? stateDir : resolveOutputsLogsRoot(outputsDir);
53
+ const logDir = path.resolve(options.logDir ?? readStringFlag(rest, "--log-dir", defaultLogDir));
54
+ let managementRepo;
55
+ try {
56
+ const remoteResult = await commandRunner.run("git", ["remote", "get-url", "origin"], { cwd: managementDir });
57
+ const remoteUrl = remoteResult.stdout.trim();
58
+ const identity = parseGitHubRemoteUrl(remoteUrl);
59
+ if (identity) {
60
+ managementRepo = { repoSlug: `${identity.owner}/${identity.name}` };
61
+ }
62
+ }
63
+ catch {
64
+ // Management repo identity resolve failed, classifyPullRequest will handle missing managementRepo
65
+ }
66
+ const stateStore = new StateStore({ stateDir, executionDir: logDir });
67
+ const journal = options.journalService ?? new JournalService(resolveOutputsJournalRoot(outputsDir));
68
+ const memoryStore = new JsonJobMemoryStore({ filePath: path.join(stateDir, "job-memory.json") });
69
+ const memoryToolService = new JobMemoryToolService(memoryStore, logger);
70
+ const backburnerGitToolService = new BackburnerGitToolService(commandRunner, logger);
71
+ logger.info(`Loading persisted state from ${stateDir}`);
72
+ if (logDir !== stateDir) {
73
+ logger.info(`Loading execution log from ${logDir}`);
74
+ }
75
+ const previousState = await stateStore.load();
76
+ let currentMcpStatuses = previousState.mcpStatuses ?? [];
77
+ if (config.mcps.length > 0) {
78
+ try {
79
+ const resolvedMcps = await createSmitheryMcpResolverFromEnv().resolveDependencies(config.mcps, currentMcpStatuses);
80
+ const reconciliation = reconcileMcpStatus(config.mcps, currentMcpStatuses, resolvedMcps, new Date().toISOString());
81
+ currentMcpStatuses = reconciliation.records;
82
+ await stateStore.writeMcpStatusState(currentMcpStatuses);
83
+ logger.info(`MCP readiness reconciled: added=${reconciliation.added.length}, updated=${reconciliation.updated.length}, unchanged=${reconciliation.unchanged.length}, removed=${reconciliation.removed.length}`);
84
+ }
85
+ catch (err) {
86
+ logger.warn(`Failed to reconcile MCP readiness: ${err instanceof Error ? err.message : String(err)}`);
87
+ }
88
+ }
89
+ const gitHubGateway = options.gitHubGateway ?? new GhCliGitHubGateway(commandRunner, config.allowedUsers);
90
+ const syncService = options.syncService ??
91
+ new LocalRepoSyncService(gitGateway, gitHubGateway);
92
+ const scanService = options.scanService ?? new GitHubScanService(gitHubGateway);
93
+ const implementationWorkflowService = new ImplementationWorkflowService(gitGateway, gitHubGateway);
94
+ const triageFollowUpService = new TriageFollowUpService(gitGateway, gitHubGateway);
95
+ const mergePrepService = options.mergePrepService ?? new MergePrepWorkspaceService(gitGateway);
96
+ const enabledRepos = config.repos.filter((repo) => repo.enabled);
97
+ const results = [];
98
+ return {
99
+ managementDir,
100
+ outputsDir,
101
+ stateDir,
102
+ logDir,
103
+ logger,
104
+ codeRoot,
105
+ brokerPort,
106
+ commandRunner,
107
+ gitGateway,
108
+ gitOpsLifecycle,
109
+ workspaceRecoveryService,
110
+ managementGitOps,
111
+ config,
112
+ agentPool,
113
+ outputsGitOpsPrepared,
114
+ ...(managementRepo ? { managementRepo } : {}),
115
+ stateStore,
116
+ journal,
117
+ memoryStore,
118
+ memoryToolService,
119
+ backburnerGitToolService,
120
+ previousState,
121
+ currentMcpStatuses,
122
+ gitHubGateway,
123
+ syncService,
124
+ scanService,
125
+ implementationWorkflowService,
126
+ triageFollowUpService,
127
+ mergePrepService,
128
+ enabledRepos,
129
+ results
130
+ };
131
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./types.js";
2
+ export * from "./tracker.js";
3
+ export * from "./screen.js";