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,396 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.RepairAgent = void 0;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const child_process_1 = require("child_process");
43
+ const session_executor_1 = __importDefault(require("./session-executor"));
44
+ const verifier_engine_1 = __importDefault(require("./verifier-engine"));
45
+ const test_command_discovery_1 = require("./test-command-discovery");
46
+ const logger_1 = require("./logger");
47
+ const defaults_1 = require("./defaults");
48
+ const logger = (0, logger_1.getLogger)('repair-agent');
49
+ // Approximate tokens per character (GPT-family average: ~4 chars per token).
50
+ const CHARS_PER_TOKEN = 4;
51
+ /**
52
+ * RepairAgent - spawns a dedicated Copilot CLI session with failure context
53
+ * to fix issues detected by the verifier, then re-verifies.
54
+ *
55
+ * Retry loop: up to maxRetries attempts. Each attempt receives the prior
56
+ * transcript and verification report so the agent can see what went wrong.
57
+ */
58
+ class RepairAgent {
59
+ workingDir;
60
+ maxRetries;
61
+ constructor(workingDir, maxRetries) {
62
+ this.workingDir = workingDir;
63
+ this.maxRetries = maxRetries ?? 3;
64
+ }
65
+ /**
66
+ * Build a repair prompt that includes the failure context so the agent
67
+ * knows exactly what to fix.
68
+ */
69
+ buildRepairPrompt(context) {
70
+ const sections = [];
71
+ sections.push('=== REPAIR AGENT - Self-Repair Session ===');
72
+ sections.push('');
73
+ sections.push(`Step ${context.stepNumber} (${context.agentName}) failed verification.`);
74
+ sections.push(`Repair attempt ${context.retryCount} of ${this.maxRetries}.`);
75
+ sections.push('');
76
+ sections.push('--- ORIGINAL TASK ---');
77
+ sections.push(context.originalTask);
78
+ sections.push('');
79
+ // Include failed checks so the repair agent knows exactly what to fix
80
+ if (context.failedChecks.length > 0) {
81
+ sections.push('--- FAILED VERIFICATION CHECKS ---');
82
+ context.failedChecks.forEach((check, i) => {
83
+ sections.push(` ${i + 1}. ${check}`);
84
+ });
85
+ sections.push('');
86
+ }
87
+ if (context.rootCause) {
88
+ sections.push('--- ROOT CAUSE ---');
89
+ sections.push(context.rootCause);
90
+ sections.push('');
91
+ }
92
+ // Include the verification report if it exists on disk
93
+ if (context.verificationReportPath && fs.existsSync(context.verificationReportPath)) {
94
+ const report = fs.readFileSync(context.verificationReportPath, 'utf8');
95
+ // Cap at 4000 chars to stay within prompt budget
96
+ const trimmed = report.length > defaults_1.DEFAULT_REPAIR_REPORT_CHARS
97
+ ? report.slice(0, defaults_1.DEFAULT_REPAIR_REPORT_CHARS) + '\n... (truncated)'
98
+ : report;
99
+ sections.push('--- VERIFICATION REPORT ---');
100
+ sections.push(trimmed);
101
+ sections.push('');
102
+ }
103
+ // Include the original transcript so the repair agent can see what the
104
+ // previous agent actually did (and did wrong).
105
+ if (context.transcriptPath && fs.existsSync(context.transcriptPath)) {
106
+ const transcript = fs.readFileSync(context.transcriptPath, 'utf8');
107
+ // Cap at 6000 chars
108
+ const trimmed = transcript.length > defaults_1.DEFAULT_REPAIR_TRANSCRIPT_CHARS
109
+ ? transcript.slice(0, defaults_1.DEFAULT_REPAIR_TRANSCRIPT_CHARS) + '\n... (truncated)'
110
+ : transcript;
111
+ sections.push('--- PRIOR SESSION TRANSCRIPT ---');
112
+ sections.push(trimmed);
113
+ sections.push('');
114
+ }
115
+ // Include git diff on the branch so the agent sees current state
116
+ const diff = this.getGitDiff(context.branchName);
117
+ if (diff) {
118
+ const trimmed = diff.length > defaults_1.DEFAULT_REPAIR_REPORT_CHARS
119
+ ? diff.slice(0, defaults_1.DEFAULT_REPAIR_REPORT_CHARS) + '\n... (truncated)'
120
+ : diff;
121
+ sections.push('--- GIT DIFF ON BRANCH ---');
122
+ sections.push(trimmed);
123
+ sections.push('');
124
+ }
125
+ // Outcome evidence: structured failure context from verifier engine
126
+ if (context.failureContext) {
127
+ sections.push('--- OUTCOME EVIDENCE ---');
128
+ sections.push(context.failureContext);
129
+ sections.push('');
130
+ }
131
+ // Discover the target project's full test gate before the repair
132
+ // instructions so the agent commits only after running the real script.
133
+ const testDiscovery = (0, test_command_discovery_1.discoverTestCommand)(this.workingDir);
134
+ if (testDiscovery.warning && !(0, logger_1.isPrettyMode)()) {
135
+ logger.warn(`test command discovery: ${testDiscovery.warning}`);
136
+ }
137
+ sections.push((0, test_command_discovery_1.renderVerifyCommandSection)(testDiscovery));
138
+ sections.push('--- REPAIR INSTRUCTIONS ---');
139
+ // classify failure and inject targeted strategy (Upgrade 9)
140
+ const failureClass = this.classifyFailure(context.failedChecks, context.rootCause);
141
+ const strategy = this.getRepairStrategy(failureClass);
142
+ sections.push(`--- FAILURE CLASSIFICATION: ${failureClass} ---`);
143
+ sections.push(strategy);
144
+ sections.push('');
145
+ // inject focused evidence for specific failure types
146
+ if (failureClass === 'test-failure') {
147
+ const testChecks = context.failedChecks.filter(c => c.startsWith('[test]'));
148
+ if (testChecks.length > 0) {
149
+ sections.push('Failing test checks:');
150
+ testChecks.forEach(t => sections.push(` - ${t}`));
151
+ sections.push('');
152
+ }
153
+ }
154
+ else if (failureClass === 'build-failure') {
155
+ const buildChecks = context.failedChecks.filter(c => c.startsWith('[build]'));
156
+ if (buildChecks.length > 0) {
157
+ sections.push('Build errors:');
158
+ buildChecks.forEach(b => sections.push(` - ${b}`));
159
+ sections.push('');
160
+ }
161
+ }
162
+ // Signal urgency when this is the final allowed attempt
163
+ if (context.retryCount >= this.maxRetries) {
164
+ sections.push('This is the final attempt. Prioritize getting a working result over completeness.');
165
+ sections.push('');
166
+ }
167
+ sections.push('4. Commit your fixes with a clear message starting with "repair:".');
168
+ sections.push('5. Do not claim work is done without evidence in the transcript.');
169
+ sections.push('');
170
+ return sections.join('\n');
171
+ }
172
+ /**
173
+ * Estimate token cost from a transcript string.
174
+ * Uses a simple character-to-token ratio (approximately 4 chars per token
175
+ * for English text in GPT-family models).
176
+ */
177
+ estimateTokenCost(text) {
178
+ if (!text)
179
+ return 0;
180
+ return Math.ceil(text.length / CHARS_PER_TOKEN);
181
+ }
182
+ /**
183
+ * Run the repair loop: up to maxRetries attempts.
184
+ * Each attempt spawns a Copilot CLI session with the failure context,
185
+ * then re-verifies. Stops on first successful verification.
186
+ *
187
+ * Returns a RepairResult summarizing all attempts.
188
+ */
189
+ async attemptRepair(context, sessionOptions, verificationRequirements) {
190
+ const attemptDetails = [];
191
+ let totalTokens = 0;
192
+ const overallStart = Date.now();
193
+ for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
194
+ const attemptStart = Date.now();
195
+ // Update retry count in context for prompt generation
196
+ const repairContext = { ...context, retryCount: attempt };
197
+ const prompt = this.buildRepairPrompt(repairContext);
198
+ totalTokens += this.estimateTokenCost(prompt);
199
+ // Set up transcript path for this repair attempt
200
+ const repairTranscript = this.getRepairTranscriptPath(context, attempt);
201
+ const repairDir = path.dirname(repairTranscript);
202
+ if (!fs.existsSync(repairDir)) {
203
+ fs.mkdirSync(repairDir, { recursive: true });
204
+ }
205
+ const opts = {
206
+ ...sessionOptions,
207
+ shareToFile: repairTranscript,
208
+ logPrefix: `[REPAIR:${context.agentName}:${context.stepNumber}:attempt-${attempt}]`
209
+ };
210
+ let sessionResult;
211
+ try {
212
+ // Create session executor for the working directory (may be a worktree)
213
+ const executor = new session_executor_1.default(this.workingDir);
214
+ sessionResult = await executor.executeSession(prompt, opts);
215
+ // Estimate tokens from output
216
+ if (sessionResult.output) {
217
+ totalTokens += this.estimateTokenCost(sessionResult.output);
218
+ }
219
+ if (!sessionResult.success) {
220
+ attemptDetails.push({
221
+ attempt,
222
+ durationMs: Date.now() - attemptStart,
223
+ sessionSuccess: false,
224
+ verificationPassed: false,
225
+ estimatedTokens: this.estimateTokenCost(prompt) + this.estimateTokenCost(sessionResult.output || ''),
226
+ error: sessionResult.error || 'Session exited with non-zero code'
227
+ });
228
+ continue;
229
+ }
230
+ // Re-verify
231
+ const transcriptToVerify = fs.existsSync(repairTranscript)
232
+ ? repairTranscript
233
+ : context.transcriptPath;
234
+ const verifier = new verifier_engine_1.default(this.workingDir);
235
+ const verificationResult = await verifier.verifyStep(context.stepNumber, context.agentName, transcriptToVerify, verificationRequirements);
236
+ const verificationPassed = verificationResult.passed;
237
+ attemptDetails.push({
238
+ attempt,
239
+ durationMs: Date.now() - attemptStart,
240
+ sessionSuccess: true,
241
+ verificationPassed,
242
+ estimatedTokens: this.estimateTokenCost(prompt) + this.estimateTokenCost(sessionResult.output || '')
243
+ });
244
+ if (verificationPassed) {
245
+ return {
246
+ success: true,
247
+ attempts: attempt,
248
+ verificationPassed: true,
249
+ transcriptPath: repairTranscript,
250
+ estimatedTokenCost: totalTokens,
251
+ totalDurationMs: Date.now() - overallStart,
252
+ attemptDetails
253
+ };
254
+ }
255
+ // Update the context with the new transcript and report for next attempt
256
+ context = {
257
+ ...context,
258
+ transcriptPath: repairTranscript,
259
+ failedChecks: this.extractFailedChecks(verificationResult)
260
+ };
261
+ }
262
+ catch (error) {
263
+ const err = error;
264
+ attemptDetails.push({
265
+ attempt,
266
+ durationMs: Date.now() - attemptStart,
267
+ sessionSuccess: false,
268
+ verificationPassed: false,
269
+ estimatedTokens: this.estimateTokenCost(prompt),
270
+ error: err.message
271
+ });
272
+ }
273
+ }
274
+ // All retries exhausted
275
+ return {
276
+ success: false,
277
+ attempts: this.maxRetries,
278
+ verificationPassed: false,
279
+ transcriptPath: attemptDetails.length > 0
280
+ ? this.getRepairTranscriptPath(context, attemptDetails.length)
281
+ : null,
282
+ estimatedTokenCost: totalTokens,
283
+ totalDurationMs: Date.now() - overallStart,
284
+ attemptDetails,
285
+ error: `Repair failed after ${this.maxRetries} attempt(s)`
286
+ };
287
+ }
288
+ /**
289
+ * Classify failure type from tagged check strings and root cause.
290
+ * Uses frequency count on [type] prefixes from extractFailedChecks output.
291
+ */
292
+ classifyFailure(failedChecks, rootCause) {
293
+ const lower = [...failedChecks.map(c => c.toLowerCase()), rootCause.toLowerCase()].join(' ');
294
+ // priority: timeout > dependency > missing artifact > majority tag
295
+ if (/timeout|timed out/.test(lower))
296
+ return 'timeout';
297
+ if (/\bpackage\b|\bdependency\b|\bmodule not found\b/.test(lower))
298
+ return 'dependency-error';
299
+ if (/not found|not created|missing|\[missing-files\]|\[no-changes\]/.test(lower))
300
+ return 'missing-artifact';
301
+ // count tagged prefixes
302
+ let buildCount = 0, testCount = 0;
303
+ for (const check of failedChecks) {
304
+ if (check.startsWith('[build]'))
305
+ buildCount++;
306
+ else if (check.startsWith('[test]'))
307
+ testCount++;
308
+ }
309
+ if (buildCount > 0 && buildCount >= testCount)
310
+ return 'build-failure';
311
+ if (testCount > 0)
312
+ return 'test-failure';
313
+ return 'general';
314
+ }
315
+ /**
316
+ * Return targeted repair instructions for the given failure class.
317
+ * Replaces the generic one-size-fits-all instructions.
318
+ */
319
+ getRepairStrategy(failureClass) {
320
+ switch (failureClass) {
321
+ case 'build-failure':
322
+ return 'Focus on the compiler/bundler errors below. Fix the specific file and line mentioned. Do not change unrelated code.';
323
+ case 'test-failure':
324
+ return 'The failing test names and assertions are listed below. Fix the implementation to make these tests pass. Do not modify the tests.';
325
+ case 'missing-artifact':
326
+ return 'The following expected files were not created. Create them now.';
327
+ case 'dependency-error':
328
+ return 'Install or fix the missing dependencies listed below.';
329
+ case 'timeout':
330
+ return 'The previous session timed out. Simplify the task: focus on the minimum viable deliverable, skip optional steps.';
331
+ case 'general':
332
+ return '1. Read the failed checks and root cause above carefully.\n2. Fix the specific issues identified. Do not redo unrelated work.\n3. Run tests if the task requires tests.';
333
+ }
334
+ }
335
+ /**
336
+ * Extract human-readable failed check descriptions from a VerificationResult.
337
+ */
338
+ extractFailedChecks(result) {
339
+ const checks = [];
340
+ for (const check of result.checks) {
341
+ if (!check.passed) {
342
+ const label = this.formatCheckLabel(check);
343
+ checks.push(label);
344
+ }
345
+ }
346
+ if (result.unverifiedClaims.length > 0) {
347
+ checks.push(`Unverified claims: ${result.unverifiedClaims.join('; ')}`);
348
+ }
349
+ return checks;
350
+ }
351
+ /**
352
+ * Format a single failed check into a tagged string.
353
+ * Outcome-based check types get richer detail than transcript-parsed ones.
354
+ */
355
+ formatCheckLabel(check) {
356
+ const reason = check.reason ? ` - ${check.reason}` : '';
357
+ switch (check.type) {
358
+ case 'build_exec':
359
+ return `[build] ${check.description}${reason}`;
360
+ case 'test_exec':
361
+ return `[test] ${check.description}${reason}`;
362
+ case 'file_existence':
363
+ return `[missing-files] ${check.description}${reason}`;
364
+ case 'git_diff':
365
+ return `[no-changes] ${check.description}${reason}`;
366
+ default:
367
+ return `[${check.type}] ${check.description}${reason}`;
368
+ }
369
+ }
370
+ /**
371
+ * Get the transcript path for a given repair attempt.
372
+ */
373
+ getRepairTranscriptPath(context, attempt) {
374
+ const dir = path.dirname(context.transcriptPath);
375
+ return path.join(dir, `repair-attempt-${attempt}.md`);
376
+ }
377
+ /**
378
+ * Get git diff for a branch. Returns empty string on failure.
379
+ */
380
+ getGitDiff(_branchName) {
381
+ try {
382
+ const diff = (0, child_process_1.execSync)(`git diff HEAD~1 --stat 2>/dev/null || echo ""`, {
383
+ cwd: this.workingDir,
384
+ encoding: 'utf8',
385
+ timeout: 10000
386
+ });
387
+ return diff.trim();
388
+ }
389
+ catch {
390
+ // Git diff unavailable (no prior commit, detached HEAD); non-critical for repair
391
+ return '';
392
+ }
393
+ }
394
+ }
395
+ exports.RepairAgent = RepairAgent;
396
+ exports.default = RepairAgent;