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,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.showUsage = showUsage;
|
|
4
|
+
function showUsage() {
|
|
5
|
+
console.log(`
|
|
6
|
+
Swarm Orchestrator - Falsification and Audit-Ready Orchestration for AI Coding Agents
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
swarm bootstrap <path(s)> "Goal" Deep analysis and plan generation (multi-repo)
|
|
10
|
+
swarm plan <goal> Generate intelligent plan
|
|
11
|
+
swarm plan --copilot <goal> Generate Copilot CLI prompt for planning
|
|
12
|
+
swarm plan import <runid> <transcript> Parse plan from Copilot /share transcript
|
|
13
|
+
swarm execute <planfile> Execute a saved plan step-by-step
|
|
14
|
+
swarm swarm <planfile> Execute plan with verified branch/worktree workflow (analyzer-gated concurrency)
|
|
15
|
+
swarm run --goal "description" Plan + execute in one step (convenience)
|
|
16
|
+
swarm quick "task" Quick-fix mode for simple single-agent tasks
|
|
17
|
+
swarm demo <scenario> Run pre-configured demo scenario
|
|
18
|
+
swarm demo-fast Fast 2-step demo (alias for: swarm demo demo-fast)
|
|
19
|
+
swarm demo list List available demo scenarios
|
|
20
|
+
swarm gates [path] Run quality gates on a repo (default: cwd)
|
|
21
|
+
swarm status <execid> Show execution status
|
|
22
|
+
swarm templates List available plan templates
|
|
23
|
+
swarm share import <runid> <step> <agent> <path>
|
|
24
|
+
Import /share transcript for a step
|
|
25
|
+
swarm share context <runid> <step> Show prior context for a step
|
|
26
|
+
swarm audit <session-id> Generate Markdown audit report for a session
|
|
27
|
+
swarm metrics <session-id> Show metrics summary for a session
|
|
28
|
+
swarm agents export [--output-dir dir] Export agents as .agent.md from execution history
|
|
29
|
+
swarm use <recipe> [--param k=v ...] Execute a pre-built recipe (see: swarm recipes)
|
|
30
|
+
swarm recipes List available recipes
|
|
31
|
+
swarm recipe-info <name> Show recipe details and parameters
|
|
32
|
+
swarm report <run-id> Generate structured run report from artifacts
|
|
33
|
+
swarm attest verify <commit> Verify swarm attestation git note
|
|
34
|
+
swarm --help Show this help message
|
|
35
|
+
|
|
36
|
+
Flags:
|
|
37
|
+
--delegate Instruct agents to use /delegate for PR creation
|
|
38
|
+
--mcp Require MCP evidence from GitHub context in verification
|
|
39
|
+
--model Specify model for sessions (e.g., claude-sonnet-4.5)
|
|
40
|
+
--resume <id> Resume a previously paused/failed swarm session
|
|
41
|
+
--agent Specify agent for quick-fix mode
|
|
42
|
+
--skip-verify Skip verification in quick-fix mode (faster)
|
|
43
|
+
--confirm-deploy Enable opt-in deployment for deployment steps (vercel, netlify)
|
|
44
|
+
--no-quality-gates Disable quality gates (swarm mode)
|
|
45
|
+
--pm Run PM agent plan review before swarm execution
|
|
46
|
+
--strict-isolation Force per-task branch isolation, transcript-only context
|
|
47
|
+
--lean Enable Delta Context Engine (reuse prior KB patterns)
|
|
48
|
+
--useInnerFleet Prefix prompts with /fleet for inner sub-agent dispatch
|
|
49
|
+
--wrap-fleet Enable /fleet prefix on all step prompts (alias for --useInnerFleet)
|
|
50
|
+
--cost-estimate-only Run plan generation and cost estimation, print result, exit
|
|
51
|
+
--max-premium-requests <n> Abort if estimated premium requests exceed budget
|
|
52
|
+
--max-retries <n> Max retry attempts for queued and repair retries (default 3)
|
|
53
|
+
--quality-gates-config <path> Path to quality gates YAML (default: config/quality-gates.yaml)
|
|
54
|
+
--quality-gates-out <dir> Where to write gate reports (default: <runDir>/quality-gates)
|
|
55
|
+
--pr <auto|review> Create PRs instead of direct merge (auto: merge on pass, review: wait for approval)
|
|
56
|
+
--owasp-report Generate OWASP ASI compliance report after verification
|
|
57
|
+
--tool <name> Agent tool: copilot, claude-code, codex, claude-code-teams
|
|
58
|
+
--target <dir> Run execution in specified directory instead of cwd (alias: --dir)
|
|
59
|
+
--hooks Enable per-step hook injection for scope enforcement (default: on)
|
|
60
|
+
--no-hooks Disable hook injection for debugging
|
|
61
|
+
--verbose Enable debug-level logging
|
|
62
|
+
--output json Print machine-readable JSON for supported commands
|
|
63
|
+
--yes, -y Skip cost confirmation prompt (auto-approve)
|
|
64
|
+
|
|
65
|
+
Examples:
|
|
66
|
+
swarm demo-fast
|
|
67
|
+
swarm plan "Build a REST API for user management"
|
|
68
|
+
swarm plan --output json "Build a REST API for user management"
|
|
69
|
+
swarm swarm plan.json --model claude-opus-4.5 --verbose
|
|
70
|
+
swarm metrics <session-id> --output json
|
|
71
|
+
`);
|
|
72
|
+
}
|
package/dist/src/cli.js
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.generatePlan = void 0;
|
|
38
|
+
exports.main = main;
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const flags_1 = require("./cli/flags");
|
|
42
|
+
const logger_1 = require("./logger");
|
|
43
|
+
const presenter_1 = require("./presenter");
|
|
44
|
+
const startupArgs = process.argv.slice(2);
|
|
45
|
+
// User-facing commands enable a clean presenter surface by default:
|
|
46
|
+
// pretty-mode hides `[scope]` prefixes, diagnostic logger output is routed to
|
|
47
|
+
// stderr, and --quiet suppresses everything except errors and the result line.
|
|
48
|
+
// `--verbose` keeps the legacy diagnostic-on-stdout shape for developers.
|
|
49
|
+
const USER_FACING_COMMANDS = new Set(['run', 'swarm', 'quick', 'demo', 'demo-fast', 'bootstrap']);
|
|
50
|
+
const firstNonFlag = startupArgs.find((a) => !a.startsWith('-'));
|
|
51
|
+
const isUserFacingCommand = firstNonFlag ? USER_FACING_COMMANDS.has(firstNonFlag) : false;
|
|
52
|
+
const isVerbose = startupArgs.includes('--verbose');
|
|
53
|
+
const isQuiet = startupArgs.includes('--quiet') || startupArgs.includes('-q');
|
|
54
|
+
(0, logger_1.configureLogger)({
|
|
55
|
+
level: isQuiet ? 'warn' : (isVerbose ? 'debug' : 'info'),
|
|
56
|
+
outputFormat: (0, flags_1.parseOutputFormat)(startupArgs),
|
|
57
|
+
// Diagnostic output (info/debug/trace) routes to stderr when the presenter
|
|
58
|
+
// owns stdout. Without pretty mode (developer / non-user-facing commands),
|
|
59
|
+
// diagnostics keep flowing to stdout so tooling that scrapes stdout works.
|
|
60
|
+
diagnosticsToStderr: isUserFacingCommand && !isVerbose,
|
|
61
|
+
});
|
|
62
|
+
if (isUserFacingCommand && !isVerbose) {
|
|
63
|
+
(0, logger_1.setPrettyMode)(true);
|
|
64
|
+
}
|
|
65
|
+
(0, presenter_1.configurePresenter)({ quiet: isQuiet });
|
|
66
|
+
const logger = (0, logger_1.getLogger)('cli');
|
|
67
|
+
/**
|
|
68
|
+
* Parse a single .env file and set any variables not already in process.env.
|
|
69
|
+
* Supports KEY=value, KEY="value", KEY='value', and `export KEY=value`.
|
|
70
|
+
* Skips blank lines and comments. No external dependencies.
|
|
71
|
+
*/
|
|
72
|
+
function parseDotenvFile(filePath) {
|
|
73
|
+
if (!fs.existsSync(filePath))
|
|
74
|
+
return;
|
|
75
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
76
|
+
logger.debug(`loading env file ${filePath}`);
|
|
77
|
+
for (const raw of content.split('\n')) {
|
|
78
|
+
const line = raw.trim();
|
|
79
|
+
if (!line || line.startsWith('#'))
|
|
80
|
+
continue;
|
|
81
|
+
const stripped = line.startsWith('export ') ? line.slice(7) : line;
|
|
82
|
+
const eqIndex = stripped.indexOf('=');
|
|
83
|
+
if (eqIndex === -1)
|
|
84
|
+
continue;
|
|
85
|
+
const key = stripped.slice(0, eqIndex).trim();
|
|
86
|
+
let value = stripped.slice(eqIndex + 1).trim();
|
|
87
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
88
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
89
|
+
value = value.slice(1, -1);
|
|
90
|
+
}
|
|
91
|
+
if (process.env[key] === undefined) {
|
|
92
|
+
process.env[key] = value;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Load .env from multiple locations so API keys are found regardless
|
|
98
|
+
* of which target repo the user runs the command from.
|
|
99
|
+
*
|
|
100
|
+
* Search order (first match for a given key wins):
|
|
101
|
+
* 1. cwd (the target project directory)
|
|
102
|
+
* 2. The orchestrator's own install directory (where cli.js lives)
|
|
103
|
+
* 3. The user's home directory (~/.env) as a last-resort fallback
|
|
104
|
+
*/
|
|
105
|
+
function loadDotenv() {
|
|
106
|
+
const candidates = [
|
|
107
|
+
path.resolve(process.cwd(), '.env'),
|
|
108
|
+
];
|
|
109
|
+
// __dirname at runtime is dist/src/, so two levels up reaches the
|
|
110
|
+
// project root where .env and package.json live.
|
|
111
|
+
const orchestratorRoot = path.resolve(__dirname, '..', '..');
|
|
112
|
+
const orchestratorEnv = path.join(orchestratorRoot, '.env');
|
|
113
|
+
if (orchestratorEnv !== candidates[0]) {
|
|
114
|
+
candidates.push(orchestratorEnv);
|
|
115
|
+
}
|
|
116
|
+
const homeEnv = path.join(process.env.HOME || process.env.USERPROFILE || '', '.env');
|
|
117
|
+
if (homeEnv && !candidates.includes(homeEnv)) {
|
|
118
|
+
candidates.push(homeEnv);
|
|
119
|
+
}
|
|
120
|
+
for (const envPath of candidates) {
|
|
121
|
+
parseDotenvFile(envPath);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
loadDotenv();
|
|
125
|
+
const index_1 = require("./cli/index");
|
|
126
|
+
Object.defineProperty(exports, "generatePlan", { enumerable: true, get: function () { return index_1.generatePlan; } });
|
|
127
|
+
async function main() {
|
|
128
|
+
const args = (0, flags_1.normalizeLeadingGlobalFlags)(process.argv.slice(2));
|
|
129
|
+
if (args.length === 0) {
|
|
130
|
+
(0, index_1.showUsage)();
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const command = args[0];
|
|
134
|
+
let exitCode = 0;
|
|
135
|
+
try {
|
|
136
|
+
switch (command) {
|
|
137
|
+
case 'demo-fast':
|
|
138
|
+
exitCode = await (0, index_1.handleDemoCommand)(['demo', 'demo-fast', ...args.slice(1)]);
|
|
139
|
+
break;
|
|
140
|
+
case 'gates':
|
|
141
|
+
exitCode = await (0, index_1.handleGatesCommand)(args.slice(1));
|
|
142
|
+
break;
|
|
143
|
+
case 'quick':
|
|
144
|
+
exitCode = await (0, index_1.handleQuickCommand)(args);
|
|
145
|
+
break;
|
|
146
|
+
case 'bootstrap':
|
|
147
|
+
exitCode = await (0, index_1.handleBootstrapCommand)(args);
|
|
148
|
+
break;
|
|
149
|
+
case 'plan':
|
|
150
|
+
exitCode = await (0, index_1.handlePlanCommand)(args);
|
|
151
|
+
break;
|
|
152
|
+
case 'execute':
|
|
153
|
+
exitCode = await (0, index_1.handleExecuteCommand)(args);
|
|
154
|
+
break;
|
|
155
|
+
case 'status':
|
|
156
|
+
exitCode = await (0, index_1.handleStatusCommand)(args);
|
|
157
|
+
break;
|
|
158
|
+
case 'swarm':
|
|
159
|
+
exitCode = await (0, index_1.handleSwarmCommand)(args);
|
|
160
|
+
break;
|
|
161
|
+
case 'demo':
|
|
162
|
+
exitCode = await (0, index_1.handleDemoCommand)(args);
|
|
163
|
+
break;
|
|
164
|
+
case 'templates':
|
|
165
|
+
exitCode = await (0, index_1.handleTemplatesCommand)();
|
|
166
|
+
break;
|
|
167
|
+
case '--help':
|
|
168
|
+
case '-h':
|
|
169
|
+
(0, index_1.showUsage)();
|
|
170
|
+
break;
|
|
171
|
+
case 'share':
|
|
172
|
+
exitCode = await (0, index_1.handleShareCommand)(args);
|
|
173
|
+
break;
|
|
174
|
+
case 'audit':
|
|
175
|
+
exitCode = await (0, index_1.handleAuditCommand)(args);
|
|
176
|
+
break;
|
|
177
|
+
case 'metrics':
|
|
178
|
+
exitCode = await (0, index_1.handleMetricsCommand)(args);
|
|
179
|
+
break;
|
|
180
|
+
case 'run':
|
|
181
|
+
exitCode = await (0, index_1.handleRunCommand)(args);
|
|
182
|
+
break;
|
|
183
|
+
case 'report':
|
|
184
|
+
exitCode = await (0, index_1.handleReportCommand)(args);
|
|
185
|
+
break;
|
|
186
|
+
case 'agents':
|
|
187
|
+
exitCode = await (0, index_1.handleAgentsCommand)(args);
|
|
188
|
+
break;
|
|
189
|
+
case 'attest':
|
|
190
|
+
exitCode = await (0, index_1.handleAttestCommand)(args);
|
|
191
|
+
break;
|
|
192
|
+
case 'use':
|
|
193
|
+
exitCode = await (0, index_1.handleUseCommand)(args);
|
|
194
|
+
break;
|
|
195
|
+
case 'recipes':
|
|
196
|
+
exitCode = (0, index_1.handleRecipesCommand)();
|
|
197
|
+
break;
|
|
198
|
+
case 'recipe-info':
|
|
199
|
+
exitCode = (0, index_1.handleRecipeInfoCommand)(args);
|
|
200
|
+
break;
|
|
201
|
+
default:
|
|
202
|
+
logger.error(`Unknown command: ${command}\n`);
|
|
203
|
+
(0, index_1.showUsage)();
|
|
204
|
+
exitCode = 1;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
logger.error('Fatal error:', error instanceof Error ? error.message : String(error));
|
|
209
|
+
exitCode = 1;
|
|
210
|
+
}
|
|
211
|
+
if (exitCode !== 0) {
|
|
212
|
+
process.exit(exitCode);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (require.main === module) {
|
|
216
|
+
main();
|
|
217
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Commit Pattern Detector
|
|
4
|
+
*
|
|
5
|
+
* Analyzes git commit patterns to detect anti-patterns like:
|
|
6
|
+
* - Generic/vague messages
|
|
7
|
+
* - Repetitive patterns
|
|
8
|
+
* - Single-commit dumps
|
|
9
|
+
* - Non-incremental commits
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.CommitPatternDetector = void 0;
|
|
13
|
+
/**
|
|
14
|
+
* Generic/vague message patterns that indicate low quality
|
|
15
|
+
*/
|
|
16
|
+
const GENERIC_PATTERNS = [
|
|
17
|
+
/^update/i,
|
|
18
|
+
/^fix$/i,
|
|
19
|
+
/^fix bug/i,
|
|
20
|
+
/^changes$/i,
|
|
21
|
+
/^wip$/i,
|
|
22
|
+
/^work in progress/i,
|
|
23
|
+
/^temp$/i,
|
|
24
|
+
/^temporary/i,
|
|
25
|
+
/^misc/i,
|
|
26
|
+
/^various/i,
|
|
27
|
+
/^stuff$/i,
|
|
28
|
+
/^code$/i,
|
|
29
|
+
/^update code/i,
|
|
30
|
+
/^fix code/i,
|
|
31
|
+
/^fix issue/i,
|
|
32
|
+
/^address.*feedback/i,
|
|
33
|
+
/^pr feedback/i,
|
|
34
|
+
/^refactor$/i,
|
|
35
|
+
/^cleanup$/i,
|
|
36
|
+
/^done$/i,
|
|
37
|
+
/^complete$/i
|
|
38
|
+
];
|
|
39
|
+
/**
|
|
40
|
+
* Detects commit anti-patterns in a branch's history
|
|
41
|
+
*/
|
|
42
|
+
class CommitPatternDetector {
|
|
43
|
+
/**
|
|
44
|
+
* Analyze commit patterns for quality
|
|
45
|
+
*/
|
|
46
|
+
analyzeCommits(commits) {
|
|
47
|
+
if (commits.length === 0) {
|
|
48
|
+
return {
|
|
49
|
+
hasAntiPatterns: false,
|
|
50
|
+
warnings: [],
|
|
51
|
+
score: 100,
|
|
52
|
+
details: {
|
|
53
|
+
genericMessages: 0,
|
|
54
|
+
repetitivePatterns: 0,
|
|
55
|
+
singleCommitDump: false,
|
|
56
|
+
averageFilesPerCommit: 0,
|
|
57
|
+
commitCount: 0
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
const warnings = [];
|
|
62
|
+
let score = 100;
|
|
63
|
+
// Check for generic messages
|
|
64
|
+
const genericCount = commits.filter(c => GENERIC_PATTERNS.some(pattern => pattern.test(c.message))).length;
|
|
65
|
+
if (genericCount > 0) {
|
|
66
|
+
warnings.push(`Found ${genericCount} generic/vague commit message(s)`);
|
|
67
|
+
score -= genericCount * 15;
|
|
68
|
+
}
|
|
69
|
+
// Check for repetitive patterns (same message multiple times)
|
|
70
|
+
const messageFrequency = new Map();
|
|
71
|
+
for (const commit of commits) {
|
|
72
|
+
const normalized = commit.message.toLowerCase().trim();
|
|
73
|
+
messageFrequency.set(normalized, (messageFrequency.get(normalized) || 0) + 1);
|
|
74
|
+
}
|
|
75
|
+
const repetitiveCount = Array.from(messageFrequency.values()).filter(count => count > 2).length;
|
|
76
|
+
if (repetitiveCount > 0) {
|
|
77
|
+
warnings.push(`Found ${repetitiveCount} repetitive commit message pattern(s)`);
|
|
78
|
+
score -= repetitiveCount * 20;
|
|
79
|
+
}
|
|
80
|
+
// Check for single-commit dump (one commit with many files)
|
|
81
|
+
const singleCommitDump = commits.length === 1 && commits[0].files.length > 5;
|
|
82
|
+
if (singleCommitDump) {
|
|
83
|
+
warnings.push('Single-commit dump detected (one commit with many files)');
|
|
84
|
+
score -= 30;
|
|
85
|
+
}
|
|
86
|
+
// Check for non-incremental work (too many files per commit on average)
|
|
87
|
+
const totalFiles = commits.reduce((sum, c) => sum + c.files.length, 0);
|
|
88
|
+
const avgFilesPerCommit = totalFiles / commits.length;
|
|
89
|
+
if (avgFilesPerCommit > 8 && commits.length > 1) {
|
|
90
|
+
warnings.push(`High files-per-commit average (${avgFilesPerCommit.toFixed(1)}), suggests non-incremental work`);
|
|
91
|
+
score -= 15;
|
|
92
|
+
}
|
|
93
|
+
// Check for too few commits given file count
|
|
94
|
+
if (commits.length === 1 && totalFiles > 3) {
|
|
95
|
+
warnings.push('Too few commits for amount of work (should break into logical chunks)');
|
|
96
|
+
score -= 20;
|
|
97
|
+
}
|
|
98
|
+
// Ensure score stays in 0-100 range
|
|
99
|
+
score = Math.max(0, Math.min(100, score));
|
|
100
|
+
return {
|
|
101
|
+
hasAntiPatterns: warnings.length > 0,
|
|
102
|
+
warnings,
|
|
103
|
+
score,
|
|
104
|
+
details: {
|
|
105
|
+
genericMessages: genericCount,
|
|
106
|
+
repetitivePatterns: repetitiveCount,
|
|
107
|
+
singleCommitDump,
|
|
108
|
+
averageFilesPerCommit: parseFloat(avgFilesPerCommit.toFixed(1)),
|
|
109
|
+
commitCount: commits.length
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Check if a single commit message is problematic
|
|
115
|
+
*/
|
|
116
|
+
isGenericMessage(message) {
|
|
117
|
+
return GENERIC_PATTERNS.some(pattern => pattern.test(message));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Get suggestions for improving commit quality
|
|
121
|
+
*/
|
|
122
|
+
getSuggestions(result) {
|
|
123
|
+
const suggestions = [];
|
|
124
|
+
if (result.details.genericMessages > 0) {
|
|
125
|
+
suggestions.push('Use specific, descriptive commit messages (e.g., "add user authentication API" not "update code")');
|
|
126
|
+
}
|
|
127
|
+
if (result.details.repetitivePatterns > 0) {
|
|
128
|
+
suggestions.push('Vary commit messages to reflect different work done');
|
|
129
|
+
}
|
|
130
|
+
if (result.details.singleCommitDump) {
|
|
131
|
+
suggestions.push('Break work into multiple logical commits (e.g., separate commits for API, tests, docs)');
|
|
132
|
+
}
|
|
133
|
+
if (result.details.averageFilesPerCommit > 8) {
|
|
134
|
+
suggestions.push('Make smaller, more focused commits (aim for 2-5 files per commit)');
|
|
135
|
+
}
|
|
136
|
+
if (result.score < 70) {
|
|
137
|
+
suggestions.push('Review git commit guidelines in your agent instructions for examples');
|
|
138
|
+
}
|
|
139
|
+
return suggestions;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
exports.CommitPatternDetector = CommitPatternDetector;
|
|
143
|
+
exports.default = CommitPatternDetector;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.analyzeCommitQuality = analyzeCommitQuality;
|
|
4
|
+
const commit_pattern_detector_1 = require("./commit-pattern-detector");
|
|
5
|
+
const logger_1 = require("./logger");
|
|
6
|
+
const logger = (0, logger_1.getLogger)('commit-quality');
|
|
7
|
+
async function analyzeCommitQuality(commits, stepNumber, agentName) {
|
|
8
|
+
if (commits.length === 0)
|
|
9
|
+
return;
|
|
10
|
+
const detector = new commit_pattern_detector_1.CommitPatternDetector();
|
|
11
|
+
// Convert to CommitMessage format; parsed commits may carry extra
|
|
12
|
+
// fields (timestamp, files) beyond the ShareIndex schema
|
|
13
|
+
const commitMessages = commits.map(c => {
|
|
14
|
+
const extra = c;
|
|
15
|
+
return {
|
|
16
|
+
hash: c.sha || 'unknown',
|
|
17
|
+
message: c.message || '',
|
|
18
|
+
timestamp: extra.timestamp ? new Date(extra.timestamp) : new Date(),
|
|
19
|
+
files: extra.files || []
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
const result = detector.analyzeCommits(commitMessages);
|
|
23
|
+
// Surface anti-patterns; suppress the "all good" announcement so passing
|
|
24
|
+
// steps stay quiet and the live status block carries the success signal.
|
|
25
|
+
if (result.hasAntiPatterns) {
|
|
26
|
+
logger.warn(` commit-quality warnings · step ${stepNumber} (${agentName}) · score ${result.score}/100`);
|
|
27
|
+
result.warnings.forEach(warning => {
|
|
28
|
+
logger.warn(` - ${warning}`);
|
|
29
|
+
});
|
|
30
|
+
const suggestions = detector.getSuggestions(result);
|
|
31
|
+
if (suggestions.length > 0) {
|
|
32
|
+
logger.warn(` suggestions:`);
|
|
33
|
+
suggestions.forEach(suggestion => {
|
|
34
|
+
logger.warn(` - ${suggestion}`);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|