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,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* GitHub MCP Integration
|
|
4
|
+
* Generates MCP prompts and validates MCP evidence in verification docs
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.GitHubMcpIntegrator = void 0;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
class GitHubMcpIntegrator {
|
|
43
|
+
/**
|
|
44
|
+
* Generate MCP prompt section for agent instructions
|
|
45
|
+
*/
|
|
46
|
+
static generateMcpPromptSection() {
|
|
47
|
+
return `
|
|
48
|
+
GitHub Context (MCP) Requirements:
|
|
49
|
+
- Before making decisions, consult GitHub context using available MCP tools
|
|
50
|
+
- Check for: related issues, existing PRs, recent commits, CI workflows
|
|
51
|
+
- In your verification section, include an "MCP Evidence" section with:
|
|
52
|
+
* What GitHub context you consulted
|
|
53
|
+
* Specific evidence quoted (issue numbers, PR titles, workflow names, etc.)
|
|
54
|
+
* How it influenced your decisions
|
|
55
|
+
- Example MCP Evidence format:
|
|
56
|
+
|
|
57
|
+
## MCP Evidence
|
|
58
|
+
- Consulted open issues: Found issue #42 "Add user authentication"
|
|
59
|
+
- Checked existing PRs: No conflicting PRs for auth feature
|
|
60
|
+
- Reviewed CI workflow: .github/workflows/ci.yml runs tests on push
|
|
61
|
+
- Decision: Implemented auth to resolve #42, added tests for CI compatibility
|
|
62
|
+
|
|
63
|
+
Without MCP evidence in your verification, this step will be flagged.
|
|
64
|
+
`.trim();
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Generate /delegate prompt section for agent instructions
|
|
68
|
+
*/
|
|
69
|
+
static generateDelegatePromptSection() {
|
|
70
|
+
return `
|
|
71
|
+
Pull Request Creation (via /delegate):
|
|
72
|
+
- When your changes are ready, create a PR using the /delegate command
|
|
73
|
+
- The /delegate command will guide you through PR creation
|
|
74
|
+
- Include the resulting PR URL in your verification section
|
|
75
|
+
- Format: "Created PR: https://github.com/owner/repo/pull/123"
|
|
76
|
+
- If /delegate is not available or fails, note this in verification
|
|
77
|
+
|
|
78
|
+
Example verification with PR:
|
|
79
|
+
## Verification
|
|
80
|
+
- Changed files: src/api.ts, test/api.test.ts
|
|
81
|
+
- Tests run: npm test (14 passing)
|
|
82
|
+
- Created PR: https://github.com/owner/repo/pull/123
|
|
83
|
+
`.trim();
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Validate MCP evidence in verification.md
|
|
87
|
+
*/
|
|
88
|
+
static validateMcpEvidence(verificationPath) {
|
|
89
|
+
const warnings = [];
|
|
90
|
+
if (!fs.existsSync(verificationPath)) {
|
|
91
|
+
return {
|
|
92
|
+
found: false,
|
|
93
|
+
warnings: ['verification.md not found']
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const content = fs.readFileSync(verificationPath, 'utf-8');
|
|
97
|
+
// look for MCP evidence section
|
|
98
|
+
const mcpSectionMatch = content.match(/##\s+MCP\s+Evidence(.*?)(?=\n##|\n$)/is);
|
|
99
|
+
if (!mcpSectionMatch || !mcpSectionMatch[1]) {
|
|
100
|
+
warnings.push('No "## MCP Evidence" section found in verification.md');
|
|
101
|
+
return { found: false, warnings };
|
|
102
|
+
}
|
|
103
|
+
const mcpSection = mcpSectionMatch[1].trim();
|
|
104
|
+
if (mcpSection.length < 50) {
|
|
105
|
+
warnings.push('MCP Evidence section is too short (< 50 chars)');
|
|
106
|
+
}
|
|
107
|
+
// check for specific evidence markers
|
|
108
|
+
const hasIssueReference = /issue\s+#?\d+|issues:/i.test(mcpSection);
|
|
109
|
+
const hasPrReference = /PR\s+#?\d+|pull request/i.test(mcpSection);
|
|
110
|
+
const hasWorkflowReference = /workflow|\.github\/workflows|CI/i.test(mcpSection);
|
|
111
|
+
const hasCommitReference = /commit|sha/i.test(mcpSection);
|
|
112
|
+
const hasDecisionStatement = /decision|influenced|based on|considering/i.test(mcpSection);
|
|
113
|
+
const evidenceCount = [
|
|
114
|
+
hasIssueReference,
|
|
115
|
+
hasPrReference,
|
|
116
|
+
hasWorkflowReference,
|
|
117
|
+
hasCommitReference
|
|
118
|
+
].filter(Boolean).length;
|
|
119
|
+
if (evidenceCount === 0) {
|
|
120
|
+
warnings.push('MCP Evidence has no specific GitHub references (issues, PRs, workflows, commits)');
|
|
121
|
+
}
|
|
122
|
+
if (!hasDecisionStatement) {
|
|
123
|
+
warnings.push('MCP Evidence should explain how context influenced decisions');
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
found: true,
|
|
127
|
+
section: mcpSection,
|
|
128
|
+
warnings
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Extract PR URLs from verification.md
|
|
133
|
+
*/
|
|
134
|
+
static extractPrUrls(verificationPath) {
|
|
135
|
+
if (!fs.existsSync(verificationPath)) {
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
const content = fs.readFileSync(verificationPath, 'utf-8');
|
|
139
|
+
// github PR URLs
|
|
140
|
+
const urlMatches = content.match(/https:\/\/github\.com\/[^\/]+\/[^\/]+\/pull\/\d+/g) || [];
|
|
141
|
+
// PR references like "PR: #123" or "Created PR #42"
|
|
142
|
+
const refMatches = content.match(/(?:PR|pull request)\s*:?\s*#(\d+)/gi) || [];
|
|
143
|
+
const prNumbers = refMatches.map(m => m.match(/#(\d+)/)?.[1]).filter(Boolean);
|
|
144
|
+
return [...new Set([...urlMatches, ...prNumbers.map(n => `#${n}`)])];
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Format MCP evidence for display
|
|
148
|
+
*/
|
|
149
|
+
static formatMcpEvidenceDisplay(evidence) {
|
|
150
|
+
if (!evidence.found) {
|
|
151
|
+
return `⚠ MCP Evidence: NOT FOUND\n${evidence.warnings.map(w => ` - ${w}`).join('\n')}`;
|
|
152
|
+
}
|
|
153
|
+
let output = '✓ MCP Evidence: FOUND\n';
|
|
154
|
+
if (evidence.section) {
|
|
155
|
+
output += `\n${evidence.section}\n`;
|
|
156
|
+
}
|
|
157
|
+
if (evidence.warnings.length > 0) {
|
|
158
|
+
output += '\n⚠ Warnings:\n';
|
|
159
|
+
output += evidence.warnings.map(w => ` - ${w}`).join('\n');
|
|
160
|
+
}
|
|
161
|
+
return output;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
exports.GitHubMcpIntegrator = GitHubMcpIntegrator;
|
|
@@ -0,0 +1,229 @@
|
|
|
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.HookGenerator = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
/**
|
|
40
|
+
* Generates per-step Copilot CLI hook files that enforce scope boundaries
|
|
41
|
+
* during execution and capture structured evidence in real-time.
|
|
42
|
+
*
|
|
43
|
+
* Hooks are written to <workingDir>/.github/hooks/ which the Copilot CLI
|
|
44
|
+
* SDK auto-loads on session start. Context (toolName, toolArgs, toolResult)
|
|
45
|
+
* is piped to hook commands via stdin as JSON.
|
|
46
|
+
*/
|
|
47
|
+
class HookGenerator {
|
|
48
|
+
/**
|
|
49
|
+
* Generate hooks for a single step execution.
|
|
50
|
+
* Writes a hook config to <workingDir>/.github/hooks/ and returns
|
|
51
|
+
* paths needed for evidence parsing after execution.
|
|
52
|
+
*/
|
|
53
|
+
generateStepHooks(input) {
|
|
54
|
+
const hooksDir = path.join(input.workingDir, '.github', 'hooks');
|
|
55
|
+
fs.mkdirSync(hooksDir, { recursive: true });
|
|
56
|
+
const evidenceDir = path.join(input.runDir, 'evidence');
|
|
57
|
+
if (!fs.existsSync(evidenceDir)) {
|
|
58
|
+
fs.mkdirSync(evidenceDir, { recursive: true });
|
|
59
|
+
}
|
|
60
|
+
const evidenceLogPath = path.join(evidenceDir, `step-${input.step.stepNumber}.jsonl`);
|
|
61
|
+
const scopeRules = this.deriveScopeRules(input.agent, input.existingTestFiles);
|
|
62
|
+
const hookConfig = this.buildHookConfig(scopeRules, evidenceLogPath, input);
|
|
63
|
+
const hooksFilePath = path.join(hooksDir, `swarm-step-${input.step.stepNumber}.json`);
|
|
64
|
+
fs.writeFileSync(hooksFilePath, JSON.stringify(hookConfig, null, 2));
|
|
65
|
+
return { hooksDir, hooksFilePath, evidenceLogPath, scopeRules };
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Remove the generated hooks file after step execution.
|
|
69
|
+
* The evidence log is NOT removed (it lives in the run directory).
|
|
70
|
+
*/
|
|
71
|
+
cleanupHooks(hooksFileOrDir) {
|
|
72
|
+
try {
|
|
73
|
+
const stat = fs.statSync(hooksFileOrDir);
|
|
74
|
+
if (stat.isDirectory()) {
|
|
75
|
+
// Legacy path: remove temp directory from old approach
|
|
76
|
+
fs.rmSync(hooksFileOrDir, { recursive: true, force: true });
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
// Remove the single hooks JSON file we created
|
|
80
|
+
fs.unlinkSync(hooksFileOrDir);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// Best-effort cleanup
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Parse an evidence JSONL file into structured entries.
|
|
89
|
+
*/
|
|
90
|
+
parseEvidenceLog(evidenceLogPath) {
|
|
91
|
+
if (!fs.existsSync(evidenceLogPath))
|
|
92
|
+
return [];
|
|
93
|
+
const content = fs.readFileSync(evidenceLogPath, 'utf8').trim();
|
|
94
|
+
if (!content)
|
|
95
|
+
return [];
|
|
96
|
+
const entries = [];
|
|
97
|
+
for (const line of content.split('\n')) {
|
|
98
|
+
const trimmed = line.trim();
|
|
99
|
+
if (!trimmed)
|
|
100
|
+
continue;
|
|
101
|
+
try {
|
|
102
|
+
entries.push(JSON.parse(trimmed));
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// Skip malformed lines; hooks may produce partial output on kill
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return entries;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Derive scope rules from agent boundaries.
|
|
112
|
+
* Agent boundaries contain natural-language rules like
|
|
113
|
+
* "Do not modify frontend components or UI code". These are mapped
|
|
114
|
+
* to file path patterns for hook enforcement.
|
|
115
|
+
*/
|
|
116
|
+
deriveScopeRules(agent, existingTestFiles) {
|
|
117
|
+
const allow = [];
|
|
118
|
+
const deny = [];
|
|
119
|
+
for (const scope of agent.scope) {
|
|
120
|
+
const lower = scope.toLowerCase();
|
|
121
|
+
if (lower.includes('frontend') || lower.includes('ui') || lower.includes('component')) {
|
|
122
|
+
allow.push('src/components', 'src/pages', 'src/views', 'public', 'styles', '.css', '.scss', '.html');
|
|
123
|
+
}
|
|
124
|
+
if (lower.includes('backend') || lower.includes('server') || lower.includes('api')) {
|
|
125
|
+
allow.push('src/api', 'src/server', 'src/routes', 'src/middleware', 'server', 'api');
|
|
126
|
+
}
|
|
127
|
+
if (lower.includes('test') || lower.includes('quality')) {
|
|
128
|
+
allow.push('test', 'tests', '__tests__', 'spec', '.test.', '.spec.');
|
|
129
|
+
}
|
|
130
|
+
if (lower.includes('ci/cd') || lower.includes('docker') || lower.includes('deployment')) {
|
|
131
|
+
allow.push('.github', 'Dockerfile', 'docker-compose', '.env', 'deploy');
|
|
132
|
+
}
|
|
133
|
+
if (lower.includes('security')) {
|
|
134
|
+
allow.push('src', 'config', 'package.json');
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
for (const boundary of agent.boundaries) {
|
|
138
|
+
const lower = boundary.toLowerCase();
|
|
139
|
+
if (lower.includes('frontend') || lower.includes('ui')) {
|
|
140
|
+
deny.push('src/components', 'src/pages', 'src/views', '.css', '.scss');
|
|
141
|
+
}
|
|
142
|
+
if (lower.includes('backend') || lower.includes('server')) {
|
|
143
|
+
deny.push('src/api', 'src/server', 'src/routes', 'server');
|
|
144
|
+
}
|
|
145
|
+
if (lower.includes('database') || lower.includes('schema') || lower.includes('migration')) {
|
|
146
|
+
deny.push('migrations', 'prisma/schema', 'db/schema');
|
|
147
|
+
}
|
|
148
|
+
if (lower.includes('ci/cd') || lower.includes('pipeline') || lower.includes('infrastructure')) {
|
|
149
|
+
deny.push('.github/workflows', 'Dockerfile');
|
|
150
|
+
}
|
|
151
|
+
if (lower.includes('test framework')) {
|
|
152
|
+
deny.push('jest.config', 'mocha', '.mocharc');
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// Protect pre-existing test files from modification by default.
|
|
156
|
+
// Reviewer steps are read-only and do not write to any files.
|
|
157
|
+
// Worker steps must not modify existing tests unless the goal explicitly requires it.
|
|
158
|
+
const canModifyTests = agent.name === 'reviewer';
|
|
159
|
+
if (!canModifyTests && existingTestFiles && existingTestFiles.length > 0) {
|
|
160
|
+
for (const testFile of existingTestFiles) {
|
|
161
|
+
deny.push(testFile);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
allow: [...new Set(allow)],
|
|
166
|
+
deny: [...new Set(deny)]
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
// Scope enforcement via preToolUse hooks. The SDK reads the
|
|
170
|
+
// permissionDecision field from the hook's JSON stdout. When a file path
|
|
171
|
+
// matches a deny rule and no allow rule overrides it, the hook outputs
|
|
172
|
+
// "deny" with a reason. The SDK blocks the tool call and injects the
|
|
173
|
+
// reason into the agent's context. Violations are also logged to the
|
|
174
|
+
// evidence file so the verification layer can flag them independently.
|
|
175
|
+
/**
|
|
176
|
+
* Build a bash script that reads context JSON from stdin, checks the
|
|
177
|
+
* file path against deny/allow rules, and either denies the tool call
|
|
178
|
+
* (via permissionDecision) or approves it. Violations are logged to
|
|
179
|
+
* the evidence file regardless for verification-layer enforcement.
|
|
180
|
+
*/
|
|
181
|
+
buildPreToolUseScript(scopeRules, evidenceLogPath, agentName) {
|
|
182
|
+
const rulesJson = JSON.stringify({ allow: scopeRules.allow, deny: scopeRules.deny });
|
|
183
|
+
const escapedPath = evidenceLogPath.replace(/'/g, "'\\'");
|
|
184
|
+
const safeAgent = agentName.replace(/'/g, '');
|
|
185
|
+
// Node reads context from stdin, checks scope rules, denies out-of-scope tool calls, logs violations
|
|
186
|
+
return `node -e "let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{try{const ctx=JSON.parse(d);const rules=${rulesJson.replace(/"/g, '\\"')};const p=(ctx.toolArgs||{}).path||(ctx.toolArgs||{}).filePath||'';if(p&&rules.deny.length>0){const denied=rules.deny.some(r=>p.includes(r));if(denied){const allowed=rules.allow.some(r=>p.includes(r));if(!allowed){const rule=rules.deny.find(r=>p.includes(r));const entry={timestamp:new Date().toISOString(),event:'scope_violation',tool:ctx.toolName||'unknown',filePath:p,agentName:'${safeAgent}',boundaryRule:rule};require('fs').appendFileSync('${escapedPath}',JSON.stringify(entry)+'\\n');process.stdout.write(JSON.stringify({permissionDecision:'deny',permissionDecisionReason:'Scope violation: '+p+' is outside agent boundary ('+rule+')'}));return}}}process.stdout.write(JSON.stringify({permissionDecision:'approve'}))}catch(e){process.stdout.write(JSON.stringify({permissionDecision:'approve'}))}})"`;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Build a bash script that reads context JSON from stdin and appends
|
|
190
|
+
* a structured evidence entry to the JSONL log file.
|
|
191
|
+
*/
|
|
192
|
+
buildPostToolUseScript(evidenceLogPath) {
|
|
193
|
+
const escapedPath = evidenceLogPath.replace(/'/g, "'\\''");
|
|
194
|
+
return `node -e "let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{try{const ctx=JSON.parse(d);const entry={timestamp:new Date().toISOString(),event:'postToolUse',tool:ctx.toolName||'unknown',filePath:(ctx.toolArgs||{}).path||(ctx.toolArgs||{}).filePath,exitCode:ctx.toolResult?ctx.toolResult.exitCode:undefined};require('fs').appendFileSync('${escapedPath}',JSON.stringify(entry)+'\\n')}catch(e){}})"`;
|
|
195
|
+
}
|
|
196
|
+
// ---------------------------------------------------------------------------
|
|
197
|
+
// Private: build complete hook config
|
|
198
|
+
// ---------------------------------------------------------------------------
|
|
199
|
+
buildHookConfig(scopeRules, evidenceLogPath, input) {
|
|
200
|
+
const escapedEvidence = evidenceLogPath.replace(/'/g, "'\\''");
|
|
201
|
+
return {
|
|
202
|
+
version: 1,
|
|
203
|
+
hooks: {
|
|
204
|
+
sessionStart: [{
|
|
205
|
+
type: 'command',
|
|
206
|
+
bash: `node -e "const entry={timestamp:new Date().toISOString(),event:'sessionStart',tool:'session',filePath:'${input.stepBranch}'};try{require('fs').appendFileSync('${escapedEvidence}',JSON.stringify(entry)+'\\n')}catch(e){}"`,
|
|
207
|
+
timeoutSec: 10
|
|
208
|
+
}],
|
|
209
|
+
preToolUse: [{
|
|
210
|
+
type: 'command',
|
|
211
|
+
bash: this.buildPreToolUseScript(scopeRules, evidenceLogPath, input.agent.name),
|
|
212
|
+
timeoutSec: 10
|
|
213
|
+
}],
|
|
214
|
+
postToolUse: [{
|
|
215
|
+
type: 'command',
|
|
216
|
+
bash: this.buildPostToolUseScript(evidenceLogPath),
|
|
217
|
+
timeoutSec: 10
|
|
218
|
+
}],
|
|
219
|
+
errorOccurred: [{
|
|
220
|
+
type: 'command',
|
|
221
|
+
bash: `node -e "let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{try{const ctx=JSON.parse(d);const entry={timestamp:new Date().toISOString(),event:'errorOccurred',tool:'error',exitCode:1};require('fs').appendFileSync('${escapedEvidence}',JSON.stringify(entry)+'\\n')}catch(e){}})"`,
|
|
222
|
+
timeoutSec: 10
|
|
223
|
+
}]
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
exports.HookGenerator = HookGenerator;
|
|
229
|
+
exports.default = HookGenerator;
|
|
@@ -0,0 +1,48 @@
|
|
|
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
15
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.validateURL = exports.StatisticsTracker = exports.URLShortener = exports.load_quality_gates_config = exports.run_quality_gates = exports.PMAgent = exports.RepairAgent = exports.DemoMode = exports.ShareParser = exports.VerifierEngine = exports.SessionExecutor = exports.ConfigLoader = exports.PlanGenerator = exports.SwarmOrchestrator = void 0;
|
|
19
|
+
/**
|
|
20
|
+
* Swarm Orchestrator - Public API
|
|
21
|
+
* Import these for programmatic use of the orchestrator.
|
|
22
|
+
*/
|
|
23
|
+
var swarm_orchestrator_1 = require("./swarm-orchestrator");
|
|
24
|
+
Object.defineProperty(exports, "SwarmOrchestrator", { enumerable: true, get: function () { return swarm_orchestrator_1.SwarmOrchestrator; } });
|
|
25
|
+
var plan_generator_1 = require("./plan-generator");
|
|
26
|
+
Object.defineProperty(exports, "PlanGenerator", { enumerable: true, get: function () { return plan_generator_1.PlanGenerator; } });
|
|
27
|
+
var config_loader_1 = require("./config-loader");
|
|
28
|
+
Object.defineProperty(exports, "ConfigLoader", { enumerable: true, get: function () { return config_loader_1.ConfigLoader; } });
|
|
29
|
+
var session_executor_1 = require("./session-executor");
|
|
30
|
+
Object.defineProperty(exports, "SessionExecutor", { enumerable: true, get: function () { return session_executor_1.SessionExecutor; } });
|
|
31
|
+
var verifier_engine_1 = require("./verifier-engine");
|
|
32
|
+
Object.defineProperty(exports, "VerifierEngine", { enumerable: true, get: function () { return verifier_engine_1.VerifierEngine; } });
|
|
33
|
+
var share_parser_1 = require("./share-parser");
|
|
34
|
+
Object.defineProperty(exports, "ShareParser", { enumerable: true, get: function () { return share_parser_1.ShareParser; } });
|
|
35
|
+
var demo_mode_1 = require("./demo-mode");
|
|
36
|
+
Object.defineProperty(exports, "DemoMode", { enumerable: true, get: function () { return demo_mode_1.DemoMode; } });
|
|
37
|
+
var repair_agent_1 = require("./repair-agent");
|
|
38
|
+
Object.defineProperty(exports, "RepairAgent", { enumerable: true, get: function () { return repair_agent_1.RepairAgent; } });
|
|
39
|
+
var pm_agent_1 = require("./pm-agent");
|
|
40
|
+
Object.defineProperty(exports, "PMAgent", { enumerable: true, get: function () { return pm_agent_1.PMAgent; } });
|
|
41
|
+
var quality_gates_1 = require("./quality-gates");
|
|
42
|
+
Object.defineProperty(exports, "run_quality_gates", { enumerable: true, get: function () { return quality_gates_1.run_quality_gates; } });
|
|
43
|
+
Object.defineProperty(exports, "load_quality_gates_config", { enumerable: true, get: function () { return quality_gates_1.load_quality_gates_config; } });
|
|
44
|
+
var url_shortener_1 = require("./url-shortener");
|
|
45
|
+
Object.defineProperty(exports, "URLShortener", { enumerable: true, get: function () { return url_shortener_1.URLShortener; } });
|
|
46
|
+
Object.defineProperty(exports, "StatisticsTracker", { enumerable: true, get: function () { return url_shortener_1.StatisticsTracker; } });
|
|
47
|
+
Object.defineProperty(exports, "validateURL", { enumerable: true, get: function () { return url_shortener_1.validateURL; } });
|
|
48
|
+
__exportStar(require("./verification"), exports);
|