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.
- package/LICENSE +15 -0
- package/README.md +199 -0
- package/agents/reviewer.agent.md +50 -0
- package/agents/worker.agent.md +41 -0
- package/config/default-agents.yaml +56 -0
- package/config/pm-agent.yaml +36 -0
- package/config/quality-gates.yaml +88 -0
- package/config/repair-agent.yaml +34 -0
- package/config/semgrep-rules/complexity-mismatch.yaml +6 -0
- package/config/semgrep-rules/exception-swallowing.yaml +13 -0
- package/config/semgrep-rules/hardcoded-answer.yaml +6 -0
- package/config/semgrep-rules/mock-mutation.yaml +6 -0
- package/config/semgrep-rules/test-modification.yaml +6 -0
- package/config/user-agents.yaml +23 -0
- package/dist/src/adapters/adapter-factory.js +29 -0
- package/dist/src/adapters/agent-adapter.js +32 -0
- package/dist/src/adapters/claude-code-adapter.js +126 -0
- package/dist/src/adapters/claude-code-teams.js +119 -0
- package/dist/src/adapters/codex-adapter.js +118 -0
- package/dist/src/adapters/copilot-adapter.js +224 -0
- package/dist/src/adapters/fatal-error-classifier.js +88 -0
- package/dist/src/adapters/index.js +44 -0
- package/dist/src/adapters/persistent-session.js +204 -0
- package/dist/src/adapters/process-supervisor.js +199 -0
- package/dist/src/agents-exporter.js +398 -0
- package/dist/src/analytics-log.js +161 -0
- package/dist/src/baseline-scanner.js +65 -0
- package/dist/src/bootstrap-evidence.js +88 -0
- package/dist/src/bootstrap-orchestrator.js +205 -0
- package/dist/src/bootstrap-types.js +5 -0
- package/dist/src/branch-merger.js +427 -0
- package/dist/src/cli/attest-handlers.js +44 -0
- package/dist/src/cli/cost-prompt.js +51 -0
- package/dist/src/cli/demo-handlers.js +274 -0
- package/dist/src/cli/flags.js +152 -0
- package/dist/src/cli/index.js +57 -0
- package/dist/src/cli/live-status.js +186 -0
- package/dist/src/cli/misc-handlers.js +242 -0
- package/dist/src/cli/plan-handlers.js +350 -0
- package/dist/src/cli/share-handlers.js +163 -0
- package/dist/src/cli/status-handlers.js +457 -0
- package/dist/src/cli/swarm-handlers.js +638 -0
- package/dist/src/cli/usage.js +72 -0
- package/dist/src/cli.js +217 -0
- package/dist/src/commit-pattern-detector.js +143 -0
- package/dist/src/commit-quality-analyzer.js +38 -0
- package/dist/src/config-loader.js +339 -0
- package/dist/src/context-broker.js +358 -0
- package/dist/src/copilot-cli-wrapper.js +258 -0
- package/dist/src/cost-estimator.js +241 -0
- package/dist/src/defaults.js +18 -0
- package/dist/src/demo-mode.js +180 -0
- package/dist/src/deployment-handler.js +78 -0
- package/dist/src/deployment-manager.js +228 -0
- package/dist/src/execution-queue.js +196 -0
- package/dist/src/external-tool-manager.js +184 -0
- package/dist/src/gate-prompt-builder.js +117 -0
- package/dist/src/gate-remediation.js +173 -0
- package/dist/src/github-issues-ingester.js +152 -0
- package/dist/src/github-mcp-integrator.js +164 -0
- package/dist/src/hook-generator.js +229 -0
- package/dist/src/index.js +48 -0
- package/dist/src/knowledge-base.js +300 -0
- package/dist/src/logger.js +111 -0
- package/dist/src/meta-analyzer.js +208 -0
- package/dist/src/metrics-collector.js +209 -0
- package/dist/src/metrics-types.js +5 -0
- package/dist/src/multi-repo-coordinator.js +179 -0
- package/dist/src/orchestrator/async-meta-analysis.js +84 -0
- package/dist/src/orchestrator/fatal-run-error.js +43 -0
- package/dist/src/orchestrator/final-gates-remediation.js +258 -0
- package/dist/src/orchestrator/git-state-utils.js +119 -0
- package/dist/src/orchestrator/pause-controller.js +55 -0
- package/dist/src/orchestrator/replan-runner.js +258 -0
- package/dist/src/orchestrator/step-executor.js +391 -0
- package/dist/src/orchestrator/wave-scheduler-loop.js +204 -0
- package/dist/src/owasp-mapper.js +153 -0
- package/dist/src/owasp-report-renderer.js +39 -0
- package/dist/src/plan-files.js +142 -0
- package/dist/src/plan-generator.js +1207 -0
- package/dist/src/pm-agent.js +296 -0
- package/dist/src/post-run-reporter.js +203 -0
- package/dist/src/pr-automation.js +103 -0
- package/dist/src/pr-manager.js +318 -0
- package/dist/src/presenter/index.js +209 -0
- package/dist/src/prompt-builder.js +173 -0
- package/dist/src/quality-gates/config-loader.js +196 -0
- package/dist/src/quality-gates/default-config.js +243 -0
- package/dist/src/quality-gates/file-utils.js +152 -0
- package/dist/src/quality-gates/gate-runner.js +171 -0
- package/dist/src/quality-gates/gates/accessibility.js +355 -0
- package/dist/src/quality-gates/gates/duplicate-blocks.js +144 -0
- package/dist/src/quality-gates/gates/hardcoded-config.js +52 -0
- package/dist/src/quality-gates/gates/readme-claims.js +62 -0
- package/dist/src/quality-gates/gates/runtime-checks.js +265 -0
- package/dist/src/quality-gates/gates/scaffold-defaults.js +108 -0
- package/dist/src/quality-gates/gates/test-coverage.js +240 -0
- package/dist/src/quality-gates/gates/test-file-protection.js +85 -0
- package/dist/src/quality-gates/gates/test-isolation.js +74 -0
- package/dist/src/quality-gates/index.js +17 -0
- package/dist/src/quality-gates/registry.js +205 -0
- package/dist/src/quality-gates/types.js +2 -0
- package/dist/src/quick-fix-mode.js +302 -0
- package/dist/src/recipe-loader.js +122 -0
- package/dist/src/repair-agent.js +396 -0
- package/dist/src/repo-analyzer.js +342 -0
- package/dist/src/report-generator.js +146 -0
- package/dist/src/report-renderer.js +90 -0
- package/dist/src/requirement-filter.js +52 -0
- package/dist/src/sarif-formatter.js +140 -0
- package/dist/src/scheduling/dependency-analyzer.js +178 -0
- package/dist/src/scheduling/work-stealing-queue.js +123 -0
- package/dist/src/secret-redactor.js +90 -0
- package/dist/src/session-executor.js +587 -0
- package/dist/src/session-manager.js +221 -0
- package/dist/src/share/transcript-verification.js +128 -0
- package/dist/src/share-parser.js +477 -0
- package/dist/src/spinner.js +146 -0
- package/dist/src/step-runner.js +365 -0
- package/dist/src/swarm-orchestrator.js +686 -0
- package/dist/src/task-classifier.js +134 -0
- package/dist/src/test-command-discovery.js +123 -0
- package/dist/src/text-similarity.js +24 -0
- package/dist/src/tier-maps.js +158 -0
- package/dist/src/types.js +5 -0
- package/dist/src/url-shortener.js +135 -0
- package/dist/src/verification/attestation.js +166 -0
- package/dist/src/verification/cheat-detector.js +240 -0
- package/dist/src/verification/command-runner.js +70 -0
- package/dist/src/verification/composite-score.js +157 -0
- package/dist/src/verification/cosign-attestation.js +137 -0
- package/dist/src/verification/diff-analysis.js +89 -0
- package/dist/src/verification/differential-gate.js +173 -0
- package/dist/src/verification/index.js +41 -0
- package/dist/src/verification/mutation-gate.js +242 -0
- package/dist/src/verification/property-gate.js +201 -0
- package/dist/src/verification/test-synthesizer.js +243 -0
- package/dist/src/verifier/outcome-checks.js +396 -0
- package/dist/src/verifier/transcript-checks.js +207 -0
- package/dist/src/verifier/verification-reporters.js +148 -0
- package/dist/src/verifier-engine.js +491 -0
- package/dist/src/wave-resizer.js +131 -0
- package/dist/src/wave-scheduler.js +44 -0
- package/dist/src/worktree-manager.js +368 -0
- package/dist/src/worktree-reserved-paths.js +97 -0
- package/package.json +80 -0
- package/plugin/agents/.gitkeep +0 -0
- package/plugin/agents/backend_master.agent.md +72 -0
- package/plugin/agents/devops_pro.agent.md +45 -0
- package/plugin/agents/frontend_expert.agent.md +59 -0
- package/plugin/agents/integrator_finalizer.agent.md +44 -0
- package/plugin/agents/meta_reviewer.agent.md +44 -0
- package/plugin/agents/security_auditor.agent.md +43 -0
- package/plugin/agents/tester_elite.agent.md +43 -0
- package/plugin/hooks/hooks.json +19 -0
- package/plugin/hooks/post-tool-use.json +9 -0
- package/plugin/hooks/pre-tool-use.json +9 -0
- package/plugin/plugin.json +47 -0
- package/plugin/skills/swarm-gates/SKILL.md +53 -0
- package/plugin/skills/swarm-orchestrate/SKILL.md +34 -0
- package/plugin/skills/swarm-verify/SKILL.md +44 -0
- package/templates/README.md +35 -0
- package/templates/cli-tool.json +31 -0
- package/templates/fullstack.json +52 -0
- package/templates/library.json +38 -0
- package/templates/react-app.json +45 -0
- package/templates/recipes/add-api-docs.json +35 -0
- package/templates/recipes/add-auth.json +47 -0
- package/templates/recipes/add-ci.json +39 -0
- package/templates/recipes/add-tests.json +39 -0
- package/templates/recipes/migrate-to-ts.json +42 -0
- package/templates/recipes/refactor-modularize.json +44 -0
- package/templates/recipes/security-audit.json +35 -0
- package/templates/rest-api.json +38 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Quick-Fix Mode
|
|
4
|
+
*
|
|
5
|
+
* Bypasses full swarm orchestration for simple, single-agent tasks.
|
|
6
|
+
* Provides faster execution for:
|
|
7
|
+
* - Single file changes
|
|
8
|
+
* - Documentation updates
|
|
9
|
+
* - Bug fixes
|
|
10
|
+
* - Simple refactoring
|
|
11
|
+
*
|
|
12
|
+
* Uses heuristics to determine if a task is "quick-fix eligible"
|
|
13
|
+
*/
|
|
14
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
17
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
18
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
19
|
+
}
|
|
20
|
+
Object.defineProperty(o, k2, desc);
|
|
21
|
+
}) : (function(o, m, k, k2) {
|
|
22
|
+
if (k2 === undefined) k2 = k;
|
|
23
|
+
o[k2] = m[k];
|
|
24
|
+
}));
|
|
25
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
26
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
27
|
+
}) : function(o, v) {
|
|
28
|
+
o["default"] = v;
|
|
29
|
+
});
|
|
30
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
31
|
+
var ownKeys = function(o) {
|
|
32
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
33
|
+
var ar = [];
|
|
34
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
35
|
+
return ar;
|
|
36
|
+
};
|
|
37
|
+
return ownKeys(o);
|
|
38
|
+
};
|
|
39
|
+
return function (mod) {
|
|
40
|
+
if (mod && mod.__esModule) return mod;
|
|
41
|
+
var result = {};
|
|
42
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
43
|
+
__setModuleDefault(result, mod);
|
|
44
|
+
return result;
|
|
45
|
+
};
|
|
46
|
+
})();
|
|
47
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
48
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
49
|
+
};
|
|
50
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
+
exports.QuickFixMode = void 0;
|
|
52
|
+
const fs = __importStar(require("fs"));
|
|
53
|
+
const path = __importStar(require("path"));
|
|
54
|
+
const config_loader_1 = require("./config-loader");
|
|
55
|
+
const session_executor_1 = __importDefault(require("./session-executor"));
|
|
56
|
+
const verifier_engine_1 = __importDefault(require("./verifier-engine"));
|
|
57
|
+
const logger_1 = require("./logger");
|
|
58
|
+
const logger = (0, logger_1.getLogger)('quick-fix-mode');
|
|
59
|
+
/**
|
|
60
|
+
* Quick-fix mode for single-agent bypass
|
|
61
|
+
*/
|
|
62
|
+
class QuickFixMode {
|
|
63
|
+
configLoader;
|
|
64
|
+
sessionExecutor;
|
|
65
|
+
verifier;
|
|
66
|
+
constructor(workingDir) {
|
|
67
|
+
this.configLoader = new config_loader_1.ConfigLoader();
|
|
68
|
+
this.sessionExecutor = new session_executor_1.default(workingDir);
|
|
69
|
+
this.verifier = new verifier_engine_1.default(workingDir);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Determine if a task is eligible for quick-fix mode
|
|
73
|
+
*/
|
|
74
|
+
isQuickFixEligible(task) {
|
|
75
|
+
const taskLower = task.toLowerCase();
|
|
76
|
+
// Indicators that suggest quick-fix is appropriate
|
|
77
|
+
const quickFixPatterns = [
|
|
78
|
+
{ pattern: /^(fix|update|change|modify)\s+(a|an|the)?\s*single\s+file/i, agent: 'backend_master', reason: 'Single file modification' },
|
|
79
|
+
{ pattern: /^update\s+(readme|documentation|docs?|changelog)/i, agent: 'integrator_finalizer', reason: 'Documentation update' },
|
|
80
|
+
{ pattern: /^fix\s+(typo|spelling|grammar)/i, agent: 'integrator_finalizer', reason: 'Typo fix' },
|
|
81
|
+
{ pattern: /^add\s+(comment|comments|docstring)/i, agent: 'backend_master', reason: 'Adding comments' },
|
|
82
|
+
{ pattern: /^remove\s+(unused|dead)\s+code/i, agent: 'backend_master', reason: 'Code cleanup' },
|
|
83
|
+
{ pattern: /^rename\s+(variable|function|class|file)/i, agent: 'backend_master', reason: 'Renaming' },
|
|
84
|
+
{ pattern: /^fix\s+linting?\s+(error|warning)/i, agent: 'backend_master', reason: 'Linting fix' },
|
|
85
|
+
{ pattern: /^update\s+(dependency|package|version)/i, agent: 'backend_master', reason: 'Dependency update' },
|
|
86
|
+
{ pattern: /^fix\s+simple\s+bug/i, agent: 'backend_master', reason: 'Simple bug fix' }
|
|
87
|
+
];
|
|
88
|
+
for (const { pattern, agent, reason } of quickFixPatterns) {
|
|
89
|
+
if (pattern.test(task)) {
|
|
90
|
+
return { eligible: true, reason, suggestedAgent: agent };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Indicators that suggest full swarm is needed
|
|
94
|
+
const fullSwarmPatterns = [
|
|
95
|
+
{ pattern: /\band\b/g, reason: 'Multiple tasks in one request', checkCount: true }, // Check this FIRST
|
|
96
|
+
{ pattern: /multiple\s+(files|components|modules|services)/i, reason: 'Multiple components involved' },
|
|
97
|
+
{ pattern: /\b(architecture|design|refactor|restructure)\b/i, reason: 'Architectural change needed' },
|
|
98
|
+
{ pattern: /\b(implement|build|create)\s+.*(feature|system|module|service)\b/i, reason: 'New feature implementation' },
|
|
99
|
+
{ pattern: /\b(test|testing|e2e|integration)\b.*\b(suite|coverage|framework)\b/i, reason: 'Comprehensive testing needed' },
|
|
100
|
+
{ pattern: /\b(deploy|deployment|ci\/cd|pipeline)\b/i, reason: 'Deployment/infrastructure work' },
|
|
101
|
+
{ pattern: /\b(security|audit|vulnerability)\b.*\b(review|scan|check)\b/i, reason: 'Security review needed' }
|
|
102
|
+
];
|
|
103
|
+
for (const item of fullSwarmPatterns) {
|
|
104
|
+
const { pattern, reason } = item;
|
|
105
|
+
if (pattern.test(taskLower)) {
|
|
106
|
+
// Special case: count "and"s
|
|
107
|
+
if ('checkCount' in item && item.checkCount) {
|
|
108
|
+
const andCount = (taskLower.match(/\band\b/g) || []).length;
|
|
109
|
+
if (andCount >= 3) { // 3 or more "and"s means 4+ tasks
|
|
110
|
+
return { eligible: false, reason: `Multiple tasks detected (${andCount} "and"s)` };
|
|
111
|
+
}
|
|
112
|
+
// Otherwise, 1-2 "and"s is ok, continue checking other patterns
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
return { eligible: false, reason };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Default: if task is short and simple, allow quick-fix
|
|
119
|
+
if (task.length < 100 && task.split(' ').length < 15) {
|
|
120
|
+
return {
|
|
121
|
+
eligible: true,
|
|
122
|
+
reason: 'Task is short and simple',
|
|
123
|
+
suggestedAgent: 'backend_master' // default agent
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
eligible: false,
|
|
128
|
+
reason: 'Task complexity suggests full swarm orchestration'
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Execute a task in quick-fix mode
|
|
133
|
+
*/
|
|
134
|
+
async execute(task, options = {}) {
|
|
135
|
+
const startTime = Date.now();
|
|
136
|
+
// Check eligibility
|
|
137
|
+
const eligibility = this.isQuickFixEligible(task);
|
|
138
|
+
if (!eligibility.eligible) {
|
|
139
|
+
return {
|
|
140
|
+
success: false,
|
|
141
|
+
agentUsed: 'none',
|
|
142
|
+
output: `⚠️ Quick-fix mode not recommended for this task.\nReason: ${eligibility.reason}\n\nUse full swarm mode instead:\n swarm plan "${task}"\n swarm swarm plan.json`,
|
|
143
|
+
duration: Date.now() - startTime,
|
|
144
|
+
wasQuickFixEligible: false,
|
|
145
|
+
reason: eligibility.reason
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
// Determine which agent to use
|
|
149
|
+
const agentName = options.agent || eligibility.suggestedAgent || 'backend_master';
|
|
150
|
+
let agentProfile;
|
|
151
|
+
try {
|
|
152
|
+
const agents = await this.configLoader.loadAllAgents();
|
|
153
|
+
agentProfile = agents.find((a) => a.name === agentName || config_loader_1.ConfigLoader.normalizeAgentName(a.name) === config_loader_1.ConfigLoader.normalizeAgentName(agentName));
|
|
154
|
+
if (!agentProfile) {
|
|
155
|
+
return {
|
|
156
|
+
success: false,
|
|
157
|
+
agentUsed: agentName,
|
|
158
|
+
output: `Agent "${agentName}" not found. Available agents: ${agents.map(a => a.name).join(', ')}`,
|
|
159
|
+
duration: Date.now() - startTime,
|
|
160
|
+
wasQuickFixEligible: true,
|
|
161
|
+
reason: 'Agent not found'
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
return {
|
|
167
|
+
success: false,
|
|
168
|
+
agentUsed: agentName,
|
|
169
|
+
output: `Failed to load agents: ${error instanceof Error ? error.message : String(error)}`,
|
|
170
|
+
duration: Date.now() - startTime,
|
|
171
|
+
wasQuickFixEligible: true,
|
|
172
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
logger.info(`⚡ Quick-fix mode: ${eligibility.reason}`);
|
|
176
|
+
logger.info(` Agent: ${agentProfile.name}`);
|
|
177
|
+
logger.info(` Task: ${task}\n`);
|
|
178
|
+
// Build prompt for the agent
|
|
179
|
+
const prompt = this.buildQuickFixPrompt(task, agentProfile);
|
|
180
|
+
// Set up session options
|
|
181
|
+
const workingDir = options.workingDir || process.cwd();
|
|
182
|
+
const transcriptPath = path.join(workingDir, '.quickfix', `quickfix-${Date.now()}.md`);
|
|
183
|
+
// Ensure .quickfix directory exists
|
|
184
|
+
const quickfixDir = path.dirname(transcriptPath);
|
|
185
|
+
if (!fs.existsSync(quickfixDir)) {
|
|
186
|
+
fs.mkdirSync(quickfixDir, { recursive: true });
|
|
187
|
+
}
|
|
188
|
+
// Only use --agent flag if the agent file exists in the target repo
|
|
189
|
+
const agentSlug = agentProfile.name.toLowerCase().replace(/\s+/g, '_');
|
|
190
|
+
const agentFilePath = path.join(workingDir, '.github', 'agents', `${agentSlug}.agent.md`);
|
|
191
|
+
const agentFileExists = fs.existsSync(agentFilePath);
|
|
192
|
+
const sessionOptions = {
|
|
193
|
+
shareToFile: transcriptPath,
|
|
194
|
+
allowAllTools: true,
|
|
195
|
+
silent: false,
|
|
196
|
+
logPrefix: `[${agentProfile.name}]`
|
|
197
|
+
};
|
|
198
|
+
// Only pass --agent if the file exists (copilot CLI requires it)
|
|
199
|
+
if (agentFileExists) {
|
|
200
|
+
sessionOptions.agent = agentSlug;
|
|
201
|
+
}
|
|
202
|
+
if (options.model) {
|
|
203
|
+
sessionOptions.model = options.model;
|
|
204
|
+
}
|
|
205
|
+
// Execute the session
|
|
206
|
+
let sessionResult;
|
|
207
|
+
try {
|
|
208
|
+
sessionResult = await this.sessionExecutor.executeSession(prompt, sessionOptions);
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
212
|
+
return {
|
|
213
|
+
success: false,
|
|
214
|
+
agentUsed: agentProfile.name,
|
|
215
|
+
output: `Session execution failed: ${msg}`,
|
|
216
|
+
duration: Date.now() - startTime,
|
|
217
|
+
wasQuickFixEligible: true,
|
|
218
|
+
reason: msg
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
// Skip verification if requested
|
|
222
|
+
if (options.skipVerification) {
|
|
223
|
+
return {
|
|
224
|
+
success: sessionResult.success,
|
|
225
|
+
agentUsed: agentProfile.name,
|
|
226
|
+
sessionResult,
|
|
227
|
+
output: sessionResult.output,
|
|
228
|
+
duration: Date.now() - startTime,
|
|
229
|
+
wasQuickFixEligible: true,
|
|
230
|
+
reason: eligibility.reason
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
// Verify the work
|
|
234
|
+
let verificationPassed = false;
|
|
235
|
+
if (sessionResult.success && sessionResult.transcriptPath) {
|
|
236
|
+
try {
|
|
237
|
+
const verificationResult = await this.verifier.verifyStep(1, // Quick-fix is always "step 1"
|
|
238
|
+
agentProfile.name, sessionResult.transcriptPath, {
|
|
239
|
+
requireTests: false, // Don't require tests for quick fixes
|
|
240
|
+
requireBuild: false, // Don't require build for quick fixes
|
|
241
|
+
requireCommits: true // Do require commits
|
|
242
|
+
});
|
|
243
|
+
verificationPassed = verificationResult.passed;
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
// Verification error - don't fail hard in quick-fix mode
|
|
247
|
+
logger.warn(`⚠️ Verification skipped: ${error instanceof Error ? error.message : String(error)}`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
const duration = Date.now() - startTime;
|
|
251
|
+
return {
|
|
252
|
+
success: sessionResult.success,
|
|
253
|
+
agentUsed: agentProfile.name,
|
|
254
|
+
sessionResult,
|
|
255
|
+
verificationPassed,
|
|
256
|
+
output: sessionResult.output,
|
|
257
|
+
duration,
|
|
258
|
+
wasQuickFixEligible: true,
|
|
259
|
+
reason: eligibility.reason
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Build a prompt for quick-fix mode
|
|
264
|
+
*/
|
|
265
|
+
buildQuickFixPrompt(task, agent) {
|
|
266
|
+
const sections = [];
|
|
267
|
+
sections.push('=== QUICK-FIX MODE ===\n');
|
|
268
|
+
sections.push('You are executing a simple, focused task that does not require');
|
|
269
|
+
sections.push('full swarm orchestration. Work quickly and efficiently.\n');
|
|
270
|
+
sections.push(`Agent: ${agent.name}`);
|
|
271
|
+
sections.push(`Description: ${agent.description}\n`);
|
|
272
|
+
sections.push('TASK:');
|
|
273
|
+
sections.push(task + '\n');
|
|
274
|
+
sections.push('QUICK-FIX GUIDELINES:');
|
|
275
|
+
sections.push('- Keep changes minimal and focused');
|
|
276
|
+
sections.push('- Make 1-3 small commits with clear messages');
|
|
277
|
+
sections.push('- No need for comprehensive testing unless task requires it');
|
|
278
|
+
sections.push('- Document changes briefly');
|
|
279
|
+
sections.push('- Run quick verification (linting, basic tests if applicable)\n');
|
|
280
|
+
sections.push('Your scope:');
|
|
281
|
+
agent.scope.forEach(item => {
|
|
282
|
+
sections.push('- ' + item);
|
|
283
|
+
});
|
|
284
|
+
sections.push('');
|
|
285
|
+
sections.push('Boundaries (do not exceed):');
|
|
286
|
+
agent.boundaries.forEach(item => {
|
|
287
|
+
sections.push('- ' + item);
|
|
288
|
+
});
|
|
289
|
+
sections.push('');
|
|
290
|
+
sections.push('Done when:');
|
|
291
|
+
agent.done_definition.forEach(item => {
|
|
292
|
+
sections.push('- ' + item);
|
|
293
|
+
});
|
|
294
|
+
sections.push('');
|
|
295
|
+
sections.push('IMPORTANT:');
|
|
296
|
+
sections.push('Make natural, incremental git commits as you work.');
|
|
297
|
+
sections.push('Run /share when complete to save transcript.\n');
|
|
298
|
+
return sections.join('\n');
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
exports.QuickFixMode = QuickFixMode;
|
|
302
|
+
exports.default = QuickFixMode;
|
|
@@ -0,0 +1,122 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.loadRecipe = loadRecipe;
|
|
37
|
+
exports.listRecipes = listRecipes;
|
|
38
|
+
exports.listRecipeDetails = listRecipeDetails;
|
|
39
|
+
exports.parameterizeRecipe = parameterizeRecipe;
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const RECIPES_DIR = path.join(__dirname, '..', '..', 'templates', 'recipes');
|
|
43
|
+
/**
|
|
44
|
+
* Load a recipe by name from the built-in recipes directory.
|
|
45
|
+
* Throws with available recipe names if the requested recipe is not found.
|
|
46
|
+
*/
|
|
47
|
+
function loadRecipe(name) {
|
|
48
|
+
const recipePath = path.join(RECIPES_DIR, `${name}.json`);
|
|
49
|
+
if (!fs.existsSync(recipePath)) {
|
|
50
|
+
const available = listRecipes();
|
|
51
|
+
throw new Error(`Unknown recipe "${name}". Available recipes: ${available.join(', ')}`);
|
|
52
|
+
}
|
|
53
|
+
const content = fs.readFileSync(recipePath, 'utf8');
|
|
54
|
+
return JSON.parse(content);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* List all available recipe names (without .json extension).
|
|
58
|
+
*/
|
|
59
|
+
function listRecipes() {
|
|
60
|
+
if (!fs.existsSync(RECIPES_DIR)) {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
return fs.readdirSync(RECIPES_DIR)
|
|
64
|
+
.filter(f => f.endsWith('.json'))
|
|
65
|
+
.map(f => f.replace(/\.json$/, ''))
|
|
66
|
+
.sort();
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Return full metadata for all available recipes.
|
|
70
|
+
*/
|
|
71
|
+
function listRecipeDetails() {
|
|
72
|
+
return listRecipes().map(name => loadRecipe(name));
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Substitute {{param}} placeholders in recipe step tasks with provided values.
|
|
76
|
+
* Missing parameters fall back to the recipe's declared defaults.
|
|
77
|
+
* Throws if a placeholder has no provided value and no default.
|
|
78
|
+
*/
|
|
79
|
+
function parameterizeRecipe(recipe, params) {
|
|
80
|
+
const merged = {};
|
|
81
|
+
// Collect defaults first, then override with user-supplied values
|
|
82
|
+
for (const [key, def] of Object.entries(recipe.parameters)) {
|
|
83
|
+
if (params[key] !== undefined) {
|
|
84
|
+
merged[key] = params[key];
|
|
85
|
+
}
|
|
86
|
+
else if (def.default !== undefined) {
|
|
87
|
+
merged[key] = def.default;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Validate: every placeholder in step tasks must be resolvable
|
|
91
|
+
const placeholderRegex = /\{\{(\w[\w-]*)\}\}/g;
|
|
92
|
+
const steps = recipe.steps.map(step => {
|
|
93
|
+
let match;
|
|
94
|
+
// Reset lastIndex since we reuse the regex
|
|
95
|
+
placeholderRegex.lastIndex = 0;
|
|
96
|
+
while ((match = placeholderRegex.exec(step.task)) !== null) {
|
|
97
|
+
const paramName = match[1];
|
|
98
|
+
if (merged[paramName] === undefined) {
|
|
99
|
+
throw new Error(`Recipe "${recipe.name}" step ${step.stepNumber}: parameter "${paramName}" has no value and no default`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Replace all placeholders
|
|
103
|
+
const task = step.task.replace(placeholderRegex, (_full, paramName) => {
|
|
104
|
+
return merged[paramName] ?? paramName;
|
|
105
|
+
});
|
|
106
|
+
return {
|
|
107
|
+
stepNumber: step.stepNumber,
|
|
108
|
+
agentName: step.agentName,
|
|
109
|
+
task,
|
|
110
|
+
dependencies: [...step.dependencies],
|
|
111
|
+
expectedOutputs: [...step.expectedOutputs],
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
return {
|
|
115
|
+
goal: `Recipe: ${recipe.name} (${recipe.description})`,
|
|
116
|
+
createdAt: new Date().toISOString(),
|
|
117
|
+
steps,
|
|
118
|
+
metadata: {
|
|
119
|
+
totalSteps: steps.length,
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|