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,296 @@
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.PMAgent = void 0;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const config_loader_1 = require("./config-loader");
43
+ const session_executor_1 = __importDefault(require("./session-executor"));
44
+ const logger_1 = require("./logger");
45
+ const logger = (0, logger_1.getLogger)('pm-agent');
46
+ // Approximate tokens per character (GPT-family average).
47
+ const CHARS_PER_TOKEN = 4;
48
+ /**
49
+ * PMAgent - Project Manager agent that reviews a generated plan before
50
+ * swarm execution. Validates step ordering, dependency correctness,
51
+ * scope coverage, and agent assignment.
52
+ *
53
+ * Usage:
54
+ * const pm = new PMAgent(agents);
55
+ * const result = pm.reviewPlan(plan);
56
+ *
57
+ * The review is purely local (no LLM call) by default. When a Copilot
58
+ * CLI session is available, it can optionally run an LLM-assisted review.
59
+ */
60
+ class PMAgent {
61
+ availableAgents;
62
+ constructor(availableAgents) {
63
+ this.availableAgents = availableAgents;
64
+ }
65
+ /**
66
+ * Run a local (deterministic) review of the plan.
67
+ * Checks for common issues:
68
+ * - Circular dependencies
69
+ * - References to non-existent agents
70
+ * - Orphaned steps (no dependency path to step 1)
71
+ * - Missing integration/finalization step
72
+ * - Duplicate step numbers
73
+ */
74
+ reviewPlan(plan) {
75
+ const start = Date.now();
76
+ const reviewNotes = [];
77
+ const changesApplied = [];
78
+ const revisedPlan = this.deepCopyPlan(plan);
79
+ // 1. Check for duplicate step numbers
80
+ const stepNumbers = revisedPlan.steps.map(s => s.stepNumber);
81
+ const seen = new Set();
82
+ for (const num of stepNumbers) {
83
+ if (seen.has(num)) {
84
+ reviewNotes.push(`Duplicate step number: ${num}`);
85
+ }
86
+ seen.add(num);
87
+ }
88
+ // 2. Check for references to non-existent agents
89
+ const agentNames = new Set(this.availableAgents.map(a => a.name));
90
+ const normalizedAgentNames = new Set(this.availableAgents.map(a => config_loader_1.ConfigLoader.normalizeAgentName(a.name)));
91
+ for (const step of revisedPlan.steps) {
92
+ if (!agentNames.has(step.agentName) && !normalizedAgentNames.has(config_loader_1.ConfigLoader.normalizeAgentName(step.agentName))) {
93
+ reviewNotes.push(`Step ${step.stepNumber} references unknown agent: ${step.agentName}`);
94
+ }
95
+ }
96
+ // 3. Check for circular dependencies
97
+ const circularSteps = this.detectCircularDeps(revisedPlan.steps);
98
+ if (circularSteps.length > 0) {
99
+ reviewNotes.push(`Circular dependencies detected involving step(s): ${circularSteps.join(', ')}`);
100
+ }
101
+ // 4. Check for dependencies on non-existent steps
102
+ const validSteps = new Set(revisedPlan.steps.map(s => s.stepNumber));
103
+ for (const step of revisedPlan.steps) {
104
+ for (const dep of step.dependencies) {
105
+ if (!validSteps.has(dep)) {
106
+ reviewNotes.push(`Step ${step.stepNumber} depends on non-existent step ${dep}`);
107
+ }
108
+ }
109
+ }
110
+ // 5. Check for missing reviewer step (last step should be reviewer)
111
+ if (revisedPlan.steps.length > 1) {
112
+ const lastStep = revisedPlan.steps[revisedPlan.steps.length - 1];
113
+ const hasReviewer = lastStep.agentName === 'reviewer';
114
+ if (!hasReviewer && agentNames.has('reviewer')) {
115
+ reviewNotes.push('Plan is missing a final integration/finalization step');
116
+ }
117
+ }
118
+ // 6. Ensure metadata is up to date
119
+ if (!revisedPlan.metadata || revisedPlan.metadata.totalSteps !== revisedPlan.steps.length) {
120
+ revisedPlan.metadata = {
121
+ ...revisedPlan.metadata,
122
+ totalSteps: revisedPlan.steps.length
123
+ };
124
+ changesApplied.push('Updated metadata.totalSteps');
125
+ }
126
+ const estimatedTokenCost = Math.ceil(JSON.stringify(revisedPlan).length / CHARS_PER_TOKEN);
127
+ return {
128
+ revisedPlan,
129
+ reviewNotes,
130
+ changesApplied,
131
+ durationMs: Date.now() - start,
132
+ estimatedTokenCost,
133
+ skipped: false
134
+ };
135
+ }
136
+ /**
137
+ * Build a prompt for LLM-assisted plan review (for use with Copilot CLI).
138
+ */
139
+ buildReviewPrompt(plan) {
140
+ const sections = [];
141
+ sections.push('=== PM AGENT - Plan Review ===');
142
+ sections.push('');
143
+ sections.push('You are a project manager reviewing an execution plan for a parallel');
144
+ sections.push('swarm of coding agents. Review the plan for:');
145
+ sections.push(' 1. Correct dependency ordering (no circular deps)');
146
+ sections.push(' 2. Appropriate agent assignment for each task');
147
+ sections.push(' 3. Completeness (all aspects of the goal covered)');
148
+ sections.push(' 4. Step granularity (not too coarse, not too fine)');
149
+ sections.push(' 5. Final integration step is present');
150
+ sections.push('');
151
+ sections.push('--- AVAILABLE AGENTS ---');
152
+ for (const agent of this.availableAgents) {
153
+ sections.push(` ${agent.name}: ${agent.purpose}`);
154
+ }
155
+ sections.push('');
156
+ sections.push('--- PLAN TO REVIEW ---');
157
+ sections.push(JSON.stringify(plan, null, 2));
158
+ sections.push('');
159
+ sections.push('--- INSTRUCTIONS ---');
160
+ sections.push('Output only a revised JSON plan object if changes are needed,');
161
+ sections.push('or respond with "PLAN_APPROVED" if the plan is already good.');
162
+ sections.push('Do not add commentary outside of a valid JSON block or PLAN_APPROVED.');
163
+ return sections.join('\n');
164
+ }
165
+ /**
166
+ * Run an LLM-assisted review via Copilot CLI session.
167
+ * Falls back to local review if the session fails.
168
+ */
169
+ async reviewPlanWithLLM(plan, sessionOptions, outputDir) {
170
+ const start = Date.now();
171
+ // Always run local review first
172
+ const localResult = this.reviewPlan(plan);
173
+ const prompt = this.buildReviewPrompt(plan);
174
+ const transcriptPath = path.join(outputDir, 'pm-review-transcript.md');
175
+ if (!fs.existsSync(outputDir)) {
176
+ fs.mkdirSync(outputDir, { recursive: true });
177
+ }
178
+ const opts = {
179
+ ...sessionOptions,
180
+ shareToFile: transcriptPath,
181
+ logPrefix: '[PM-AGENT]'
182
+ };
183
+ try {
184
+ const executor = new session_executor_1.default();
185
+ const result = await executor.executeSession(prompt, opts);
186
+ if (!result.success) {
187
+ // Fall back to local-only review
188
+ return {
189
+ ...localResult,
190
+ reviewNotes: [...localResult.reviewNotes, 'LLM review failed, using local review only'],
191
+ durationMs: Date.now() - start
192
+ };
193
+ }
194
+ // Try to parse revised plan from output
195
+ const revised = this.parseRevisedPlan(result.output, plan);
196
+ if (revised) {
197
+ return {
198
+ revisedPlan: revised,
199
+ reviewNotes: [...localResult.reviewNotes, 'LLM review applied changes'],
200
+ changesApplied: [...localResult.changesApplied, 'LLM-revised plan'],
201
+ durationMs: Date.now() - start,
202
+ estimatedTokenCost: Math.ceil((prompt.length + (result.output?.length || 0)) / CHARS_PER_TOKEN),
203
+ skipped: false
204
+ };
205
+ }
206
+ // PLAN_APPROVED or unparseable output - use local result
207
+ return {
208
+ ...localResult,
209
+ reviewNotes: [...localResult.reviewNotes, 'LLM approved plan without changes'],
210
+ durationMs: Date.now() - start
211
+ };
212
+ }
213
+ catch (err) {
214
+ const msg = err instanceof Error ? err.message : String(err);
215
+ logger.warn(`[pm-agent] LLM review failed, using local review only: ${msg}`);
216
+ return {
217
+ ...localResult,
218
+ reviewNotes: [...localResult.reviewNotes, 'LLM review unavailable, using local review only'],
219
+ durationMs: Date.now() - start
220
+ };
221
+ }
222
+ }
223
+ /**
224
+ * Detect circular dependencies in plan steps.
225
+ * Returns step numbers involved in cycles.
226
+ */
227
+ detectCircularDeps(steps) {
228
+ const visited = new Set();
229
+ const inStack = new Set();
230
+ const cycleSteps = [];
231
+ const stepMap = new Map(steps.map(s => [s.stepNumber, s]));
232
+ const dfs = (stepNum) => {
233
+ if (inStack.has(stepNum)) {
234
+ cycleSteps.push(stepNum);
235
+ return true;
236
+ }
237
+ if (visited.has(stepNum))
238
+ return false;
239
+ visited.add(stepNum);
240
+ inStack.add(stepNum);
241
+ const step = stepMap.get(stepNum);
242
+ if (step) {
243
+ for (const dep of step.dependencies) {
244
+ if (dfs(dep)) {
245
+ cycleSteps.push(stepNum);
246
+ return true;
247
+ }
248
+ }
249
+ }
250
+ inStack.delete(stepNum);
251
+ return false;
252
+ };
253
+ for (const step of steps) {
254
+ dfs(step.stepNumber);
255
+ }
256
+ return [...new Set(cycleSteps)];
257
+ }
258
+ /**
259
+ * Try to parse a revised plan from LLM output.
260
+ * Returns null if output does not contain a valid plan JSON.
261
+ */
262
+ parseRevisedPlan(output, originalPlan) {
263
+ if (!output || output.includes('PLAN_APPROVED'))
264
+ return null;
265
+ // Try to extract JSON from the output
266
+ const jsonMatch = output.match(/\{[\s\S]*"steps"[\s\S]*\}/);
267
+ if (!jsonMatch)
268
+ return null;
269
+ try {
270
+ const parsed = JSON.parse(jsonMatch[0]);
271
+ if (parsed.steps && Array.isArray(parsed.steps)) {
272
+ return {
273
+ goal: parsed.goal || originalPlan.goal,
274
+ createdAt: originalPlan.createdAt,
275
+ steps: parsed.steps,
276
+ metadata: {
277
+ totalSteps: parsed.steps.length,
278
+ estimatedDuration: parsed.metadata?.estimatedDuration
279
+ }
280
+ };
281
+ }
282
+ }
283
+ catch {
284
+ // LLM output is not valid JSON; expected when model returns prose instead of structured data
285
+ }
286
+ return null;
287
+ }
288
+ /**
289
+ * Deep-copy a plan to avoid mutating the original.
290
+ */
291
+ deepCopyPlan(plan) {
292
+ return JSON.parse(JSON.stringify(plan));
293
+ }
294
+ }
295
+ exports.PMAgent = PMAgent;
296
+ exports.default = PMAgent;
@@ -0,0 +1,203 @@
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.runPostExecution = runPostExecution;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const logger_1 = require("./logger");
43
+ const analytics_log_1 = __importDefault(require("./analytics-log"));
44
+ const external_tool_manager_1 = __importDefault(require("./external-tool-manager"));
45
+ const deployment_manager_1 = __importDefault(require("./deployment-manager"));
46
+ const pr_automation_1 = __importDefault(require("./pr-automation"));
47
+ const adapters_1 = require("./adapters");
48
+ const logger = (0, logger_1.getLogger)('post-run');
49
+ async function runPostExecution(workingDir, runDir, context, plan, options) {
50
+ // Finalize metrics and save to analytics log
51
+ if (context.metricsCollector) {
52
+ const metrics = context.metricsCollector.finalize();
53
+ // Save metrics to run directory
54
+ const metricsPath = path.join(runDir, 'metrics.json');
55
+ fs.writeFileSync(metricsPath, JSON.stringify(metrics, null, 2), 'utf8');
56
+ // Append to analytics log
57
+ const analyticsLog = new analytics_log_1.default();
58
+ analyticsLog.appendRun(metrics);
59
+ logger.debug(`metrics ${metricsPath}`);
60
+ // Save cost attribution alongside metrics
61
+ if (context.costEstimate && context.stepCostRecords) {
62
+ const modelName = options?.model || (0, adapters_1.defaultModelForAdapter)(options?.cliAgent);
63
+ const totalEstimated = context.costEstimate.totalPremiumRequests;
64
+ const totalActual = context.stepCostRecords.reduce((s, r) => s + r.actualPremiumRequests, 0);
65
+ const attribution = {
66
+ totalEstimatedPremiumRequests: totalEstimated,
67
+ totalActualPremiumRequests: totalActual,
68
+ estimateAccuracy: context.costEstimator?.getAccuracy() ?? 1.0,
69
+ modelUsed: modelName,
70
+ modelMultiplier: context.costEstimate.modelMultiplier,
71
+ overageTriggered: context.costEstimate.overageCostUSD > 0,
72
+ perStep: context.stepCostRecords,
73
+ };
74
+ const costPath = path.join(runDir, 'cost-attribution.json');
75
+ fs.writeFileSync(costPath, JSON.stringify(attribution, null, 2), 'utf8');
76
+ }
77
+ // Persist session state for audit/resume support
78
+ // Use the runDir basename as session ID so it matches the directory
79
+ // the CLI created (context.executionId differs by a few ms)
80
+ const runDirId = path.basename(runDir);
81
+ const completedSteps = context.results.filter(r => r.status === 'completed');
82
+ const sessionState = {
83
+ sessionId: runDirId,
84
+ graph: {
85
+ goal: plan.goal,
86
+ steps: plan.steps.map(s => ({ stepNumber: s.stepNumber, task: s.task, agent: s.agentName }))
87
+ },
88
+ branchMap: Object.fromEntries(context.results
89
+ .filter(r => r.branchName)
90
+ .map(r => [String(r.stepNumber), r.branchName])),
91
+ transcripts: Object.fromEntries(context.results
92
+ .filter(r => r.sessionResult?.transcriptPath)
93
+ .map(r => [String(r.stepNumber), r.sessionResult.transcriptPath])),
94
+ metrics: metrics,
95
+ gateResults: context.finalGateResults || [],
96
+ status: completedSteps.length === plan.steps.length ? 'completed' : 'failed',
97
+ lastCompletedStep: Math.max(0, ...completedSteps.map(r => r.stepNumber))
98
+ };
99
+ // Write directly to runDir (saveSession uses cwd which differs for demos)
100
+ fs.writeFileSync(path.join(runDir, 'session-state.json'), JSON.stringify(sessionState, null, 2), 'utf8');
101
+ // Also persist via collector so audit/metrics CLI can find it from project root
102
+ context.metricsCollector.saveSession(runDirId, sessionState);
103
+ }
104
+ // OWASP ASI compliance report (when --owasp-report is set)
105
+ if (options?.owaspReport) {
106
+ try {
107
+ const { OwaspMapper } = await Promise.resolve().then(() => __importStar(require('./owasp-mapper')));
108
+ const { OwaspReportRenderer } = await Promise.resolve().then(() => __importStar(require('./owasp-report-renderer')));
109
+ const verificationResults = context.results
110
+ .map(r => r.verificationResult)
111
+ .filter((v) => v !== undefined);
112
+ const repaired = context.results.filter(r => (r.retryCount ?? 0) > 0 && r.status === 'completed').length;
113
+ const failed = context.results.filter(r => r.status === 'failed').length;
114
+ const completed = context.results.filter(r => r.status === 'completed').length;
115
+ const passed = completed - repaired;
116
+ const exhausted = context.results.filter(r => r.status === 'failed' && (r.retryCount ?? 0) > 0).length;
117
+ // Read version from package.json at project root
118
+ let toolVersion = '4.1.0';
119
+ try {
120
+ const pkgPath = path.join(__dirname, '..', 'package.json');
121
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
122
+ toolVersion = pkg.version || toolVersion;
123
+ }
124
+ catch {
125
+ // Fall back to hardcoded version if package.json is unavailable
126
+ }
127
+ const meta = {
128
+ executionId: context.executionId,
129
+ toolVersion,
130
+ strictIsolation: !!options.strictIsolation,
131
+ adapterType: options.cliAgent || 'copilot',
132
+ totalSteps: plan.steps.length,
133
+ passedSteps: passed,
134
+ repairedSteps: repaired,
135
+ failedSteps: failed,
136
+ retriesExhausted: exhausted,
137
+ };
138
+ const mapper = new OwaspMapper();
139
+ const complianceReport = mapper.map(verificationResults, meta);
140
+ fs.writeFileSync(path.join(runDir, 'owasp-compliance.md'), OwaspReportRenderer.toMarkdown(complianceReport), 'utf8');
141
+ fs.writeFileSync(path.join(runDir, 'owasp-compliance.json'), OwaspReportRenderer.toJson(complianceReport), 'utf8');
142
+ logger.info(` OWASP ASI: ${complianceReport.mitigatedRisks}/${complianceReport.applicableRisks} applicable risks mitigated`);
143
+ }
144
+ catch (owaspErr) {
145
+ logger.warn(` OWASP report generation failed: ${owaspErr instanceof Error ? owaspErr.message : owaspErr}`);
146
+ }
147
+ }
148
+ // Record execution in knowledge base
149
+ if (context.knowledgeBase) {
150
+ const totalPatternsDetected = context.waveAnalyses?.reduce((sum, analysis) => sum + analysis.detectedPatterns.length, 0) || 0;
151
+ context.knowledgeBase.recordRun(totalPatternsDetected);
152
+ // Record cost history for future estimation calibration
153
+ if (context.costEstimate && context.stepCostRecords) {
154
+ const modelName = options?.model || (0, adapters_1.defaultModelForAdapter)(options?.cliAgent);
155
+ const totalRetries = context.stepCostRecords.reduce((s, r) => s + r.retryCount, 0);
156
+ const totalActual = context.stepCostRecords.reduce((s, r) => s + r.actualPremiumRequests, 0);
157
+ const totalEstimated = context.costEstimate.totalPremiumRequests;
158
+ const evidence = {
159
+ runId: context.executionId,
160
+ estimated: totalEstimated,
161
+ actual: totalActual,
162
+ retries: totalRetries,
163
+ steps: plan.steps.length,
164
+ model: modelName,
165
+ };
166
+ context.knowledgeBase.addOrUpdatePattern({
167
+ category: 'cost_history',
168
+ insight: `${plan.steps.length} steps, model ${modelName}, ${totalActual} premium requests, ${totalRetries} retries`,
169
+ confidence: 'high',
170
+ evidence: [JSON.stringify(evidence)],
171
+ impact: 'medium',
172
+ });
173
+ }
174
+ }
175
+ // Auto-create PR if requested
176
+ if (options?.autoPR) {
177
+ logger.info('\nšŸ“ Creating PR...');
178
+ try {
179
+ const toolManager = new external_tool_manager_1.default({
180
+ enableExternal: options.enableExternal || false,
181
+ dryRun: options.dryRun || false,
182
+ logFile: path.join(runDir, 'external-commands.log')
183
+ });
184
+ const deploymentManager = new deployment_manager_1.default(toolManager, workingDir);
185
+ const prAutomation = new pr_automation_1.default(toolManager, workingDir);
186
+ const deployments = deploymentManager.loadDeploymentMetadata(runDir);
187
+ // generatePRSummary accepts a narrow PRSummaryContext (duck-typed in
188
+ // pr-automation.ts). `mainBranch` on the PostRunContext feeds
189
+ // PRSummary.baseBranch; plan fills in plan.goal.
190
+ const summary = prAutomation.generatePRSummary({ ...context, plan }, deployments);
191
+ const prResult = await prAutomation.createPR(summary);
192
+ if (prResult.success) {
193
+ logger.info(`āœ… PR created: ${prResult.url}`);
194
+ }
195
+ else {
196
+ logger.warn(`āš ļø PR creation failed: ${prResult.error}`);
197
+ }
198
+ }
199
+ catch (error) {
200
+ logger.warn(`āš ļø PR automation error: ${error instanceof Error ? error.message : error}`);
201
+ }
202
+ }
203
+ }
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PRAutomation = void 0;
4
+ /**
5
+ * PR Automation - auto-creates PRs with execution summaries
6
+ */
7
+ class PRAutomation {
8
+ toolManager;
9
+ workingDir;
10
+ constructor(toolManager, workingDir) {
11
+ this.toolManager = toolManager;
12
+ this.workingDir = workingDir || process.cwd();
13
+ }
14
+ /**
15
+ * Generate PR summary from execution context
16
+ */
17
+ generatePRSummary(context, deployments) {
18
+ const completedSteps = context.results.filter(r => r.status === 'completed').length;
19
+ const failedSteps = context.results.filter(r => r.status === 'failed').length;
20
+ const totalSteps = context.results.length;
21
+ let body = '## Swarm Execution Summary\n\n';
22
+ body += `**Execution ID:** \`${context.executionId}\`\n`;
23
+ body += `**Goal:** ${context.plan.goal}\n`;
24
+ body += `**Completed:** ${completedSteps}/${totalSteps} steps\n\n`;
25
+ if (failedSteps > 0) {
26
+ body += `āš ļø **${failedSteps} step(s) failed**\n\n`;
27
+ }
28
+ // Add deployment links
29
+ if (deployments.length > 0) {
30
+ body += '## šŸš€ Preview Deployments\n\n';
31
+ for (const deployment of deployments) {
32
+ if (deployment.previewUrl) {
33
+ body += `- **${deployment.platform}** (Step ${deployment.stepNumber}): ${deployment.previewUrl}\n`;
34
+ }
35
+ }
36
+ body += '\n';
37
+ }
38
+ // Add step details
39
+ body += '## Steps Executed\n\n';
40
+ for (const result of context.results) {
41
+ const icon = result.status === 'completed' ? 'āœ…' :
42
+ result.status === 'failed' ? 'āŒ' :
43
+ result.status === 'running' ? '🚧' : 'āø';
44
+ body += `${icon} **Step ${result.stepNumber}** (${result.agentName}): ${result.status}\n`;
45
+ if (result.verificationResult) {
46
+ const passed = result.verificationResult.passed ? 'āœ“' : 'āœ—';
47
+ body += ` - Verification: ${passed} ${result.verificationResult.passed ? 'passed' : 'failed'}\n`;
48
+ }
49
+ }
50
+ body += '\n---\n';
51
+ body += `*Generated by Swarm Orchestrator*\n`;
52
+ return {
53
+ title: `[Swarm] ${context.plan.goal}`,
54
+ body,
55
+ baseBranch: context.mainBranch,
56
+ headBranch: `swarm/${context.executionId}`
57
+ };
58
+ }
59
+ /**
60
+ * Create PR via gh CLI
61
+ */
62
+ async createPR(summary) {
63
+ const tools = await this.toolManager.detectAvailableTools();
64
+ if (!tools.gh) {
65
+ return {
66
+ success: false,
67
+ error: 'gh CLI not available'
68
+ };
69
+ }
70
+ // Create PR
71
+ const execution = await this.toolManager.executeCommand('gh', [
72
+ 'pr', 'create',
73
+ '--base', summary.baseBranch,
74
+ '--head', summary.headBranch,
75
+ '--title', summary.title,
76
+ '--body', summary.body
77
+ ], {
78
+ workingDir: this.workingDir,
79
+ requireTool: 'gh'
80
+ });
81
+ if (execution.exitCode !== 0) {
82
+ return {
83
+ success: false,
84
+ error: execution.error || 'Failed to create PR'
85
+ };
86
+ }
87
+ // Extract PR URL from output
88
+ const url = this.extractPRUrl(execution.output || '');
89
+ return {
90
+ success: true,
91
+ ...(url && { url })
92
+ };
93
+ }
94
+ /**
95
+ * Extract PR URL from gh CLI output
96
+ */
97
+ extractPRUrl(output) {
98
+ const match = output.match(/(https:\/\/github\.com\/[^\s]+)/);
99
+ return match ? match[1] : undefined;
100
+ }
101
+ }
102
+ exports.PRAutomation = PRAutomation;
103
+ exports.default = PRAutomation;