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,300 @@
|
|
|
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.KnowledgeBaseManager = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const text_similarity_1 = require("./text-similarity");
|
|
40
|
+
const logger_1 = require("./logger");
|
|
41
|
+
const logger = (0, logger_1.getLogger)('knowledge-base');
|
|
42
|
+
// Auto-prune triggers when pattern count exceeds this threshold
|
|
43
|
+
const MAX_PATTERNS = 500;
|
|
44
|
+
/**
|
|
45
|
+
* knowledge base for learning from execution patterns
|
|
46
|
+
* stores insights from reviewer-role analysis
|
|
47
|
+
*/
|
|
48
|
+
class KnowledgeBaseManager {
|
|
49
|
+
knowledgeBasePath;
|
|
50
|
+
knowledgeBase;
|
|
51
|
+
constructor(workingDir) {
|
|
52
|
+
const baseDir = workingDir || process.cwd();
|
|
53
|
+
this.knowledgeBasePath = path.join(baseDir, 'knowledge-base.json');
|
|
54
|
+
this.knowledgeBase = this.loadKnowledgeBase();
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* load knowledge base from disk or create new
|
|
58
|
+
*/
|
|
59
|
+
loadKnowledgeBase() {
|
|
60
|
+
if (fs.existsSync(this.knowledgeBasePath)) {
|
|
61
|
+
try {
|
|
62
|
+
const content = fs.readFileSync(this.knowledgeBasePath, 'utf8');
|
|
63
|
+
return JSON.parse(content);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
logger.warn(`Failed to load knowledge base, creating new: ${error}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
version: 1,
|
|
71
|
+
lastUpdated: new Date().toISOString(),
|
|
72
|
+
patterns: [],
|
|
73
|
+
statistics: {
|
|
74
|
+
totalRuns: 0,
|
|
75
|
+
totalPatterns: 0,
|
|
76
|
+
avgPatternsPerRun: 0
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* save knowledge base to disk
|
|
82
|
+
*/
|
|
83
|
+
saveKnowledgeBase() {
|
|
84
|
+
try {
|
|
85
|
+
fs.writeFileSync(this.knowledgeBasePath, JSON.stringify(this.knowledgeBase, null, 2), 'utf8');
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
logger.error(`Failed to save knowledge base: ${error}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* add or update pattern in knowledge base.
|
|
93
|
+
* Auto-prunes when pattern count exceeds MAX_PATTERNS to bound
|
|
94
|
+
* Levenshtein search cost and disk footprint.
|
|
95
|
+
*/
|
|
96
|
+
addOrUpdatePattern(pattern) {
|
|
97
|
+
const now = new Date().toISOString();
|
|
98
|
+
// check if similar pattern exists
|
|
99
|
+
const existing = this.knowledgeBase.patterns.find(p => p.category === pattern.category &&
|
|
100
|
+
this.isSimilarInsight(p.insight, pattern.insight));
|
|
101
|
+
if (existing) {
|
|
102
|
+
// update existing pattern
|
|
103
|
+
existing.occurrences++;
|
|
104
|
+
existing.lastSeen = now;
|
|
105
|
+
existing.confidence = pattern.confidence;
|
|
106
|
+
existing.evidence.push(...pattern.evidence);
|
|
107
|
+
existing.impact = pattern.impact;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// create new pattern
|
|
111
|
+
const newPattern = {
|
|
112
|
+
id: this.generatePatternId(pattern.category),
|
|
113
|
+
category: pattern.category,
|
|
114
|
+
insight: pattern.insight,
|
|
115
|
+
confidence: pattern.confidence,
|
|
116
|
+
evidence: pattern.evidence,
|
|
117
|
+
occurrences: 1,
|
|
118
|
+
firstSeen: now,
|
|
119
|
+
lastSeen: now,
|
|
120
|
+
impact: pattern.impact,
|
|
121
|
+
examples: []
|
|
122
|
+
};
|
|
123
|
+
this.knowledgeBase.patterns.push(newPattern);
|
|
124
|
+
}
|
|
125
|
+
// Prevent unbounded growth: prune stale and low-value entries
|
|
126
|
+
if (this.knowledgeBase.patterns.length > MAX_PATTERNS) {
|
|
127
|
+
this.prunePatterns({ removeOlderThan: 90, removeLowConfidence: true });
|
|
128
|
+
}
|
|
129
|
+
this.knowledgeBase.lastUpdated = now;
|
|
130
|
+
this.knowledgeBase.statistics.totalPatterns = this.knowledgeBase.patterns.length;
|
|
131
|
+
this.saveKnowledgeBase();
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Record a recipe execution for historical tracking.
|
|
135
|
+
* Stores structured run data so future recipe invocations can reference
|
|
136
|
+
* success rates and typical durations.
|
|
137
|
+
*/
|
|
138
|
+
recordRecipeRun(data) {
|
|
139
|
+
const status = data.passed ? 'passed' : 'failed';
|
|
140
|
+
const completionRatio = `${data.stepsCompleted}/${data.totalSteps}`;
|
|
141
|
+
this.addOrUpdatePattern({
|
|
142
|
+
category: 'recipe_run',
|
|
143
|
+
insight: `recipe:${data.recipe} tool:${data.tool} ${status} (${completionRatio} steps, ${data.duration}ms)`,
|
|
144
|
+
confidence: 'high',
|
|
145
|
+
evidence: [
|
|
146
|
+
`recipe:${data.recipe}`,
|
|
147
|
+
`tool:${data.tool}`,
|
|
148
|
+
`passed:${data.passed}`,
|
|
149
|
+
`duration:${data.duration}`,
|
|
150
|
+
`completed:${completionRatio}`,
|
|
151
|
+
`params:${JSON.stringify(data.parameters)}`,
|
|
152
|
+
],
|
|
153
|
+
impact: data.passed ? 'low' : 'medium',
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* get patterns by category
|
|
158
|
+
*/
|
|
159
|
+
getPatternsByCategory(category) {
|
|
160
|
+
return this.knowledgeBase.patterns.filter(p => p.category === category);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* get high-confidence patterns
|
|
164
|
+
*/
|
|
165
|
+
getHighConfidencePatterns() {
|
|
166
|
+
return this.knowledgeBase.patterns.filter(p => p.confidence === 'high');
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* get patterns that should influence planning
|
|
170
|
+
*/
|
|
171
|
+
getPlanningRelevantPatterns() {
|
|
172
|
+
return this.knowledgeBase.patterns.filter(p => (p.category === 'dependency_order' || p.category === 'best_practice') &&
|
|
173
|
+
p.confidence !== 'low' &&
|
|
174
|
+
p.occurrences >= 2);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* get anti-patterns to warn about
|
|
178
|
+
*/
|
|
179
|
+
getAntiPatterns() {
|
|
180
|
+
return this.knowledgeBase.patterns.filter(p => p.category === 'anti_pattern' && p.impact !== 'low');
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* record execution run
|
|
184
|
+
*/
|
|
185
|
+
recordRun(_patternsDetected) {
|
|
186
|
+
this.knowledgeBase.statistics.totalRuns++;
|
|
187
|
+
const { totalRuns, totalPatterns } = this.knowledgeBase.statistics;
|
|
188
|
+
this.knowledgeBase.statistics.avgPatternsPerRun = totalPatterns / totalRuns;
|
|
189
|
+
this.knowledgeBase.lastUpdated = new Date().toISOString();
|
|
190
|
+
this.saveKnowledgeBase();
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* get summary statistics
|
|
194
|
+
*/
|
|
195
|
+
getStatistics() {
|
|
196
|
+
return { ...this.knowledgeBase.statistics };
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* export knowledge base for review
|
|
200
|
+
*/
|
|
201
|
+
export() {
|
|
202
|
+
return JSON.parse(JSON.stringify(this.knowledgeBase));
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* clear old or low-value patterns
|
|
206
|
+
*/
|
|
207
|
+
prunePatterns(options) {
|
|
208
|
+
const now = new Date();
|
|
209
|
+
let removed = 0;
|
|
210
|
+
this.knowledgeBase.patterns = this.knowledgeBase.patterns.filter(pattern => {
|
|
211
|
+
if (options?.removeOlderThan) {
|
|
212
|
+
const lastSeenDate = new Date(pattern.lastSeen);
|
|
213
|
+
const daysSinceLastSeen = (now.getTime() - lastSeenDate.getTime()) / (1000 * 60 * 60 * 24);
|
|
214
|
+
if (daysSinceLastSeen > options.removeOlderThan) {
|
|
215
|
+
removed++;
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (options?.removeLowConfidence && pattern.confidence === 'low') {
|
|
220
|
+
removed++;
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
if (options?.removeRare && pattern.occurrences < 2) {
|
|
224
|
+
removed++;
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
return true;
|
|
228
|
+
});
|
|
229
|
+
if (removed > 0) {
|
|
230
|
+
this.knowledgeBase.statistics.totalPatterns = this.knowledgeBase.patterns.length;
|
|
231
|
+
this.saveKnowledgeBase();
|
|
232
|
+
}
|
|
233
|
+
return removed;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* check if two insights are similar (simple string similarity)
|
|
237
|
+
*/
|
|
238
|
+
isSimilarInsight(insight1, insight2) {
|
|
239
|
+
const normalize = (s) => s.toLowerCase().replace(/[^\w\s]/g, '').trim();
|
|
240
|
+
const n1 = normalize(insight1);
|
|
241
|
+
const n2 = normalize(insight2);
|
|
242
|
+
// exact match
|
|
243
|
+
if (n1 === n2)
|
|
244
|
+
return true;
|
|
245
|
+
// high overlap (simple check)
|
|
246
|
+
const words1 = new Set(n1.split(/\s+/));
|
|
247
|
+
const words2 = new Set(n2.split(/\s+/));
|
|
248
|
+
const intersection = new Set([...words1].filter(w => words2.has(w)));
|
|
249
|
+
const union = new Set([...words1, ...words2]);
|
|
250
|
+
const similarity = intersection.size / union.size;
|
|
251
|
+
return similarity > 0.7;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* generate unique pattern ID
|
|
255
|
+
*/
|
|
256
|
+
generatePatternId(category) {
|
|
257
|
+
const timestamp = Date.now();
|
|
258
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
259
|
+
return `${category}-${timestamp}-${random}`;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Delegates to the shared levenshtein from text-similarity.ts.
|
|
263
|
+
* Kept as a public method for backward compatibility with tests.
|
|
264
|
+
*/
|
|
265
|
+
levenshtein(a, b) {
|
|
266
|
+
return (0, text_similarity_1.levenshtein)(a, b);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Find stored patterns similar to a task description.
|
|
270
|
+
* Uses keyword overlap + normalized Levenshtein similarity.
|
|
271
|
+
* Skips patterns where length difference exceeds 2x (Levenshtein
|
|
272
|
+
* similarity cannot reach the threshold in those cases).
|
|
273
|
+
*/
|
|
274
|
+
findSimilarTasks(description, threshold = 0.7) {
|
|
275
|
+
const descLower = description.toLowerCase();
|
|
276
|
+
const descWords = new Set(descLower.split(/\s+/));
|
|
277
|
+
const descLen = descLower.length;
|
|
278
|
+
return this.knowledgeBase.patterns.filter(p => {
|
|
279
|
+
const insightLower = p.insight.toLowerCase();
|
|
280
|
+
// Length pre-filter: when one string is more than 2x the other,
|
|
281
|
+
// the normalized Levenshtein similarity is at most 0.5, so the
|
|
282
|
+
// combined score (keyword + lev) / 2 cannot reach 0.7 threshold
|
|
283
|
+
// unless keyword overlap is near-perfect. Skip the O(n*m) call.
|
|
284
|
+
const insightLen = insightLower.length;
|
|
285
|
+
const shorter = Math.min(descLen, insightLen);
|
|
286
|
+
const longer = Math.max(descLen, insightLen);
|
|
287
|
+
if (shorter > 0 && longer / shorter > 2)
|
|
288
|
+
return false;
|
|
289
|
+
const insightWords = new Set(insightLower.split(/\s+/));
|
|
290
|
+
const overlap = [...descWords].filter(w => insightWords.has(w)).length;
|
|
291
|
+
const union = new Set([...descWords, ...insightWords]).size;
|
|
292
|
+
const keywordSim = union > 0 ? overlap / union : 0;
|
|
293
|
+
const maxLen = longer || 1;
|
|
294
|
+
const levSim = 1 - (0, text_similarity_1.levenshtein)(descLower, insightLower) / maxLen;
|
|
295
|
+
const combined = (keywordSim + levSim) / 2;
|
|
296
|
+
return combined >= threshold;
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
exports.KnowledgeBaseManager = KnowledgeBaseManager;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.configureLogger = configureLogger;
|
|
4
|
+
exports.setPrettyMode = setPrettyMode;
|
|
5
|
+
exports.isPrettyMode = isPrettyMode;
|
|
6
|
+
exports.getLogger = getLogger;
|
|
7
|
+
exports.getLoggerConfig = getLoggerConfig;
|
|
8
|
+
exports.isJsonOutput = isJsonOutput;
|
|
9
|
+
exports.writeStructuredOutput = writeStructuredOutput;
|
|
10
|
+
const LEVEL_RANK = {
|
|
11
|
+
error: 0,
|
|
12
|
+
warn: 1,
|
|
13
|
+
info: 2,
|
|
14
|
+
debug: 3,
|
|
15
|
+
trace: 4,
|
|
16
|
+
};
|
|
17
|
+
const state = {
|
|
18
|
+
level: 'info',
|
|
19
|
+
outputFormat: 'text',
|
|
20
|
+
diagnosticsToStderr: false,
|
|
21
|
+
// Pretty mode: hide `[scope]` prefixes for a cleaner CLI UX.
|
|
22
|
+
// Auto-enabled by user-facing commands. Scope still shown in JSON output.
|
|
23
|
+
prettyMode: false,
|
|
24
|
+
};
|
|
25
|
+
function normalizeArgs(args) {
|
|
26
|
+
return args.map((arg) => {
|
|
27
|
+
if (typeof arg === 'string')
|
|
28
|
+
return arg;
|
|
29
|
+
if (arg instanceof Error)
|
|
30
|
+
return arg.stack || arg.message;
|
|
31
|
+
try {
|
|
32
|
+
return JSON.stringify(arg);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return String(arg);
|
|
36
|
+
}
|
|
37
|
+
}).join(' ');
|
|
38
|
+
}
|
|
39
|
+
function shouldLog(level) {
|
|
40
|
+
if (state.level === 'silent')
|
|
41
|
+
return false;
|
|
42
|
+
return LEVEL_RANK[level] <= LEVEL_RANK[state.level];
|
|
43
|
+
}
|
|
44
|
+
function writeLine(stream, line) {
|
|
45
|
+
stream.write(line + '\n');
|
|
46
|
+
}
|
|
47
|
+
function emit(level, scope, args) {
|
|
48
|
+
if (!shouldLog(level))
|
|
49
|
+
return;
|
|
50
|
+
const message = normalizeArgs(args);
|
|
51
|
+
if (state.outputFormat === 'json') {
|
|
52
|
+
writeLine(process.stderr, JSON.stringify({
|
|
53
|
+
timestamp: new Date().toISOString(),
|
|
54
|
+
level,
|
|
55
|
+
...(scope ? { scope } : {}),
|
|
56
|
+
message,
|
|
57
|
+
}));
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const prefix = (!state.prettyMode && scope) ? `[${scope}] ` : '';
|
|
61
|
+
// Diagnostic levels (info/debug/trace) go to stderr when explicitly routed there
|
|
62
|
+
// so the presenter owns stdout cleanly. Error/warn always to stderr.
|
|
63
|
+
const isDiagnostic = level === 'info' || level === 'debug' || level === 'trace';
|
|
64
|
+
const stream = level === 'error' || level === 'warn'
|
|
65
|
+
? process.stderr
|
|
66
|
+
: (state.diagnosticsToStderr && isDiagnostic ? process.stderr : process.stdout);
|
|
67
|
+
writeLine(stream, `${prefix}${message}`);
|
|
68
|
+
}
|
|
69
|
+
function createLogger(scope) {
|
|
70
|
+
return {
|
|
71
|
+
error: (...args) => emit('error', scope, args),
|
|
72
|
+
warn: (...args) => emit('warn', scope, args),
|
|
73
|
+
info: (...args) => emit('info', scope, args),
|
|
74
|
+
debug: (...args) => emit('debug', scope, args),
|
|
75
|
+
trace: (...args) => emit('trace', scope, args),
|
|
76
|
+
child: (childScope) => createLogger(scope ? `${scope}:${childScope}` : childScope),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function configureLogger(config) {
|
|
80
|
+
if (config.level)
|
|
81
|
+
state.level = config.level;
|
|
82
|
+
if (config.outputFormat)
|
|
83
|
+
state.outputFormat = config.outputFormat;
|
|
84
|
+
if (config.diagnosticsToStderr !== undefined)
|
|
85
|
+
state.diagnosticsToStderr = config.diagnosticsToStderr;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Hide `[scope]` prefixes for a cleaner user-facing CLI UX.
|
|
89
|
+
* Auto-enabled by user-facing commands; structured JSON output is unaffected.
|
|
90
|
+
*/
|
|
91
|
+
function setPrettyMode(pretty) {
|
|
92
|
+
state.prettyMode = pretty;
|
|
93
|
+
}
|
|
94
|
+
function isPrettyMode() {
|
|
95
|
+
return state.prettyMode;
|
|
96
|
+
}
|
|
97
|
+
function getLogger(scope) {
|
|
98
|
+
return createLogger(scope);
|
|
99
|
+
}
|
|
100
|
+
function getLoggerConfig() {
|
|
101
|
+
return { ...state };
|
|
102
|
+
}
|
|
103
|
+
function isJsonOutput() {
|
|
104
|
+
return state.outputFormat === 'json';
|
|
105
|
+
}
|
|
106
|
+
function writeStructuredOutput(payload) {
|
|
107
|
+
const content = typeof payload === 'string'
|
|
108
|
+
? payload
|
|
109
|
+
: JSON.stringify(payload, null, 2);
|
|
110
|
+
process.stdout.write(content + '\n');
|
|
111
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MetaAnalyzer = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* meta-analysis engine - reviews execution quality and decides on replanning
|
|
6
|
+
*/
|
|
7
|
+
class MetaAnalyzer {
|
|
8
|
+
/**
|
|
9
|
+
* analyze wave results and determine if replanning needed
|
|
10
|
+
*/
|
|
11
|
+
analyzeWave(waveIndex, waveSteps, results, plan, executionId) {
|
|
12
|
+
const waveResults = results.filter(r => waveSteps.includes(r.stepNumber));
|
|
13
|
+
const stepReviews = waveResults.map(result => {
|
|
14
|
+
return this.reviewStep(result);
|
|
15
|
+
});
|
|
16
|
+
const detectedPatterns = this.detectPatterns(waveResults);
|
|
17
|
+
const failureRate = stepReviews.filter(r => !r.verificationPassed).length / stepReviews.length;
|
|
18
|
+
let overallHealth = 'healthy';
|
|
19
|
+
if (failureRate > 0.5) {
|
|
20
|
+
overallHealth = 'critical';
|
|
21
|
+
}
|
|
22
|
+
else if (failureRate > 0.2) {
|
|
23
|
+
overallHealth = 'degraded';
|
|
24
|
+
}
|
|
25
|
+
const replanNeeded = failureRate > 0.5;
|
|
26
|
+
const replanReason = replanNeeded
|
|
27
|
+
? `Wave ${waveIndex + 1} failed: ${Math.round(failureRate * 100)}% of steps did not pass verification`
|
|
28
|
+
: null;
|
|
29
|
+
const suggestedChanges = this.generateSuggestedChanges(stepReviews, plan);
|
|
30
|
+
const knowledgeUpdates = this.extractKnowledge(stepReviews, detectedPatterns);
|
|
31
|
+
const nextActions = this.determineNextActions(overallHealth, replanNeeded, suggestedChanges);
|
|
32
|
+
return {
|
|
33
|
+
analysisTimestamp: new Date().toISOString(),
|
|
34
|
+
executionId,
|
|
35
|
+
waveAnalyzed: waveIndex + 1,
|
|
36
|
+
overallHealth,
|
|
37
|
+
stepReviews,
|
|
38
|
+
detectedPatterns,
|
|
39
|
+
replanNeeded,
|
|
40
|
+
replanReason,
|
|
41
|
+
suggestedChanges,
|
|
42
|
+
knowledgeUpdates,
|
|
43
|
+
nextActions
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* review individual step result
|
|
48
|
+
*/
|
|
49
|
+
reviewStep(result) {
|
|
50
|
+
const verificationPassed = result.verificationResult?.passed ?? false;
|
|
51
|
+
const issues = [];
|
|
52
|
+
let rootCause = 'Unknown';
|
|
53
|
+
let recommendation = 'Continue';
|
|
54
|
+
if (!verificationPassed && result.verificationResult) {
|
|
55
|
+
// analyze verification failures
|
|
56
|
+
result.verificationResult.checks.forEach(check => {
|
|
57
|
+
if (!check.passed && check.required) {
|
|
58
|
+
issues.push(`${check.type}: ${check.description} - ${check.reason || 'failed'}`);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
if (result.verificationResult.unverifiedClaims.length > 0) {
|
|
62
|
+
issues.push(`Unverified claims: ${result.verificationResult.unverifiedClaims.length} detected`);
|
|
63
|
+
}
|
|
64
|
+
// determine root cause
|
|
65
|
+
if (issues.some(i => i.includes('test'))) {
|
|
66
|
+
rootCause = 'Tests not executed or failed';
|
|
67
|
+
recommendation = 'Re-execute with explicit test requirement';
|
|
68
|
+
}
|
|
69
|
+
else if (issues.some(i => i.includes('build'))) {
|
|
70
|
+
rootCause = 'Build not executed or failed';
|
|
71
|
+
recommendation = 'Re-execute with build verification';
|
|
72
|
+
}
|
|
73
|
+
else if (issues.some(i => i.includes('commit'))) {
|
|
74
|
+
rootCause = 'No commits made';
|
|
75
|
+
recommendation = 'Re-execute with commit requirement';
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
rootCause = 'Verification checks failed';
|
|
79
|
+
recommendation = 'Review transcript and re-execute';
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
stepNumber: result.stepNumber,
|
|
84
|
+
agentName: result.agentName,
|
|
85
|
+
verificationPassed,
|
|
86
|
+
issues,
|
|
87
|
+
rootCause,
|
|
88
|
+
recommendation
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* detect patterns across multiple steps
|
|
93
|
+
*/
|
|
94
|
+
detectPatterns(results) {
|
|
95
|
+
const patterns = [];
|
|
96
|
+
// check for generic commit messages (anti-pattern)
|
|
97
|
+
const genericCommitAgents = results.filter(r => {
|
|
98
|
+
const commits = r.verificationResult?.checks.find(c => c.type === 'commit');
|
|
99
|
+
if (!commits?.evidence)
|
|
100
|
+
return false;
|
|
101
|
+
return /update|fix|change/i.test(commits.evidence) && commits.evidence.length < 30;
|
|
102
|
+
});
|
|
103
|
+
if (genericCommitAgents.length >= 2) {
|
|
104
|
+
patterns.push({
|
|
105
|
+
type: 'anti-pattern',
|
|
106
|
+
pattern: 'generic_commit_messages',
|
|
107
|
+
occurrences: genericCommitAgents.length,
|
|
108
|
+
affectedAgents: genericCommitAgents.map(r => r.agentName),
|
|
109
|
+
example: 'Commits like "update files" or "fix issues"',
|
|
110
|
+
severity: 'medium'
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
// check for unverified claims (drift)
|
|
114
|
+
const driftingAgents = results.filter(r => {
|
|
115
|
+
return (r.verificationResult?.unverifiedClaims.length || 0) > 2;
|
|
116
|
+
});
|
|
117
|
+
if (driftingAgents.length >= 1) {
|
|
118
|
+
patterns.push({
|
|
119
|
+
type: 'context-gap',
|
|
120
|
+
pattern: 'unverified_claims',
|
|
121
|
+
occurrences: driftingAgents.length,
|
|
122
|
+
affectedAgents: driftingAgents.map(r => r.agentName),
|
|
123
|
+
example: 'Agent claims work done without evidence in transcript',
|
|
124
|
+
severity: 'high'
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return patterns;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* generate suggested changes based on review
|
|
131
|
+
*/
|
|
132
|
+
generateSuggestedChanges(stepReviews, _plan) {
|
|
133
|
+
const changes = [];
|
|
134
|
+
stepReviews.forEach(review => {
|
|
135
|
+
if (!review.verificationPassed) {
|
|
136
|
+
changes.push({
|
|
137
|
+
type: 're-execute',
|
|
138
|
+
targetStep: review.stepNumber,
|
|
139
|
+
reason: review.rootCause,
|
|
140
|
+
details: review.recommendation
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
return changes;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* extract knowledge from analysis
|
|
148
|
+
*/
|
|
149
|
+
extractKnowledge(stepReviews, patterns) {
|
|
150
|
+
const updates = [];
|
|
151
|
+
// extract from patterns
|
|
152
|
+
patterns.forEach(pattern => {
|
|
153
|
+
if (pattern.severity === 'high') {
|
|
154
|
+
updates.push({
|
|
155
|
+
category: pattern.type === 'anti-pattern' ? 'anti_pattern' : 'agent_behavior',
|
|
156
|
+
insight: `Pattern detected: ${pattern.pattern} in ${pattern.occurrences} step(s)`,
|
|
157
|
+
confidence: 'high',
|
|
158
|
+
evidence: pattern.example
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
return updates;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* determine next actions
|
|
166
|
+
*/
|
|
167
|
+
determineNextActions(health, replanNeeded, changes) {
|
|
168
|
+
const actions = [];
|
|
169
|
+
if (replanNeeded) {
|
|
170
|
+
actions.push('Trigger full replan');
|
|
171
|
+
actions.push('Preserve git history from completed steps');
|
|
172
|
+
}
|
|
173
|
+
else if (health === 'degraded') {
|
|
174
|
+
if (changes.length > 0) {
|
|
175
|
+
actions.push(`Re-execute ${changes.length} failed step(s)`);
|
|
176
|
+
}
|
|
177
|
+
actions.push('Monitor next wave closely');
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
actions.push('Continue to next wave');
|
|
181
|
+
}
|
|
182
|
+
return actions;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* make replan decision based on analysis
|
|
186
|
+
*/
|
|
187
|
+
makeReplanDecision(analysis, _plan, _completedSteps) {
|
|
188
|
+
if (!analysis.replanNeeded) {
|
|
189
|
+
return {
|
|
190
|
+
shouldReplan: false,
|
|
191
|
+
reason: 'Execution healthy, continue as planned',
|
|
192
|
+
preserveHistory: true
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
// identify which steps to retry
|
|
196
|
+
const stepsToRetry = analysis.suggestedChanges
|
|
197
|
+
.filter(c => c.type === 're-execute')
|
|
198
|
+
.map(c => c.targetStep)
|
|
199
|
+
.filter(s => s !== undefined);
|
|
200
|
+
return {
|
|
201
|
+
shouldReplan: true,
|
|
202
|
+
reason: analysis.replanReason || 'Critical issues detected',
|
|
203
|
+
stepsToRetry,
|
|
204
|
+
preserveHistory: true
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
exports.MetaAnalyzer = MetaAnalyzer;
|