swarm-orchestrator 7.0.0-alpha.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 (174) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +199 -0
  3. package/agents/reviewer.agent.md +50 -0
  4. package/agents/worker.agent.md +41 -0
  5. package/config/default-agents.yaml +56 -0
  6. package/config/pm-agent.yaml +36 -0
  7. package/config/quality-gates.yaml +88 -0
  8. package/config/repair-agent.yaml +34 -0
  9. package/config/semgrep-rules/complexity-mismatch.yaml +6 -0
  10. package/config/semgrep-rules/exception-swallowing.yaml +13 -0
  11. package/config/semgrep-rules/hardcoded-answer.yaml +6 -0
  12. package/config/semgrep-rules/mock-mutation.yaml +6 -0
  13. package/config/semgrep-rules/test-modification.yaml +6 -0
  14. package/config/user-agents.yaml +23 -0
  15. package/dist/src/adapters/adapter-factory.js +29 -0
  16. package/dist/src/adapters/agent-adapter.js +32 -0
  17. package/dist/src/adapters/claude-code-adapter.js +126 -0
  18. package/dist/src/adapters/claude-code-teams.js +119 -0
  19. package/dist/src/adapters/codex-adapter.js +118 -0
  20. package/dist/src/adapters/copilot-adapter.js +224 -0
  21. package/dist/src/adapters/fatal-error-classifier.js +88 -0
  22. package/dist/src/adapters/index.js +44 -0
  23. package/dist/src/adapters/persistent-session.js +204 -0
  24. package/dist/src/adapters/process-supervisor.js +199 -0
  25. package/dist/src/agents-exporter.js +398 -0
  26. package/dist/src/analytics-log.js +161 -0
  27. package/dist/src/baseline-scanner.js +65 -0
  28. package/dist/src/bootstrap-evidence.js +88 -0
  29. package/dist/src/bootstrap-orchestrator.js +205 -0
  30. package/dist/src/bootstrap-types.js +5 -0
  31. package/dist/src/branch-merger.js +427 -0
  32. package/dist/src/cli/attest-handlers.js +44 -0
  33. package/dist/src/cli/cost-prompt.js +51 -0
  34. package/dist/src/cli/demo-handlers.js +274 -0
  35. package/dist/src/cli/flags.js +152 -0
  36. package/dist/src/cli/index.js +57 -0
  37. package/dist/src/cli/live-status.js +186 -0
  38. package/dist/src/cli/misc-handlers.js +242 -0
  39. package/dist/src/cli/plan-handlers.js +350 -0
  40. package/dist/src/cli/share-handlers.js +163 -0
  41. package/dist/src/cli/status-handlers.js +457 -0
  42. package/dist/src/cli/swarm-handlers.js +638 -0
  43. package/dist/src/cli/usage.js +72 -0
  44. package/dist/src/cli.js +217 -0
  45. package/dist/src/commit-pattern-detector.js +143 -0
  46. package/dist/src/commit-quality-analyzer.js +38 -0
  47. package/dist/src/config-loader.js +339 -0
  48. package/dist/src/context-broker.js +358 -0
  49. package/dist/src/copilot-cli-wrapper.js +258 -0
  50. package/dist/src/cost-estimator.js +241 -0
  51. package/dist/src/defaults.js +18 -0
  52. package/dist/src/demo-mode.js +180 -0
  53. package/dist/src/deployment-handler.js +78 -0
  54. package/dist/src/deployment-manager.js +228 -0
  55. package/dist/src/execution-queue.js +196 -0
  56. package/dist/src/external-tool-manager.js +184 -0
  57. package/dist/src/gate-prompt-builder.js +117 -0
  58. package/dist/src/gate-remediation.js +173 -0
  59. package/dist/src/github-issues-ingester.js +152 -0
  60. package/dist/src/github-mcp-integrator.js +164 -0
  61. package/dist/src/hook-generator.js +229 -0
  62. package/dist/src/index.js +48 -0
  63. package/dist/src/knowledge-base.js +300 -0
  64. package/dist/src/logger.js +111 -0
  65. package/dist/src/meta-analyzer.js +208 -0
  66. package/dist/src/metrics-collector.js +209 -0
  67. package/dist/src/metrics-types.js +5 -0
  68. package/dist/src/multi-repo-coordinator.js +179 -0
  69. package/dist/src/orchestrator/async-meta-analysis.js +84 -0
  70. package/dist/src/orchestrator/fatal-run-error.js +43 -0
  71. package/dist/src/orchestrator/final-gates-remediation.js +258 -0
  72. package/dist/src/orchestrator/git-state-utils.js +119 -0
  73. package/dist/src/orchestrator/pause-controller.js +55 -0
  74. package/dist/src/orchestrator/replan-runner.js +258 -0
  75. package/dist/src/orchestrator/step-executor.js +391 -0
  76. package/dist/src/orchestrator/wave-scheduler-loop.js +204 -0
  77. package/dist/src/owasp-mapper.js +153 -0
  78. package/dist/src/owasp-report-renderer.js +39 -0
  79. package/dist/src/plan-files.js +142 -0
  80. package/dist/src/plan-generator.js +1207 -0
  81. package/dist/src/pm-agent.js +296 -0
  82. package/dist/src/post-run-reporter.js +203 -0
  83. package/dist/src/pr-automation.js +103 -0
  84. package/dist/src/pr-manager.js +318 -0
  85. package/dist/src/presenter/index.js +209 -0
  86. package/dist/src/prompt-builder.js +173 -0
  87. package/dist/src/quality-gates/config-loader.js +196 -0
  88. package/dist/src/quality-gates/default-config.js +243 -0
  89. package/dist/src/quality-gates/file-utils.js +152 -0
  90. package/dist/src/quality-gates/gate-runner.js +171 -0
  91. package/dist/src/quality-gates/gates/accessibility.js +355 -0
  92. package/dist/src/quality-gates/gates/duplicate-blocks.js +144 -0
  93. package/dist/src/quality-gates/gates/hardcoded-config.js +52 -0
  94. package/dist/src/quality-gates/gates/readme-claims.js +62 -0
  95. package/dist/src/quality-gates/gates/runtime-checks.js +265 -0
  96. package/dist/src/quality-gates/gates/scaffold-defaults.js +108 -0
  97. package/dist/src/quality-gates/gates/test-coverage.js +240 -0
  98. package/dist/src/quality-gates/gates/test-file-protection.js +85 -0
  99. package/dist/src/quality-gates/gates/test-isolation.js +74 -0
  100. package/dist/src/quality-gates/index.js +17 -0
  101. package/dist/src/quality-gates/registry.js +205 -0
  102. package/dist/src/quality-gates/types.js +2 -0
  103. package/dist/src/quick-fix-mode.js +302 -0
  104. package/dist/src/recipe-loader.js +122 -0
  105. package/dist/src/repair-agent.js +396 -0
  106. package/dist/src/repo-analyzer.js +342 -0
  107. package/dist/src/report-generator.js +146 -0
  108. package/dist/src/report-renderer.js +90 -0
  109. package/dist/src/requirement-filter.js +52 -0
  110. package/dist/src/sarif-formatter.js +140 -0
  111. package/dist/src/scheduling/dependency-analyzer.js +178 -0
  112. package/dist/src/scheduling/work-stealing-queue.js +123 -0
  113. package/dist/src/secret-redactor.js +90 -0
  114. package/dist/src/session-executor.js +587 -0
  115. package/dist/src/session-manager.js +221 -0
  116. package/dist/src/share/transcript-verification.js +128 -0
  117. package/dist/src/share-parser.js +477 -0
  118. package/dist/src/spinner.js +146 -0
  119. package/dist/src/step-runner.js +365 -0
  120. package/dist/src/swarm-orchestrator.js +686 -0
  121. package/dist/src/task-classifier.js +134 -0
  122. package/dist/src/test-command-discovery.js +123 -0
  123. package/dist/src/text-similarity.js +24 -0
  124. package/dist/src/tier-maps.js +158 -0
  125. package/dist/src/types.js +5 -0
  126. package/dist/src/url-shortener.js +135 -0
  127. package/dist/src/verification/attestation.js +166 -0
  128. package/dist/src/verification/cheat-detector.js +240 -0
  129. package/dist/src/verification/command-runner.js +70 -0
  130. package/dist/src/verification/composite-score.js +157 -0
  131. package/dist/src/verification/cosign-attestation.js +137 -0
  132. package/dist/src/verification/diff-analysis.js +89 -0
  133. package/dist/src/verification/differential-gate.js +173 -0
  134. package/dist/src/verification/index.js +41 -0
  135. package/dist/src/verification/mutation-gate.js +242 -0
  136. package/dist/src/verification/property-gate.js +201 -0
  137. package/dist/src/verification/test-synthesizer.js +243 -0
  138. package/dist/src/verifier/outcome-checks.js +396 -0
  139. package/dist/src/verifier/transcript-checks.js +207 -0
  140. package/dist/src/verifier/verification-reporters.js +148 -0
  141. package/dist/src/verifier-engine.js +491 -0
  142. package/dist/src/wave-resizer.js +131 -0
  143. package/dist/src/wave-scheduler.js +44 -0
  144. package/dist/src/worktree-manager.js +368 -0
  145. package/dist/src/worktree-reserved-paths.js +97 -0
  146. package/package.json +80 -0
  147. package/plugin/agents/.gitkeep +0 -0
  148. package/plugin/agents/backend_master.agent.md +72 -0
  149. package/plugin/agents/devops_pro.agent.md +45 -0
  150. package/plugin/agents/frontend_expert.agent.md +59 -0
  151. package/plugin/agents/integrator_finalizer.agent.md +44 -0
  152. package/plugin/agents/meta_reviewer.agent.md +44 -0
  153. package/plugin/agents/security_auditor.agent.md +43 -0
  154. package/plugin/agents/tester_elite.agent.md +43 -0
  155. package/plugin/hooks/hooks.json +19 -0
  156. package/plugin/hooks/post-tool-use.json +9 -0
  157. package/plugin/hooks/pre-tool-use.json +9 -0
  158. package/plugin/plugin.json +47 -0
  159. package/plugin/skills/swarm-gates/SKILL.md +53 -0
  160. package/plugin/skills/swarm-orchestrate/SKILL.md +34 -0
  161. package/plugin/skills/swarm-verify/SKILL.md +44 -0
  162. package/templates/README.md +35 -0
  163. package/templates/cli-tool.json +31 -0
  164. package/templates/fullstack.json +52 -0
  165. package/templates/library.json +38 -0
  166. package/templates/react-app.json +45 -0
  167. package/templates/recipes/add-api-docs.json +35 -0
  168. package/templates/recipes/add-auth.json +47 -0
  169. package/templates/recipes/add-ci.json +39 -0
  170. package/templates/recipes/add-tests.json +39 -0
  171. package/templates/recipes/migrate-to-ts.json +42 -0
  172. package/templates/recipes/refactor-modularize.json +44 -0
  173. package/templates/recipes/security-audit.json +35 -0
  174. package/templates/rest-api.json +38 -0
@@ -0,0 +1,258 @@
1
+ "use strict";
2
+ /**
3
+ * Copilot CLI Wrapper
4
+ *
5
+ * Abstraction layer for resilient Copilot CLI invocation with:
6
+ * - Graceful degradation when CLI unavailable
7
+ * - Fallback to alternative modes
8
+ * - Better error handling and retry logic
9
+ * - Feature detection and capability checking
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.CopilotCliWrapper = void 0;
13
+ const child_process_1 = require("child_process");
14
+ const logger_1 = require("./logger");
15
+ const logger = (0, logger_1.getLogger)('copilot-cli-wrapper');
16
+ /**
17
+ * Wrapper for GitHub Copilot CLI with resilience features
18
+ */
19
+ class CopilotCliWrapper {
20
+ options;
21
+ capabilities = null;
22
+ capabilityCheckDone = false;
23
+ constructor(options = {}) {
24
+ this.options = options;
25
+ // Default options
26
+ this.options.gracefulDegradation = this.options.gracefulDegradation ?? true;
27
+ this.options.retryOnFailure = this.options.retryOnFailure ?? true;
28
+ this.options.maxRetries = this.options.maxRetries ?? 3;
29
+ this.options.timeout = this.options.timeout ?? 300000; // 5 minutes
30
+ }
31
+ /**
32
+ * Check if Copilot CLI is available and what features it supports
33
+ */
34
+ async checkCapabilities() {
35
+ if (this.capabilityCheckDone && this.capabilities) {
36
+ return this.capabilities;
37
+ }
38
+ const capabilities = {
39
+ available: false,
40
+ supportsPromptMode: false,
41
+ supportsShare: false,
42
+ supportsAgents: false,
43
+ supportsMcp: false
44
+ };
45
+ try {
46
+ // Check if copilot command exists
47
+ const versionResult = await this.runCommand('copilot', ['--version'], { timeout: 5000 });
48
+ if (versionResult.exitCode === 0) {
49
+ capabilities.available = true;
50
+ capabilities.version = versionResult.stdout.trim();
51
+ // Check for -p flag support
52
+ const helpResult = await this.runCommand('copilot', ['--help'], { timeout: 5000 });
53
+ capabilities.supportsPromptMode = helpResult.stdout.includes('-p');
54
+ capabilities.supportsShare = helpResult.stdout.includes('--share');
55
+ capabilities.supportsAgents = helpResult.stdout.includes('--agent');
56
+ capabilities.supportsMcp = helpResult.stdout.includes('--mcp');
57
+ }
58
+ }
59
+ catch {
60
+ // CLI not available
61
+ capabilities.available = false;
62
+ }
63
+ this.capabilities = capabilities;
64
+ this.capabilityCheckDone = true;
65
+ return capabilities;
66
+ }
67
+ /**
68
+ * Execute a Copilot CLI command with resilience
69
+ */
70
+ async execute(args, options = {}) {
71
+ // Strict isolation guard: log when active so transcript captures the mode
72
+ if (this.options.strictIsolation) {
73
+ logger.info('[strict-isolation] Per-task branch isolation active. Context restricted to transcript evidence only.');
74
+ }
75
+ // Inner fleet toggle: prepend /fleet to prompt input
76
+ if (this.options.useInnerFleet && options.input) {
77
+ logger.info('[inner-fleet] Inner fleet mode active. External safety rail enforced.');
78
+ options = { ...options, input: `/fleet ${options.input}` };
79
+ }
80
+ const capabilities = await this.checkCapabilities();
81
+ if (!capabilities.available) {
82
+ if (this.options.gracefulDegradation) {
83
+ return this.degradedExecution(args, options);
84
+ }
85
+ else {
86
+ return {
87
+ success: false,
88
+ output: '',
89
+ error: 'Copilot CLI is not available. Please install it with: npm install -g @github/copilot',
90
+ exitCode: 127,
91
+ degraded: false,
92
+ capabilities
93
+ };
94
+ }
95
+ }
96
+ // Execute with retries
97
+ let lastError = '';
98
+ for (let attempt = 1; attempt <= (this.options.maxRetries || 1); attempt++) {
99
+ try {
100
+ const runOptions = {};
101
+ if (options.cwd)
102
+ runOptions.cwd = options.cwd;
103
+ if (this.options.timeout)
104
+ runOptions.timeout = this.options.timeout;
105
+ if (options.input)
106
+ runOptions.input = options.input;
107
+ const result = await this.runCommand('copilot', args, runOptions);
108
+ return {
109
+ success: result.exitCode === 0,
110
+ output: result.stdout + result.stderr,
111
+ error: result.exitCode !== 0 ? result.stderr : undefined,
112
+ exitCode: result.exitCode,
113
+ degraded: false,
114
+ capabilities
115
+ };
116
+ }
117
+ catch (error) {
118
+ lastError = error instanceof Error ? error.message : String(error);
119
+ if (attempt < (this.options.maxRetries || 1)) {
120
+ // Wait before retry with exponential backoff
121
+ await this.sleep(Math.pow(2, attempt) * 1000);
122
+ }
123
+ }
124
+ }
125
+ // All retries failed
126
+ if (this.options.gracefulDegradation) {
127
+ return this.degradedExecution(args, options);
128
+ }
129
+ return {
130
+ success: false,
131
+ output: '',
132
+ error: `Failed after ${this.options.maxRetries} attempts: ${lastError}`,
133
+ exitCode: 1,
134
+ degraded: false,
135
+ capabilities
136
+ };
137
+ }
138
+ /**
139
+ * Degraded execution mode when CLI unavailable or failing
140
+ * Provides helpful guidance instead of hard failure
141
+ */
142
+ degradedExecution(args, options) {
143
+ const capabilities = this.capabilities || {
144
+ available: false,
145
+ supportsPromptMode: false,
146
+ supportsShare: false,
147
+ supportsAgents: false,
148
+ supportsMcp: false
149
+ };
150
+ // Generate helpful message based on what was attempted
151
+ let message = '⚠️ Graceful Degradation Mode\n\n';
152
+ message += 'The Copilot CLI is not available or failed to execute.\n';
153
+ message += 'This would have run: copilot ' + args.join(' ') + '\n\n';
154
+ if (options.input) {
155
+ message += 'With prompt:\n';
156
+ message += '---\n';
157
+ message += options.input.substring(0, 500);
158
+ if (options.input.length > 500) {
159
+ message += '\n... (truncated)';
160
+ }
161
+ message += '\n---\n\n';
162
+ }
163
+ message += 'To use this feature:\n';
164
+ message += '1. Install Copilot CLI: npm install -g @github/copilot\n';
165
+ message += '2. Authenticate: copilot auth\n';
166
+ message += '3. Re-run this command\n\n';
167
+ message += 'Or, execute the prompt manually in your terminal.';
168
+ return {
169
+ success: false,
170
+ output: message,
171
+ error: 'Copilot CLI not available (degraded mode)',
172
+ exitCode: 0, // Don't fail hard
173
+ degraded: true,
174
+ capabilities
175
+ };
176
+ }
177
+ /**
178
+ * Run a command and capture output
179
+ */
180
+ runCommand(command, args, options = {}) {
181
+ return new Promise((resolve) => {
182
+ const proc = (0, child_process_1.spawn)(command, args, {
183
+ cwd: options.cwd || process.cwd(),
184
+ shell: true
185
+ });
186
+ let stdout = '';
187
+ let stderr = '';
188
+ let timedOut = false;
189
+ // Set timeout if specified
190
+ const timeoutId = options.timeout
191
+ ? setTimeout(() => {
192
+ timedOut = true;
193
+ proc.kill('SIGTERM');
194
+ }, options.timeout)
195
+ : null;
196
+ if (proc.stdout) {
197
+ proc.stdout.on('data', (data) => {
198
+ stdout += data.toString();
199
+ });
200
+ }
201
+ if (proc.stderr) {
202
+ proc.stderr.on('data', (data) => {
203
+ stderr += data.toString();
204
+ });
205
+ }
206
+ // Send input if provided
207
+ if (options.input && proc.stdin) {
208
+ proc.stdin.write(options.input);
209
+ proc.stdin.end();
210
+ }
211
+ proc.on('close', (code) => {
212
+ if (timeoutId)
213
+ clearTimeout(timeoutId);
214
+ if (timedOut) {
215
+ resolve({
216
+ stdout,
217
+ stderr: stderr + '\nCommand timed out',
218
+ exitCode: 124
219
+ });
220
+ }
221
+ else {
222
+ resolve({
223
+ stdout,
224
+ stderr,
225
+ exitCode: code || 0
226
+ });
227
+ }
228
+ });
229
+ proc.on('error', (err) => {
230
+ if (timeoutId)
231
+ clearTimeout(timeoutId);
232
+ resolve({
233
+ stdout,
234
+ stderr: stderr + '\n' + err.message,
235
+ exitCode: 127
236
+ });
237
+ });
238
+ });
239
+ }
240
+ sleep(ms) {
241
+ return new Promise(resolve => setTimeout(resolve, ms));
242
+ }
243
+ /**
244
+ * Get current capabilities (cached)
245
+ */
246
+ getCapabilities() {
247
+ return this.capabilities;
248
+ }
249
+ /**
250
+ * Reset capability cache (for testing)
251
+ */
252
+ resetCapabilities() {
253
+ this.capabilities = null;
254
+ this.capabilityCheckDone = false;
255
+ }
256
+ }
257
+ exports.CopilotCliWrapper = CopilotCliWrapper;
258
+ exports.default = CopilotCliWrapper;
@@ -0,0 +1,241 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CostEstimator = exports.MODEL_MULTIPLIERS = void 0;
4
+ const defaults_1 = require("./defaults");
5
+ /**
6
+ * Model multipliers for premium request consumption.
7
+ * Each copilot -p invocation = 1 base premium request * multiplier.
8
+ * Updated as GitHub changes pricing: https://docs.github.com/en/copilot/concepts/billing/copilot-requests
9
+ * Model availability varies by Copilot plan; Copilot CLI will reject
10
+ * unavailable models at runtime with "not available" on stderr.
11
+ */
12
+ exports.MODEL_MULTIPLIERS = {
13
+ 'claude-sonnet-4': 1,
14
+ 'claude-sonnet-4.6': 1,
15
+ 'claude-opus-4': 1,
16
+ 'gpt-4o': 1,
17
+ 'gpt-5.2': 1,
18
+ 'gpt-5.4': 1,
19
+ 'o3': 20,
20
+ 'o4-mini': 5,
21
+ };
22
+ const MAX_RETRY_PROBABILITY = 0.50;
23
+ const OVERAGE_COST_PER_REQUEST = 0.04;
24
+ // Quality gate remediation overhead: proportion of planned steps that
25
+ // typically trigger remediation follow-ups. Derived from observed runs
26
+ // where ~29% of total requests were gate-triggered remediation steps.
27
+ // Rounded down to 0.25 as a conservative default. Applied per-step, then
28
+ // ceiled to whole requests since partial agent invocations aren't possible.
29
+ const MAX_REMEDIATION_RATE = 0.50;
30
+ // Rough token count for the static boilerplate injected by buildSwarmPrompt.
31
+ // Measured from actual prompt captures; chars / 4 approximation.
32
+ const STATIC_BOILERPLATE_TOKENS = 350;
33
+ class CostEstimator {
34
+ knowledgeBase;
35
+ actuals = [];
36
+ constructor(knowledgeBase) {
37
+ this.knowledgeBase = knowledgeBase;
38
+ }
39
+ estimate(plan, options) {
40
+ const multiplier = exports.MODEL_MULTIPLIERS[options.modelName] ?? 1;
41
+ let retryProbability = this.calibrateRetryProbability(plan);
42
+ // Gate-aware prompts reduce repair cycles by front-loading requirements.
43
+ // Conservative estimate: 30% reduction in retry probability.
44
+ if (options.gateAwarePrompts) {
45
+ retryProbability *= 0.7;
46
+ }
47
+ const perStep = plan.steps.map(step => {
48
+ const taskTokens = Math.ceil(step.task.length / 4);
49
+ const promptTokens = STATIC_BOILERPLATE_TOKENS + taskTokens;
50
+ const baseRequests = 1 * multiplier;
51
+ const fleetMultiplier = options.fleetMode
52
+ ? this.estimateFleetMultiplier(step.task)
53
+ : 1;
54
+ // Per-step estimate is the base cost without retry inflation.
55
+ // Retry buffer is calculated as an aggregate across the plan.
56
+ const stepRequests = baseRequests * fleetMultiplier;
57
+ return {
58
+ stepNumber: step.stepNumber,
59
+ agentName: step.agentName,
60
+ estimatedPromptTokens: promptTokens,
61
+ estimatedPremiumRequests: stepRequests,
62
+ retryProbability,
63
+ rationale: this.buildRationale(multiplier, fleetMultiplier, retryProbability, options),
64
+ };
65
+ });
66
+ const baseTotalNoRetry = perStep.reduce((sum, s) => sum + s.estimatedPremiumRequests, 0);
67
+ // Retry buffer is the aggregate expected retry cost across all steps
68
+ const retryBuffer = Math.ceil(baseTotalNoRetry * retryProbability);
69
+ // Remediation buffer: when quality gates are enabled, some steps will
70
+ // fail gate checks and trigger automated follow-up remediation steps.
71
+ // Each remediation step costs one premium request per model multiplier.
72
+ const remediationRate = options.qualityGatesEnabled
73
+ ? this.calibrateRemediationRate(plan)
74
+ : 0;
75
+ const remediationBuffer = Math.ceil(plan.steps.length * remediationRate * multiplier);
76
+ const totalRaw = baseTotalNoRetry + retryBuffer + remediationBuffer;
77
+ // Low estimate assumes no retries and no remediation
78
+ const lowEstimate = baseTotalNoRetry;
79
+ const highEstimate = totalRaw;
80
+ const overageCostUSD = options.remainingAllowance !== undefined
81
+ ? Math.max(0, totalRaw - options.remainingAllowance) * OVERAGE_COST_PER_REQUEST
82
+ : 0;
83
+ return {
84
+ totalPremiumRequests: totalRaw,
85
+ lowEstimate,
86
+ highEstimate,
87
+ perStep,
88
+ retryBuffer: Math.max(0, retryBuffer),
89
+ remediationBuffer,
90
+ modelMultiplier: multiplier,
91
+ overageCostUSD: parseFloat(overageCostUSD.toFixed(2)),
92
+ ...(options.remainingAllowance !== undefined
93
+ ? { remainingAllowance: options.remainingAllowance }
94
+ : {}),
95
+ };
96
+ }
97
+ recordActual(stepNumber, estimatedRequests, actualRequests, retryCount) {
98
+ this.actuals.push({ stepNumber, estimatedRequests, actualRequests, retryCount });
99
+ }
100
+ /**
101
+ * Ratio of correctly-estimated steps to total recorded steps.
102
+ * A step is "correct" if estimated >= actual (no underestimate).
103
+ * Returns 1.0 when no actuals recorded (no data to disprove accuracy).
104
+ */
105
+ getAccuracy() {
106
+ if (this.actuals.length === 0)
107
+ return 1.0;
108
+ const totalEstimated = this.actuals.reduce((s, a) => s + a.estimatedRequests, 0);
109
+ const totalActual = this.actuals.reduce((s, a) => s + a.actualRequests, 0);
110
+ if (totalActual === 0)
111
+ return 1.0;
112
+ // Conservative overestimates are acceptable; only penalize underestimates.
113
+ // Accuracy for overestimates: actual / estimated (closer to 1 = tighter).
114
+ // Accuracy for underestimates: estimated / actual (penalizes gaps).
115
+ if (totalEstimated >= totalActual) {
116
+ return totalActual / totalEstimated;
117
+ }
118
+ return totalEstimated / totalActual;
119
+ }
120
+ /**
121
+ * Pull historical failure rate from knowledge base cost_history patterns.
122
+ * Falls back to DEFAULT_RETRY_PROBABILITY when no history exists.
123
+ * Parses structured CostHistoryEvidence from evidence array.
124
+ * Falls back to legacy string parsing for pre-v3.3 entries.
125
+ */
126
+ calibrateRetryProbability(_plan) {
127
+ if (!this.knowledgeBase)
128
+ return defaults_1.DEFAULT_RETRY_PROBABILITY;
129
+ const costPatterns = this.knowledgeBase.getPatternsByCategory('cost_history');
130
+ if (costPatterns.length === 0)
131
+ return defaults_1.DEFAULT_RETRY_PROBABILITY;
132
+ let totalRetries = 0;
133
+ let totalSteps = 0;
134
+ for (const pattern of costPatterns) {
135
+ // Try structured evidence first (single JSON string per entry)
136
+ const parsed = this.parseStructuredEvidence(pattern.evidence);
137
+ if (parsed) {
138
+ totalSteps += parsed.actual;
139
+ totalRetries += parsed.retries;
140
+ continue;
141
+ }
142
+ // Legacy fallback: string-encoded fields
143
+ for (const ev of pattern.evidence) {
144
+ if (ev.startsWith('actual:')) {
145
+ const actual = parseInt(ev.split(':')[1], 10);
146
+ if (!isNaN(actual))
147
+ totalSteps += actual;
148
+ }
149
+ }
150
+ const retryMatch = pattern.insight.match(/(\d+)\s+retries/);
151
+ if (retryMatch) {
152
+ totalRetries += parseInt(retryMatch[1], 10);
153
+ }
154
+ }
155
+ if (totalSteps === 0)
156
+ return defaults_1.DEFAULT_RETRY_PROBABILITY;
157
+ const rate = totalRetries / totalSteps;
158
+ return Math.min(rate, MAX_RETRY_PROBABILITY);
159
+ }
160
+ /**
161
+ * Pull historical remediation rate from knowledge base cost_history patterns.
162
+ * Remediation steps are quality-gate-triggered follow-ups (not retries).
163
+ * Falls back to DEFAULT_REMEDIATION_RATE when no history with remediation
164
+ * data exists. Only structured evidence (v4.2+) carries remediation counts.
165
+ */
166
+ calibrateRemediationRate(_plan) {
167
+ if (!this.knowledgeBase)
168
+ return defaults_1.DEFAULT_REMEDIATION_RATE;
169
+ const costPatterns = this.knowledgeBase.getPatternsByCategory('cost_history');
170
+ if (costPatterns.length === 0)
171
+ return defaults_1.DEFAULT_REMEDIATION_RATE;
172
+ let totalPlannedSteps = 0;
173
+ let totalRemediationSteps = 0;
174
+ for (const pattern of costPatterns) {
175
+ const parsed = this.parseStructuredEvidence(pattern.evidence);
176
+ if (!parsed)
177
+ continue;
178
+ if (typeof parsed.remediationSteps !== 'number')
179
+ continue;
180
+ totalPlannedSteps += parsed.steps;
181
+ totalRemediationSteps += parsed.remediationSteps;
182
+ }
183
+ if (totalPlannedSteps === 0)
184
+ return defaults_1.DEFAULT_REMEDIATION_RATE;
185
+ const rate = totalRemediationSteps / totalPlannedSteps;
186
+ return Math.min(rate, MAX_REMEDIATION_RATE);
187
+ }
188
+ /**
189
+ * Attempt to parse a CostHistoryEvidence object from the evidence array.
190
+ * Returns null if the evidence uses the legacy string format.
191
+ */
192
+ parseStructuredEvidence(evidence) {
193
+ if (evidence.length !== 1)
194
+ return null;
195
+ try {
196
+ const obj = JSON.parse(evidence[0]);
197
+ if (typeof obj.runId === 'string' && typeof obj.actual === 'number') {
198
+ return obj;
199
+ }
200
+ }
201
+ catch {
202
+ // Not JSON; legacy format
203
+ }
204
+ return null;
205
+ }
206
+ /**
207
+ * Heuristic fleet multiplier: tasks mentioning multiple files or components
208
+ * likely trigger more subagents.
209
+ */
210
+ estimateFleetMultiplier(taskDescription) {
211
+ const lower = taskDescription.toLowerCase();
212
+ const multiFileIndicators = [
213
+ 'multiple files', 'several files', 'all files',
214
+ 'each module', 'every module', 'across modules',
215
+ 'components', 'services', 'endpoints',
216
+ ];
217
+ const matchCount = multiFileIndicators.filter(ind => lower.includes(ind)).length;
218
+ if (matchCount >= 2)
219
+ return 4;
220
+ if (matchCount === 1)
221
+ return 3;
222
+ // Check for list-like patterns (commas separating items in the task)
223
+ const commaSegments = taskDescription.split(',').length;
224
+ if (commaSegments >= 4)
225
+ return 3;
226
+ if (commaSegments >= 2)
227
+ return 2;
228
+ return 2; // fleet always spawns at least one subagent beyond the coordinator
229
+ }
230
+ buildRationale(multiplier, fleetMultiplier, retryProb, options) {
231
+ const parts = [
232
+ `${options.modelName} (${multiplier}x)`,
233
+ ];
234
+ if (options.fleetMode) {
235
+ parts.push(`fleet (${fleetMultiplier}x subagents)`);
236
+ }
237
+ parts.push(`${(retryProb * 100).toFixed(0)}% retry buffer`);
238
+ return parts.join(', ');
239
+ }
240
+ }
241
+ exports.CostEstimator = CostEstimator;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_SHORT_CODE_MIN_LENGTH = exports.DEFAULT_URL_MAX_LENGTH = exports.DEFAULT_REMEDIATION_RATE = exports.DEFAULT_RETRY_PROBABILITY = exports.DEFAULT_REPAIR_TRANSCRIPT_CHARS = exports.DEFAULT_REPAIR_REPORT_CHARS = exports.DEFAULT_FAILURE_CONTEXT_CHARS = exports.DEFAULT_COMMAND_TIMEOUT_MS = exports.DEFAULT_BRANCH_SWITCH_TIMEOUT_MS = exports.DEFAULT_DEPENDENCY_WAIT_MS = exports.DEFAULT_CONTEXT_STALE_LOCK_MS = exports.DEFAULT_CONTEXT_LOCK_WAIT_MS = exports.DEFAULT_HEARTBEAT_QUIET_THRESHOLD_MS = exports.DEFAULT_HEARTBEAT_INTERVAL_MS = exports.DEFAULT_SIGKILL_DELAY_MS = void 0;
4
+ exports.DEFAULT_SIGKILL_DELAY_MS = 5_000;
5
+ exports.DEFAULT_HEARTBEAT_INTERVAL_MS = 5_000;
6
+ exports.DEFAULT_HEARTBEAT_QUIET_THRESHOLD_MS = 10_000;
7
+ exports.DEFAULT_CONTEXT_LOCK_WAIT_MS = 30_000;
8
+ exports.DEFAULT_CONTEXT_STALE_LOCK_MS = 300_000;
9
+ exports.DEFAULT_DEPENDENCY_WAIT_MS = 600_000;
10
+ exports.DEFAULT_BRANCH_SWITCH_TIMEOUT_MS = 15_000;
11
+ exports.DEFAULT_COMMAND_TIMEOUT_MS = 120_000;
12
+ exports.DEFAULT_FAILURE_CONTEXT_CHARS = 2_000;
13
+ exports.DEFAULT_REPAIR_REPORT_CHARS = 4_000;
14
+ exports.DEFAULT_REPAIR_TRANSCRIPT_CHARS = 6_000;
15
+ exports.DEFAULT_RETRY_PROBABILITY = 0.15;
16
+ exports.DEFAULT_REMEDIATION_RATE = 0.25;
17
+ exports.DEFAULT_URL_MAX_LENGTH = 2_048;
18
+ exports.DEFAULT_SHORT_CODE_MIN_LENGTH = 7;