fraim-framework 2.0.56 → 2.0.58
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/CHANGELOG.md +10 -0
- package/bin/fraim-mcp.js +14 -0
- package/bin/fraim.js +23 -0
- package/dist/src/cli/commands/init-project.js +10 -4
- package/dist/src/cli/commands/mcp.js +65 -0
- package/dist/src/cli/setup/mcp-config-generator.js +19 -16
- package/dist/src/fraim/issue-tracking/ado-provider.js +304 -0
- package/dist/src/fraim/issue-tracking/factory.js +63 -0
- package/dist/src/fraim/issue-tracking/github-provider.js +200 -0
- package/dist/src/fraim/issue-tracking/types.js +7 -0
- package/dist/src/fraim/issue-tracking-config.js +83 -0
- package/dist/src/local-mcp-server/stdio-server.js +207 -0
- package/dist/src/utils/workflow-parser.js +81 -0
- package/package.json +17 -12
- package/registry/scripts/pdf-styles.css +172 -0
- package/registry/scripts/prep-issue.sh +46 -4
- package/registry/scripts/profile-server.ts +131 -130
- package/registry/stubs/workflows/customer-development/user-survey-dispatch.md +1 -1
- package/registry/stubs/workflows/customer-development/users-to-target.md +1 -1
- package/registry/stubs/workflows/product-building/design.md +1 -1
- package/registry/stubs/workflows/product-building/implement.md +1 -1
- package/Claude.md +0 -1
- package/dist/registry/ai-manager-rules/customer-development-phases/phase1-customer-profiling.md +0 -101
- package/dist/registry/ai-manager-rules/customer-development-phases/phase2-platform-discovery.md +0 -235
- package/dist/registry/ai-manager-rules/customer-development-phases/phase3-prospect-qualification.md +0 -243
- package/dist/registry/ai-manager-rules/customer-development-phases/phase4-inventory-compilation.md +0 -206
- package/dist/registry/ai-manager-rules/design-phases/design-completeness-review.md +0 -73
- package/dist/registry/ai-manager-rules/design-phases/design-design.md +0 -145
- package/dist/registry/ai-manager-rules/implement-phases/implement-code.md +0 -283
- package/dist/registry/ai-manager-rules/implement-phases/implement-completeness-review.md +0 -120
- package/dist/registry/ai-manager-rules/implement-phases/implement-regression.md +0 -173
- package/dist/registry/ai-manager-rules/implement-phases/implement-repro.md +0 -104
- package/dist/registry/ai-manager-rules/implement-phases/implement-scoping.md +0 -100
- package/dist/registry/ai-manager-rules/implement-phases/implement-smoke.md +0 -237
- package/dist/registry/ai-manager-rules/implement-phases/implement-spike.md +0 -121
- package/dist/registry/ai-manager-rules/implement-phases/implement-validate.md +0 -375
- package/dist/registry/ai-manager-rules/retrospective.md +0 -116
- package/dist/registry/ai-manager-rules/shared-phases/address-pr-feedback.md +0 -188
- package/dist/registry/ai-manager-rules/shared-phases/submit-pr.md +0 -202
- package/dist/registry/ai-manager-rules/shared-phases/wait-for-pr-review.md +0 -170
- package/dist/registry/ai-manager-rules/spec-phases/spec-competitor-analysis.md +0 -105
- package/dist/registry/ai-manager-rules/spec-phases/spec-completeness-review.md +0 -66
- package/dist/registry/ai-manager-rules/spec-phases/spec-spec.md +0 -139
- package/dist/registry/ai-manager-rules/user-survey-phases/phase1-survey-scoping.md +0 -60
- package/dist/registry/ai-manager-rules/user-survey-phases/phase2-survey-build-linkedin.md +0 -23
- package/dist/registry/ai-manager-rules/user-survey-phases/phase3-survey-build-reddit.md +0 -22
- package/dist/registry/ai-manager-rules/user-survey-phases/phase4-survey-build-x.md +0 -21
- package/dist/registry/ai-manager-rules/user-survey-phases/phase5-survey-build-facebook.md +0 -19
- package/dist/registry/ai-manager-rules/user-survey-phases/phase6-survey-build-custom.md +0 -15
- package/dist/registry/ai-manager-rules/user-survey-phases/phase7-survey-dispatch.md +0 -45
- package/dist/registry/providers/ado.json +0 -19
- package/dist/registry/providers/github.json +0 -19
- package/dist/registry/scripts/cleanup-branch.js +0 -287
- package/dist/registry/scripts/evaluate-code-quality.js +0 -66
- package/dist/registry/scripts/exec-with-timeout.js +0 -142
- package/dist/registry/scripts/generate-engagement-emails.js +0 -705
- package/dist/registry/scripts/newsletter-helpers.js +0 -671
- package/dist/registry/scripts/profile-server.js +0 -388
- package/dist/registry/scripts/run-thank-you-workflow.js +0 -92
- package/dist/registry/scripts/send-newsletter-simple.js +0 -85
- package/dist/registry/scripts/send-thank-you-emails.js +0 -54
- package/dist/registry/scripts/validate-openapi-limits.js +0 -311
- package/dist/registry/scripts/validate-test-coverage.js +0 -262
- package/dist/registry/scripts/verify-test-coverage.js +0 -66
- package/dist/registry/templates/bootstrap/ARCHITECTURE-TEMPLATE.md +0 -53
- package/dist/registry/templates/bootstrap/CODE-QUALITY-REPORT-TEMPLATE.md +0 -37
- package/dist/registry/templates/bootstrap/TEST-COVERAGE-REPORT-TEMPLATE.md +0 -35
- package/dist/registry/templates/business-development/IDEATION-REPORT-TEMPLATE.md +0 -29
- package/dist/registry/templates/business-development/PRICING-STRATEGY-TEMPLATE.md +0 -126
- package/dist/registry/templates/customer-development/customer-interview-template.md +0 -99
- package/dist/registry/templates/customer-development/customer-persona-template.md +0 -69
- package/dist/registry/templates/customer-development/follow-up-email-templates.md +0 -132
- package/dist/registry/templates/customer-development/insight-analysis-template.md +0 -74
- package/dist/registry/templates/customer-development/prospect-inventory-template.csv +0 -3
- package/dist/registry/templates/customer-development/search-strategy-template.md +0 -123
- package/dist/registry/templates/customer-development/strategic-recommendations-template.md +0 -53
- package/dist/registry/templates/customer-development/thank-you-email-template.html +0 -124
- package/dist/registry/templates/customer-development/thank-you-note-template.md +0 -16
- package/dist/registry/templates/customer-development/triage-log-template.md +0 -278
- package/dist/registry/templates/customer-development/weekly-newsletter-template.html +0 -204
- package/dist/registry/templates/evidence/Design-Evidence.md +0 -30
- package/dist/registry/templates/evidence/Implementation-BugEvidence.md +0 -94
- package/dist/registry/templates/evidence/Implementation-FeatureEvidence.md +0 -129
- package/dist/registry/templates/evidence/Spec-Evidence.md +0 -19
- package/dist/registry/templates/help/HelpNeeded.md +0 -14
- package/dist/registry/templates/legal/NDA-TEMPLATE.md +0 -170
- package/dist/registry/templates/legal/PATENT-TEMPLATE.md +0 -372
- package/dist/registry/templates/legal/TRADEMARK-TEMPLATE.md +0 -339
- package/dist/registry/templates/legal/contract-review-checklist.md +0 -193
- package/dist/registry/templates/legal/review-report-template.md +0 -198
- package/dist/registry/templates/legal/saas-terms-template.md +0 -174
- package/dist/registry/templates/legal/sow-template.md +0 -117
- package/dist/registry/templates/legal/template-variables.md +0 -131
- package/dist/registry/templates/marketing/DOMAIN-REGISTRATION-TEMPLATE.md +0 -194
- package/dist/registry/templates/marketing/HBR-ARTICLE-TEMPLATE.md +0 -66
- package/dist/registry/templates/marketing/STORYTELLING-TEMPLATE.md +0 -130
- package/dist/registry/templates/marketing/WEBSITE-TEMPLATE.md +0 -262
- package/dist/registry/templates/marketing/github-pages-workflow.yml +0 -64
- package/dist/registry/templates/replicate/implementation-checklist.md +0 -39
- package/dist/registry/templates/replicate/use-cases-template.md +0 -88
- package/dist/registry/templates/retrospective/RETROSPECTIVE-TEMPLATE.md +0 -55
- package/dist/registry/templates/specs/BUGSPEC-TEMPLATE.md +0 -37
- package/dist/registry/templates/specs/FEATURESPEC-TEMPLATE.md +0 -66
- package/dist/registry/templates/specs/TECHSPEC-TEMPLATE.md +0 -39
- package/dist/registry/workflows/bootstrap/create-architecture.md +0 -38
- package/dist/registry/workflows/bootstrap/detect-broken-windows.md +0 -300
- package/dist/registry/workflows/bootstrap/evaluate-code-quality.md +0 -35
- package/dist/registry/workflows/bootstrap/verify-test-coverage.md +0 -36
- package/dist/registry/workflows/brainstorming/blue-sky-brainstorming.md +0 -211
- package/dist/registry/workflows/brainstorming/codebase-brainstorming.md +0 -165
- package/dist/registry/workflows/business-development/create-business-plan.md +0 -737
- package/dist/registry/workflows/business-development/ideate-business-opportunity.md +0 -55
- package/dist/registry/workflows/business-development/price-product.md +0 -325
- package/dist/registry/workflows/compliance/detect-compliance-requirements.md +0 -78
- package/dist/registry/workflows/compliance/generate-audit-evidence.md +0 -75
- package/dist/registry/workflows/compliance/soc2-evidence-generator.md +0 -332
- package/dist/registry/workflows/customer-development/insight-analysis.md +0 -156
- package/dist/registry/workflows/customer-development/insight-triage.md +0 -938
- package/dist/registry/workflows/customer-development/interview-preparation.md +0 -452
- package/dist/registry/workflows/customer-development/linkedin-outreach.md +0 -593
- package/dist/registry/workflows/customer-development/strategic-brainstorming.md +0 -146
- package/dist/registry/workflows/customer-development/thank-customers.md +0 -203
- package/dist/registry/workflows/customer-development/user-survey-dispatch.md +0 -60
- package/dist/registry/workflows/customer-development/users-to-target.md +0 -112
- package/dist/registry/workflows/customer-development/weekly-newsletter.md +0 -366
- package/dist/registry/workflows/deploy/cloud-deployment.md +0 -310
- package/dist/registry/workflows/improve-fraim/contribute.md +0 -32
- package/dist/registry/workflows/improve-fraim/file-issue.md +0 -32
- package/dist/registry/workflows/learning/build-skillset.md +0 -212
- package/dist/registry/workflows/learning/synthesize-learnings.md +0 -284
- package/dist/registry/workflows/legal/contract-review-analysis.md +0 -382
- package/dist/registry/workflows/legal/nda.md +0 -69
- package/dist/registry/workflows/legal/patent-filing.md +0 -76
- package/dist/registry/workflows/legal/saas-contract-development.md +0 -213
- package/dist/registry/workflows/legal/trademark-filing.md +0 -77
- package/dist/registry/workflows/marketing/content-creation.md +0 -37
- package/dist/registry/workflows/marketing/convert-to-pdf.md +0 -235
- package/dist/registry/workflows/marketing/create-modern-website.md +0 -456
- package/dist/registry/workflows/marketing/domain-registration.md +0 -323
- package/dist/registry/workflows/marketing/hbr-article.md +0 -73
- package/dist/registry/workflows/marketing/launch-checklist.md +0 -37
- package/dist/registry/workflows/marketing/marketing-strategy.md +0 -45
- package/dist/registry/workflows/marketing/storytelling.md +0 -65
- package/dist/registry/workflows/performance/analyze-performance.md +0 -65
- package/dist/registry/workflows/product-building/design.md +0 -103
- package/dist/registry/workflows/product-building/implement.md +0 -74
- package/dist/registry/workflows/product-building/iterate-on-pr-comments.md +0 -70
- package/dist/registry/workflows/product-building/prep-issue.md +0 -41
- package/dist/registry/workflows/product-building/prototype.md +0 -65
- package/dist/registry/workflows/product-building/resolve.md +0 -168
- package/dist/registry/workflows/product-building/retrospect.md +0 -86
- package/dist/registry/workflows/product-building/spec.md +0 -181
- package/dist/registry/workflows/product-building/test.md +0 -125
- package/dist/registry/workflows/productivity-report/productivity-report.md +0 -263
- package/dist/registry/workflows/quality-assurance/browser-validation.md +0 -221
- package/dist/registry/workflows/quality-assurance/iterative-improvement-cycle.md +0 -562
- package/dist/registry/workflows/replicate/replicate-discovery.md +0 -336
- package/dist/registry/workflows/replicate/replicate-to-issues.md +0 -324
- package/dist/registry/workflows/reviewer/review-implementation-vs-design-spec.md +0 -638
- package/dist/registry/workflows/reviewer/review-implementation-vs-feature-spec.md +0 -675
- package/dist/registry/workflows/startup-credits/aws-activate-application.md +0 -535
- package/dist/registry/workflows/startup-credits/google-cloud-application.md +0 -647
- package/dist/registry/workflows/startup-credits/microsoft-azure-application.md +0 -538
- package/dist/scripts/build-stub-registry.js +0 -108
- package/dist/src/ai-manager/ai-manager.js +0 -480
- package/dist/src/ai-manager/phase-flow.js +0 -357
- package/dist/src/ai-manager/types.js +0 -5
- package/dist/src/fraim-mcp-server.js +0 -1885
- package/dist/tests/debug-tools.js +0 -80
- package/dist/tests/shared-server-utils.js +0 -57
- package/dist/tests/test-add-ide.js +0 -283
- package/dist/tests/test-ai-coach-edge-cases.js +0 -420
- package/dist/tests/test-ai-coach-mcp-integration.js +0 -450
- package/dist/tests/test-ai-coach-performance.js +0 -328
- package/dist/tests/test-ai-coach-phase-content.js +0 -264
- package/dist/tests/test-ai-coach-workflows.js +0 -514
- package/dist/tests/test-cli.js +0 -228
- package/dist/tests/test-client-scripts-validation.js +0 -167
- package/dist/tests/test-complete-setup-flow.js +0 -110
- package/dist/tests/test-config-system.js +0 -279
- package/dist/tests/test-debug-session.js +0 -134
- package/dist/tests/test-end-to-end-hybrid-validation.js +0 -328
- package/dist/tests/test-enhanced-session-init.js +0 -188
- package/dist/tests/test-first-run-journey.js +0 -368
- package/dist/tests/test-fraim-issues.js +0 -59
- package/dist/tests/test-genericization.js +0 -44
- package/dist/tests/test-hybrid-script-execution.js +0 -340
- package/dist/tests/test-ide-detector.js +0 -46
- package/dist/tests/test-improved-setup.js +0 -121
- package/dist/tests/test-mcp-config-generator.js +0 -99
- package/dist/tests/test-mcp-connection.js +0 -107
- package/dist/tests/test-mcp-issue-integration.js +0 -156
- package/dist/tests/test-mcp-lifecycle-methods.js +0 -240
- package/dist/tests/test-mcp-shared-server.js +0 -308
- package/dist/tests/test-mcp-template-processing.js +0 -160
- package/dist/tests/test-modular-issue-tracking.js +0 -165
- package/dist/tests/test-node-compatibility.js +0 -95
- package/dist/tests/test-npm-install.js +0 -68
- package/dist/tests/test-package-size.js +0 -108
- package/dist/tests/test-pr-review-workflow.js +0 -307
- package/dist/tests/test-prep-issue.js +0 -129
- package/dist/tests/test-productivity-integration.js +0 -157
- package/dist/tests/test-script-location-independence.js +0 -198
- package/dist/tests/test-script-sync.js +0 -557
- package/dist/tests/test-server-utils.js +0 -32
- package/dist/tests/test-session-rehydration.js +0 -148
- package/dist/tests/test-setup-integration.js +0 -98
- package/dist/tests/test-setup-scenarios.js +0 -322
- package/dist/tests/test-standalone.js +0 -143
- package/dist/tests/test-stub-registry.js +0 -136
- package/dist/tests/test-sync-stubs.js +0 -143
- package/dist/tests/test-sync-version-update.js +0 -93
- package/dist/tests/test-telemetry.js +0 -193
- package/dist/tests/test-token-validator.js +0 -30
- package/dist/tests/test-user-journey.js +0 -236
- package/dist/tests/test-users-to-target-workflow.js +0 -253
- package/dist/tests/test-utils.js +0 -109
- package/dist/tests/test-wizard.js +0 -71
- package/dist/tests/test-workflow-discovery.js +0 -242
- package/labels.json +0 -52
- package/registry/agent-guardrails.md +0 -63
- package/registry/fraim.md +0 -48
- package/setup.js +0 -171
- package/tsconfig.json +0 -23
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
|
|
6
|
+
## [2.1.0] - 2026-02-04
|
|
7
|
+
|
|
8
|
+
### 🔄 Workflow Refinement
|
|
9
|
+
- **Consolidated Workflows**: Inlined all phase content into main workflow files (`spec.md`, `design.md`, `implement.md`) for better context retention and reduced file scatter.
|
|
10
|
+
- **Removed Redundant Files**: Deleted separate phase folders (`design-phases`, `implement-phases`, `spec-phases`, etc.) to streamline repository structure.
|
|
11
|
+
- **Terminology Update**: Renamed "AI Coach" to "AI Mentor" across all workflows to align with new branding.
|
|
12
|
+
- **Enhanced Spec Workflow**: Added `spec-competitor-analysis` phase and inlined validation steps.
|
|
13
|
+
- **Retrospective Integration**: Inlined retrospective phase content into all major workflows.
|
|
14
|
+
|
|
5
15
|
## [2.0.0] - 2024-12-19
|
|
6
16
|
|
|
7
17
|
### 🚀 Major Release: FRAIM v2 - The Future of AI-Assisted Development
|
package/bin/fraim-mcp.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* FRAIM MCP Server Entry Point
|
|
4
|
+
*
|
|
5
|
+
* This is called by MCP clients (Cursor, Claude Desktop, Windsurf, Kiro, etc.)
|
|
6
|
+
* It starts the local STDIO MCP server that proxies to the remote FRAIM server
|
|
7
|
+
* and performs template substitution.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// Load and start the server
|
|
11
|
+
const { FraimLocalMCPServer } = require('../dist/src/local-mcp-server/stdio-server.js');
|
|
12
|
+
|
|
13
|
+
const server = new FraimLocalMCPServer();
|
|
14
|
+
server.start();
|
package/bin/fraim.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* FRAIM Framework CLI Entry Point
|
|
5
|
+
*
|
|
6
|
+
* This file delegates to the compiled TypeScript implementation.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
// In production/installed package, code is in dist/
|
|
11
|
+
require('../dist/src/cli/fraim.js');
|
|
12
|
+
} catch (error) {
|
|
13
|
+
if (error.code === 'MODULE_NOT_FOUND') {
|
|
14
|
+
// In development (local clone), we might use tsx if dist is missing
|
|
15
|
+
// But typically we should just tell user to build.
|
|
16
|
+
console.error('❌ Could not find FRAIM CLI implementation.');
|
|
17
|
+
console.error(' If you are running from source, please run "npm run build" first.');
|
|
18
|
+
console.error(` Error details: ${error.message}`);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
} else {
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -39,18 +39,24 @@ const runInitProject = async () => {
|
|
|
39
39
|
if (!fs_1.default.existsSync(configPath)) {
|
|
40
40
|
const remoteInfo = (0, git_utils_1.getGitRemoteInfo)();
|
|
41
41
|
// Git remote is optional for project init
|
|
42
|
+
const repoOwner = remoteInfo.owner || 'your-username';
|
|
43
|
+
const repoName = remoteInfo.repo || path_1.default.basename(projectRoot);
|
|
44
|
+
const repoUrl = remoteInfo.owner && remoteInfo.repo
|
|
45
|
+
? `https://github.com/${remoteInfo.owner}/${remoteInfo.repo}.git`
|
|
46
|
+
: `https://github.com/${repoOwner}/${repoName}.git`;
|
|
42
47
|
const config = {
|
|
43
48
|
...types_1.DEFAULT_FRAIM_CONFIG,
|
|
44
49
|
version: (0, version_utils_1.getFraimVersion)(),
|
|
45
50
|
project: {
|
|
46
51
|
...types_1.DEFAULT_FRAIM_CONFIG.project,
|
|
47
|
-
name:
|
|
52
|
+
name: repoName
|
|
48
53
|
},
|
|
49
54
|
repository: {
|
|
50
55
|
provider: 'github',
|
|
51
|
-
owner:
|
|
52
|
-
name:
|
|
53
|
-
|
|
56
|
+
owner: repoOwner,
|
|
57
|
+
name: repoName,
|
|
58
|
+
url: repoUrl,
|
|
59
|
+
defaultBranch: remoteInfo.defaultBranch || 'main'
|
|
54
60
|
}
|
|
55
61
|
};
|
|
56
62
|
fs_1.default.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.mcpCommand = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const server_1 = require("../../local-mcp-server/server");
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
+
exports.mcpCommand = new commander_1.Command('mcp')
|
|
11
|
+
.description('Start the local FRAIM MCP server')
|
|
12
|
+
.option('-p, --port <port>', 'Port to run the server on', '3003')
|
|
13
|
+
.option('--remote-only', 'Use remote server only (skip local proxy)', false)
|
|
14
|
+
.action(async (options) => {
|
|
15
|
+
try {
|
|
16
|
+
if (options.remoteOnly) {
|
|
17
|
+
console.log(chalk_1.default.yellow('⚠️ Remote-only mode not yet implemented'));
|
|
18
|
+
console.log(chalk_1.default.blue('ℹ️ Starting local MCP server instead...'));
|
|
19
|
+
}
|
|
20
|
+
const port = parseInt(options.port);
|
|
21
|
+
if (isNaN(port) || port < 1 || port > 65535) {
|
|
22
|
+
console.error(chalk_1.default.red('❌ Invalid port number. Must be between 1 and 65535.'));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
console.log(chalk_1.default.blue('🚀 Starting FRAIM Local MCP Server...'));
|
|
26
|
+
console.log(chalk_1.default.gray(`📡 Port: ${port}`));
|
|
27
|
+
console.log(chalk_1.default.gray(`🔄 Auto-updates: Every 5 minutes`));
|
|
28
|
+
console.log(chalk_1.default.gray(`📁 Cache: ~/.fraim/cache`));
|
|
29
|
+
console.log('');
|
|
30
|
+
// Set the port in environment
|
|
31
|
+
process.env.FRAIM_LOCAL_MCP_PORT = port.toString();
|
|
32
|
+
// Start the server
|
|
33
|
+
await (0, server_1.startLocalMCPServer)();
|
|
34
|
+
// Server is now running, show configuration instructions
|
|
35
|
+
console.log('');
|
|
36
|
+
console.log(chalk_1.default.green('✅ FRAIM Local MCP Server is running!'));
|
|
37
|
+
console.log('');
|
|
38
|
+
console.log(chalk_1.default.bold('📋 Agent Configuration:'));
|
|
39
|
+
console.log('');
|
|
40
|
+
console.log(chalk_1.default.gray('Add this to your agent\'s MCP configuration:'));
|
|
41
|
+
console.log('');
|
|
42
|
+
console.log(chalk_1.default.cyan(JSON.stringify({
|
|
43
|
+
"mcpServers": {
|
|
44
|
+
"fraim": {
|
|
45
|
+
"command": "fraim",
|
|
46
|
+
"args": ["mcp"],
|
|
47
|
+
"env": {}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}, null, 2)));
|
|
51
|
+
console.log('');
|
|
52
|
+
console.log(chalk_1.default.bold('🔗 Endpoints:'));
|
|
53
|
+
console.log(chalk_1.default.gray(` MCP: http://localhost:${port}/mcp`));
|
|
54
|
+
console.log(chalk_1.default.gray(` Health: http://localhost:${port}/health`));
|
|
55
|
+
console.log('');
|
|
56
|
+
console.log(chalk_1.default.bold('🛑 To stop the server:'));
|
|
57
|
+
console.log(chalk_1.default.gray(' Press Ctrl+C'));
|
|
58
|
+
console.log('');
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
console.error(chalk_1.default.red('❌ Failed to start Local MCP Server:'));
|
|
62
|
+
console.error(chalk_1.default.red(error instanceof Error ? error.message : String(error)));
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
@@ -18,9 +18,10 @@ const generateStandardMCPServers = (fraimKey, githubToken) => ({
|
|
|
18
18
|
args: ["-y", "@playwright/mcp"]
|
|
19
19
|
},
|
|
20
20
|
fraim: {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
command: "fraim-mcp",
|
|
22
|
+
env: {
|
|
23
|
+
FRAIM_API_KEY: fraimKey,
|
|
24
|
+
FRAIM_REMOTE_URL: "https://fraim.wellnessatwork.me"
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
}
|
|
@@ -44,10 +45,10 @@ const generateClaudeMCPServers = (fraimKey, githubToken) => ({
|
|
|
44
45
|
args: ["-y", "@playwright/mcp"]
|
|
45
46
|
},
|
|
46
47
|
fraim: {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"
|
|
48
|
+
command: "fraim-mcp",
|
|
49
|
+
env: {
|
|
50
|
+
FRAIM_API_KEY: fraimKey,
|
|
51
|
+
FRAIM_REMOTE_URL: "https://fraim.wellnessatwork.me"
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
54
|
}
|
|
@@ -70,9 +71,10 @@ const generateKiroMCPServers = (fraimKey, githubToken) => ({
|
|
|
70
71
|
args: ["-y", "@playwright/mcp"]
|
|
71
72
|
},
|
|
72
73
|
fraim: {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
command: "fraim-mcp",
|
|
75
|
+
env: {
|
|
76
|
+
FRAIM_API_KEY: fraimKey,
|
|
77
|
+
FRAIM_REMOTE_URL: "https://fraim.wellnessatwork.me"
|
|
76
78
|
}
|
|
77
79
|
}
|
|
78
80
|
}
|
|
@@ -92,10 +94,11 @@ command = "npx"
|
|
|
92
94
|
args = ["-y", "@playwright/mcp"]
|
|
93
95
|
|
|
94
96
|
[mcp_servers.fraim]
|
|
95
|
-
|
|
97
|
+
command = "fraim-mcp"
|
|
96
98
|
|
|
97
|
-
[mcp_servers.fraim.
|
|
98
|
-
|
|
99
|
+
[mcp_servers.fraim.env]
|
|
100
|
+
FRAIM_API_KEY = "${fraimKey}"
|
|
101
|
+
FRAIM_REMOTE_URL = "https://fraim.wellnessatwork.me"
|
|
99
102
|
`;
|
|
100
103
|
exports.generateCodexMCPServers = generateCodexMCPServers;
|
|
101
104
|
const generateWindsurfMCPServers = (fraimKey, githubToken) => ({
|
|
@@ -116,10 +119,10 @@ const generateWindsurfMCPServers = (fraimKey, githubToken) => ({
|
|
|
116
119
|
args: ["-y", "@playwright/mcp"]
|
|
117
120
|
},
|
|
118
121
|
fraim: {
|
|
119
|
-
command: "
|
|
120
|
-
args: ["-y", "@modelcontextprotocol/server-fetch", "https://fraim.wellnessatwork.me"],
|
|
122
|
+
command: "fraim-mcp",
|
|
121
123
|
env: {
|
|
122
|
-
FRAIM_API_KEY: fraimKey
|
|
124
|
+
FRAIM_API_KEY: fraimKey,
|
|
125
|
+
FRAIM_REMOTE_URL: "https://fraim.wellnessatwork.me"
|
|
123
126
|
}
|
|
124
127
|
}
|
|
125
128
|
}
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Azure DevOps (ADO) Issue Tracking Provider
|
|
4
|
+
*
|
|
5
|
+
* Implements the IssueTrackingProvider interface for Azure DevOps Work Items
|
|
6
|
+
*/
|
|
7
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
8
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
9
|
+
};
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.AdoIssueProvider = void 0;
|
|
12
|
+
const axios_1 = __importDefault(require("axios"));
|
|
13
|
+
class AdoIssueProvider {
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.config = config;
|
|
16
|
+
// Support both cloud and on-premise ADO
|
|
17
|
+
this.baseUrl = config.baseUrl || `https://dev.azure.com/${config.organization}`;
|
|
18
|
+
}
|
|
19
|
+
async createIssue(params) {
|
|
20
|
+
const { title, body, labels, assignee, priority, dryRun } = params;
|
|
21
|
+
// ADO uses PATCH with JSON Patch format for work item creation
|
|
22
|
+
const patchDocument = [
|
|
23
|
+
{
|
|
24
|
+
op: 'add',
|
|
25
|
+
path: '/fields/System.Title',
|
|
26
|
+
value: title
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
op: 'add',
|
|
30
|
+
path: '/fields/System.Description',
|
|
31
|
+
value: body
|
|
32
|
+
}
|
|
33
|
+
];
|
|
34
|
+
// Add assignee if provided
|
|
35
|
+
if (assignee) {
|
|
36
|
+
patchDocument.push({
|
|
37
|
+
op: 'add',
|
|
38
|
+
path: '/fields/System.AssignedTo',
|
|
39
|
+
value: assignee
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
// Map priority to ADO priority values
|
|
43
|
+
if (priority) {
|
|
44
|
+
const adoPriority = this.mapPriorityToAdo(priority);
|
|
45
|
+
patchDocument.push({
|
|
46
|
+
op: 'add',
|
|
47
|
+
path: '/fields/Microsoft.VSTS.Common.Priority',
|
|
48
|
+
value: adoPriority
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
// Add tags (ADO equivalent of labels)
|
|
52
|
+
if (labels && labels.length > 0) {
|
|
53
|
+
patchDocument.push({
|
|
54
|
+
op: 'add',
|
|
55
|
+
path: '/fields/System.Tags',
|
|
56
|
+
value: labels.join('; ')
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
if (dryRun) {
|
|
60
|
+
return {
|
|
61
|
+
success: true,
|
|
62
|
+
dryRun: true,
|
|
63
|
+
provider: 'ado',
|
|
64
|
+
message: `[DRY RUN] Would create ADO work item: "${title}" in ${this.config.organization}/${this.config.project}`
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
const url = `${this.baseUrl}/${this.config.project}/_apis/wit/workitems/$Bug?api-version=7.0`;
|
|
69
|
+
const response = await axios_1.default.post(url, patchDocument, {
|
|
70
|
+
headers: {
|
|
71
|
+
'Authorization': `Basic ${Buffer.from(`:${this.config.token}`).toString('base64')}`,
|
|
72
|
+
'Content-Type': 'application/json-patch+json',
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
return {
|
|
76
|
+
success: true,
|
|
77
|
+
issueId: response.data.id,
|
|
78
|
+
issueNumber: response.data.id,
|
|
79
|
+
htmlUrl: response.data._links.html.href,
|
|
80
|
+
provider: 'ado'
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
return {
|
|
85
|
+
success: false,
|
|
86
|
+
provider: 'ado',
|
|
87
|
+
message: this.formatError(error)
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async getIssue(issueId) {
|
|
92
|
+
try {
|
|
93
|
+
const url = `${this.baseUrl}/${this.config.project}/_apis/wit/workitems/${issueId}?api-version=7.0`;
|
|
94
|
+
const response = await axios_1.default.get(url, {
|
|
95
|
+
headers: {
|
|
96
|
+
'Authorization': `Basic ${Buffer.from(`:${this.config.token}`).toString('base64')}`,
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
const workItem = response.data;
|
|
100
|
+
const fields = workItem.fields;
|
|
101
|
+
return {
|
|
102
|
+
id: workItem.id,
|
|
103
|
+
title: fields['System.Title'] || '',
|
|
104
|
+
body: fields['System.Description'] || '',
|
|
105
|
+
state: this.mapAdoStateToGeneric(fields['System.State']),
|
|
106
|
+
assignee: fields['System.AssignedTo']?.displayName,
|
|
107
|
+
labels: fields['System.Tags'] ? fields['System.Tags'].split('; ') : [],
|
|
108
|
+
createdAt: new Date(fields['System.CreatedDate']),
|
|
109
|
+
updatedAt: new Date(fields['System.ChangedDate']),
|
|
110
|
+
htmlUrl: workItem._links.html.href
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
if (error.response?.status === 404) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
throw new Error(this.formatError(error));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async updateIssue(issueId, updates) {
|
|
121
|
+
const patchDocument = [];
|
|
122
|
+
if (updates.title) {
|
|
123
|
+
patchDocument.push({
|
|
124
|
+
op: 'replace',
|
|
125
|
+
path: '/fields/System.Title',
|
|
126
|
+
value: updates.title
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
if (updates.body) {
|
|
130
|
+
patchDocument.push({
|
|
131
|
+
op: 'replace',
|
|
132
|
+
path: '/fields/System.Description',
|
|
133
|
+
value: updates.body
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
if (updates.assignee) {
|
|
137
|
+
patchDocument.push({
|
|
138
|
+
op: 'replace',
|
|
139
|
+
path: '/fields/System.AssignedTo',
|
|
140
|
+
value: updates.assignee
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
if (updates.priority) {
|
|
144
|
+
patchDocument.push({
|
|
145
|
+
op: 'replace',
|
|
146
|
+
path: '/fields/Microsoft.VSTS.Common.Priority',
|
|
147
|
+
value: this.mapPriorityToAdo(updates.priority)
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
if (updates.labels) {
|
|
151
|
+
patchDocument.push({
|
|
152
|
+
op: 'replace',
|
|
153
|
+
path: '/fields/System.Tags',
|
|
154
|
+
value: updates.labels.join('; ')
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
if (updates.dryRun) {
|
|
158
|
+
return {
|
|
159
|
+
success: true,
|
|
160
|
+
dryRun: true,
|
|
161
|
+
provider: 'ado',
|
|
162
|
+
message: `[DRY RUN] Would update ADO work item #${issueId} in ${this.config.organization}/${this.config.project}`
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
try {
|
|
166
|
+
const url = `${this.baseUrl}/${this.config.project}/_apis/wit/workitems/${issueId}?api-version=7.0`;
|
|
167
|
+
const response = await axios_1.default.patch(url, patchDocument, {
|
|
168
|
+
headers: {
|
|
169
|
+
'Authorization': `Basic ${Buffer.from(`:${this.config.token}`).toString('base64')}`,
|
|
170
|
+
'Content-Type': 'application/json-patch+json',
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
return {
|
|
174
|
+
success: true,
|
|
175
|
+
issueId: response.data.id,
|
|
176
|
+
issueNumber: response.data.id,
|
|
177
|
+
htmlUrl: response.data._links.html.href,
|
|
178
|
+
provider: 'ado'
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
return {
|
|
183
|
+
success: false,
|
|
184
|
+
provider: 'ado',
|
|
185
|
+
message: this.formatError(error)
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
async listIssues(filters) {
|
|
190
|
+
let wiql = `SELECT [System.Id], [System.Title], [System.State], [System.AssignedTo], [System.CreatedDate], [System.ChangedDate] FROM WorkItems WHERE [System.TeamProject] = '${this.config.project}'`;
|
|
191
|
+
// Add state filter
|
|
192
|
+
if (filters?.state && filters.state !== 'all') {
|
|
193
|
+
const adoState = filters.state === 'open' ? 'Active' : 'Closed';
|
|
194
|
+
wiql += ` AND [System.State] = '${adoState}'`;
|
|
195
|
+
}
|
|
196
|
+
// Add assignee filter
|
|
197
|
+
if (filters?.assignee) {
|
|
198
|
+
wiql += ` AND [System.AssignedTo] = '${filters.assignee}'`;
|
|
199
|
+
}
|
|
200
|
+
// Add label filter (tags in ADO)
|
|
201
|
+
if (filters?.labels && filters.labels.length > 0) {
|
|
202
|
+
const tagConditions = filters.labels.map(label => `[System.Tags] CONTAINS '${label}'`).join(' OR ');
|
|
203
|
+
wiql += ` AND (${tagConditions})`;
|
|
204
|
+
}
|
|
205
|
+
wiql += ' ORDER BY [System.CreatedDate] DESC';
|
|
206
|
+
try {
|
|
207
|
+
// First, execute WIQL query to get work item IDs
|
|
208
|
+
const queryUrl = `${this.baseUrl}/${this.config.project}/_apis/wit/wiql?api-version=7.0`;
|
|
209
|
+
const queryResponse = await axios_1.default.post(queryUrl, { query: wiql }, {
|
|
210
|
+
headers: {
|
|
211
|
+
'Authorization': `Basic ${Buffer.from(`:${this.config.token}`).toString('base64')}`,
|
|
212
|
+
'Content-Type': 'application/json',
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
const workItemIds = queryResponse.data.workItems.map((wi) => wi.id);
|
|
216
|
+
if (workItemIds.length === 0) {
|
|
217
|
+
return [];
|
|
218
|
+
}
|
|
219
|
+
// Limit results
|
|
220
|
+
const limitedIds = workItemIds.slice(0, filters?.limit || 30);
|
|
221
|
+
// Get detailed work item information
|
|
222
|
+
const detailsUrl = `${this.baseUrl}/${this.config.project}/_apis/wit/workitems?ids=${limitedIds.join(',')}&api-version=7.0`;
|
|
223
|
+
const detailsResponse = await axios_1.default.get(detailsUrl, {
|
|
224
|
+
headers: {
|
|
225
|
+
'Authorization': `Basic ${Buffer.from(`:${this.config.token}`).toString('base64')}`,
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
return detailsResponse.data.value.map((workItem) => {
|
|
229
|
+
const fields = workItem.fields;
|
|
230
|
+
return {
|
|
231
|
+
id: workItem.id,
|
|
232
|
+
title: fields['System.Title'] || '',
|
|
233
|
+
body: fields['System.Description'] || '',
|
|
234
|
+
state: this.mapAdoStateToGeneric(fields['System.State']),
|
|
235
|
+
assignee: fields['System.AssignedTo']?.displayName,
|
|
236
|
+
labels: fields['System.Tags'] ? fields['System.Tags'].split('; ') : [],
|
|
237
|
+
createdAt: new Date(fields['System.CreatedDate']),
|
|
238
|
+
updatedAt: new Date(fields['System.ChangedDate']),
|
|
239
|
+
htmlUrl: workItem._links.html.href
|
|
240
|
+
};
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
catch (error) {
|
|
244
|
+
throw new Error(this.formatError(error));
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
async validateConfig() {
|
|
248
|
+
try {
|
|
249
|
+
// Test by getting project info
|
|
250
|
+
const url = `${this.baseUrl}/_apis/projects/${this.config.project}?api-version=7.0`;
|
|
251
|
+
const response = await axios_1.default.get(url, {
|
|
252
|
+
headers: {
|
|
253
|
+
'Authorization': `Basic ${Buffer.from(`:${this.config.token}`).toString('base64')}`,
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
return {
|
|
257
|
+
valid: true,
|
|
258
|
+
message: `Connected to ADO project: ${response.data.name}`
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
return {
|
|
263
|
+
valid: false,
|
|
264
|
+
message: this.formatError(error)
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
mapPriorityToAdo(priority) {
|
|
269
|
+
switch (priority) {
|
|
270
|
+
case 'critical': return 1;
|
|
271
|
+
case 'high': return 2;
|
|
272
|
+
case 'medium': return 3;
|
|
273
|
+
case 'low': return 4;
|
|
274
|
+
default: return 3;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
mapAdoStateToGeneric(adoState) {
|
|
278
|
+
switch (adoState?.toLowerCase()) {
|
|
279
|
+
case 'active':
|
|
280
|
+
case 'new':
|
|
281
|
+
case 'approved':
|
|
282
|
+
return 'open';
|
|
283
|
+
case 'resolved':
|
|
284
|
+
case 'closed':
|
|
285
|
+
case 'done':
|
|
286
|
+
return 'closed';
|
|
287
|
+
case 'committed':
|
|
288
|
+
case 'in progress':
|
|
289
|
+
return 'in-progress';
|
|
290
|
+
default:
|
|
291
|
+
return 'open';
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
formatError(error) {
|
|
295
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
296
|
+
return `ADO API Error: ${error.response?.status} - ${JSON.stringify(error.response?.data)}`;
|
|
297
|
+
}
|
|
298
|
+
else if (error instanceof Error) {
|
|
299
|
+
return `ADO Error: ${error.message}`;
|
|
300
|
+
}
|
|
301
|
+
return 'Unknown ADO error';
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
exports.AdoIssueProvider = AdoIssueProvider;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Issue Tracking Provider Factory
|
|
4
|
+
*
|
|
5
|
+
* Creates the appropriate issue tracking provider based on configuration
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.IssueTrackingFactory = void 0;
|
|
9
|
+
const github_provider_1 = require("./github-provider");
|
|
10
|
+
const ado_provider_1 = require("./ado-provider");
|
|
11
|
+
class IssueTrackingFactory {
|
|
12
|
+
/**
|
|
13
|
+
* Create an issue tracking provider based on configuration
|
|
14
|
+
*/
|
|
15
|
+
static createProvider(config) {
|
|
16
|
+
switch (config.provider) {
|
|
17
|
+
case 'github':
|
|
18
|
+
if (!config.github) {
|
|
19
|
+
throw new Error('GitHub configuration is required when provider is "github"');
|
|
20
|
+
}
|
|
21
|
+
return new github_provider_1.GitHubIssueProvider(config.github);
|
|
22
|
+
case 'ado':
|
|
23
|
+
if (!config.ado) {
|
|
24
|
+
throw new Error('ADO configuration is required when provider is "ado"');
|
|
25
|
+
}
|
|
26
|
+
return new ado_provider_1.AdoIssueProvider(config.ado);
|
|
27
|
+
default:
|
|
28
|
+
throw new Error(`Unsupported issue tracking provider: ${config.provider}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get available providers
|
|
33
|
+
*/
|
|
34
|
+
static getAvailableProviders() {
|
|
35
|
+
return ['github', 'ado'];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Validate configuration without creating provider
|
|
39
|
+
*/
|
|
40
|
+
static validateConfig(config) {
|
|
41
|
+
switch (config.provider) {
|
|
42
|
+
case 'github':
|
|
43
|
+
if (!config.github) {
|
|
44
|
+
return { valid: false, message: 'GitHub configuration is required' };
|
|
45
|
+
}
|
|
46
|
+
if (!config.github.owner || !config.github.repo || !config.github.token) {
|
|
47
|
+
return { valid: false, message: 'GitHub configuration must include owner, repo, and token' };
|
|
48
|
+
}
|
|
49
|
+
return { valid: true };
|
|
50
|
+
case 'ado':
|
|
51
|
+
if (!config.ado) {
|
|
52
|
+
return { valid: false, message: 'ADO configuration is required' };
|
|
53
|
+
}
|
|
54
|
+
if (!config.ado.organization || !config.ado.project || !config.ado.token) {
|
|
55
|
+
return { valid: false, message: 'ADO configuration must include organization, project, and token' };
|
|
56
|
+
}
|
|
57
|
+
return { valid: true };
|
|
58
|
+
default:
|
|
59
|
+
return { valid: false, message: `Unsupported provider: ${config.provider}` };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.IssueTrackingFactory = IssueTrackingFactory;
|