fraim-framework 1.0.3 ā 1.0.5
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/bin/fraim.js +17 -9
- package/package.json +1 -1
- package/setup.js +193 -185
package/bin/fraim.js
CHANGED
|
@@ -83,7 +83,20 @@ async function runSetup() {
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
function
|
|
86
|
+
async function runWizard() {
|
|
87
|
+
try {
|
|
88
|
+
// Import and run the wizard function
|
|
89
|
+
const { runWizard: wizardFunction } = require('../setup.js');
|
|
90
|
+
await wizardFunction();
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.error('ā Failed to run wizard:', error.message);
|
|
93
|
+
console.log('\nš” Try running the setup script directly:');
|
|
94
|
+
console.log(' node setup.js');
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function main() {
|
|
87
100
|
const args = process.argv.slice(2);
|
|
88
101
|
|
|
89
102
|
if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
|
|
@@ -99,20 +112,15 @@ function main() {
|
|
|
99
112
|
if (args.includes('init') || args.includes('setup')) {
|
|
100
113
|
console.log(banner);
|
|
101
114
|
console.log('š Setting up FRAIM in current repository...\n');
|
|
102
|
-
runSetup();
|
|
115
|
+
await runSetup();
|
|
103
116
|
return;
|
|
104
117
|
}
|
|
105
118
|
|
|
106
119
|
if (args.includes('wizard')) {
|
|
107
120
|
console.log(banner);
|
|
108
121
|
console.log('š® FRAIM Interactive Setup Wizard\n');
|
|
109
|
-
console.log('
|
|
110
|
-
|
|
111
|
-
console.log(' 2. AI agent setup (with tested rules)');
|
|
112
|
-
console.log(' 3. Workflow customization');
|
|
113
|
-
console.log(' 4. Team member onboarding\n');
|
|
114
|
-
console.log('š” Starting setup wizard...\n');
|
|
115
|
-
runSetup();
|
|
122
|
+
console.log('Starting interactive wizard...\n');
|
|
123
|
+
await runWizard();
|
|
116
124
|
return;
|
|
117
125
|
}
|
|
118
126
|
|
package/package.json
CHANGED
package/setup.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
|
+
const { execSync } = require('child_process');
|
|
6
|
+
const readline = require('readline');
|
|
5
7
|
|
|
6
8
|
// Colors for console output
|
|
7
9
|
const colors = {
|
|
@@ -40,6 +42,10 @@ function logHeader(message) {
|
|
|
40
42
|
log('ā'.repeat(message.length));
|
|
41
43
|
}
|
|
42
44
|
|
|
45
|
+
function logStep(message) {
|
|
46
|
+
log(`\n${colors.bright}${colors.magenta}${message}${colors.reset}`);
|
|
47
|
+
}
|
|
48
|
+
|
|
43
49
|
function ensureDirectory(dirPath) {
|
|
44
50
|
if (!fs.existsSync(dirPath)) {
|
|
45
51
|
fs.mkdirSync(dirPath, { recursive: true });
|
|
@@ -53,141 +59,73 @@ function writeFile(filePath, content) {
|
|
|
53
59
|
logSuccess(`Created file: ${filePath}`);
|
|
54
60
|
}
|
|
55
61
|
|
|
56
|
-
function
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
- **design.mdc** - Design phase rules
|
|
75
|
-
- **implement.mdc** - Implementation phase rules
|
|
76
|
-
- **test.mdc** - Testing phase rules
|
|
77
|
-
- **resolve.mdc** - Resolution phase rules
|
|
78
|
-
- **cursor-workflow.mdc** - Cursor-specific workflow rules
|
|
79
|
-
|
|
80
|
-
## Key Behavioral Requirements
|
|
81
|
-
- Always verify actions taken
|
|
82
|
-
- Never expect user verification
|
|
83
|
-
- Run tests to verify expected behavior
|
|
84
|
-
- Link work to issues with "Closes #<n>"
|
|
85
|
-
- Open Draft PRs early for review
|
|
86
|
-
|
|
87
|
-
## Project Structure Awareness
|
|
88
|
-
- Work in feature branches only
|
|
89
|
-
- Never push to master
|
|
90
|
-
- Use local file system for development
|
|
91
|
-
- Coordinate through GitHub issues and PRs
|
|
92
|
-
|
|
93
|
-
## Tool Usage Guidelines
|
|
94
|
-
- Use local file system for development work
|
|
95
|
-
- Use GitHub MCP for issue management
|
|
96
|
-
- Use local Git for version control
|
|
97
|
-
- Test locally before committing
|
|
98
|
-
|
|
99
|
-
## FRAIM Integration
|
|
100
|
-
- Follow the RIGOR methodology
|
|
101
|
-
- Maintain isolation between agents
|
|
102
|
-
- Use GitOps for coordination
|
|
103
|
-
- Enable observability through clear documentation
|
|
104
|
-
`;
|
|
62
|
+
function copyDirectory(src, dest) {
|
|
63
|
+
if (!fs.existsSync(dest)) {
|
|
64
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const items = fs.readdirSync(src);
|
|
68
|
+
for (const item of items) {
|
|
69
|
+
const srcPath = path.join(src, item);
|
|
70
|
+
const destPath = path.join(dest, item);
|
|
71
|
+
|
|
72
|
+
if (fs.statSync(srcPath).isDirectory()) {
|
|
73
|
+
copyDirectory(srcPath, destPath);
|
|
74
|
+
} else {
|
|
75
|
+
fs.copyFileSync(srcPath, destPath);
|
|
76
|
+
logSuccess(`Copied: ${destPath}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
105
80
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
- Open Draft PRs early for review
|
|
122
|
-
|
|
123
|
-
## Project Structure Awareness
|
|
124
|
-
- Work in feature branches only
|
|
125
|
-
- Never push to master
|
|
126
|
-
- Use local file system for development
|
|
127
|
-
- Coordinate through GitHub issues and PRs
|
|
128
|
-
|
|
129
|
-
## Tool Usage Guidelines
|
|
130
|
-
- Use local file system for development work
|
|
131
|
-
- Use GitHub MCP for issue management
|
|
132
|
-
- Use local Git for version control
|
|
133
|
-
- Test locally before committing
|
|
134
|
-
|
|
135
|
-
## Architecture and Optimization Principles
|
|
136
|
-
- Follow established patterns
|
|
137
|
-
- Optimize for performance and maintainability
|
|
138
|
-
- Document architectural decisions
|
|
139
|
-
- Consider scalability and security
|
|
140
|
-
|
|
141
|
-
## Your Role in FRAIM
|
|
142
|
-
- Provide technical expertise and optimization
|
|
143
|
-
- Maintain code quality and standards
|
|
144
|
-
- Ensure architectural consistency
|
|
145
|
-
- Support other agents with technical guidance
|
|
146
|
-
`;
|
|
81
|
+
function askQuestion(question, defaultValue = 'y') {
|
|
82
|
+
return new Promise((resolve) => {
|
|
83
|
+
const rl = readline.createInterface({
|
|
84
|
+
input: process.stdin,
|
|
85
|
+
output: process.stdout
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const defaultText = defaultValue ? ` (${defaultValue})` : '';
|
|
89
|
+
rl.question(`${question}${defaultText}: `, (answer) => {
|
|
90
|
+
rl.close();
|
|
91
|
+
const finalAnswer = answer.trim() || defaultValue;
|
|
92
|
+
resolve(finalAnswer.toLowerCase());
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
}
|
|
147
96
|
|
|
148
|
-
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
- Never expect user verification
|
|
163
|
-
- Run tests to verify expected behavior
|
|
164
|
-
- Link work to issues with "Closes #<n>"
|
|
165
|
-
- Open Draft PRs early for review
|
|
166
|
-
|
|
167
|
-
## Project Structure Awareness
|
|
168
|
-
- Work in feature branches only
|
|
169
|
-
- Never push to master
|
|
170
|
-
- Use local file system for development
|
|
171
|
-
- Coordinate through GitHub issues and PRs
|
|
172
|
-
|
|
173
|
-
## Tool Usage Guidelines
|
|
174
|
-
- Use local file system for development work
|
|
175
|
-
- Use GitHub MCP for issue management
|
|
176
|
-
- Use local Git for version control
|
|
177
|
-
- Test locally before committing
|
|
178
|
-
|
|
179
|
-
## FRAIM Integration
|
|
180
|
-
- Follow the RIGOR methodology
|
|
181
|
-
- Maintain isolation between agents
|
|
182
|
-
- Use GitOps for coordination
|
|
183
|
-
- Enable observability through clear documentation
|
|
184
|
-
`;
|
|
97
|
+
function createGitHubLabels() {
|
|
98
|
+
const labels = [
|
|
99
|
+
{ name: 'phase:design', color: '0e8a16', description: 'Design phase - RFC creation and review' },
|
|
100
|
+
{ name: 'phase:impl', color: '1d76db', description: 'Implementation phase - coding and testing' },
|
|
101
|
+
{ name: 'phase:tests', color: 'fef2c0', description: 'Testing phase - validation and QA' },
|
|
102
|
+
{ name: 'status:wip', color: 'fbca04', description: 'Work in progress' },
|
|
103
|
+
{ name: 'status:needs-review', color: 'd93f0b', description: 'Ready for review' },
|
|
104
|
+
{ name: 'status:complete', color: '0e8a16', description: 'Completed and approved' },
|
|
105
|
+
{ name: 'status:approved', color: '0e8a16', description: 'Approved and ready to merge' },
|
|
106
|
+
{ name: 'status:changes-requested', color: 'd93f0b', description: 'Changes requested in review' },
|
|
107
|
+
{ name: 'ai-agent:cursor', color: '5319e7', description: 'Assigned to Cursor AI agent' },
|
|
108
|
+
{ name: 'ai-agent:claude', color: 'c2e0c6', description: 'Assigned to Claude AI agent' },
|
|
109
|
+
{ name: 'ai-agent:windsurf', color: 'bfdadc', description: 'Assigned to Windsurf AI agent' }
|
|
110
|
+
];
|
|
185
111
|
|
|
186
|
-
|
|
187
|
-
writeFile('.windsurfrules', windsurfRules);
|
|
188
|
-
writeFile('CLAUDE.md', claudeRules);
|
|
112
|
+
logInfo('Creating GitHub labels...');
|
|
189
113
|
|
|
190
|
-
|
|
114
|
+
for (const label of labels) {
|
|
115
|
+
try {
|
|
116
|
+
const command = `gh label create "${label.name}" --color "${label.color}" --description "${label.description}"`;
|
|
117
|
+
execSync(command, { stdio: 'pipe' });
|
|
118
|
+
logSuccess(`Created label: ${label.name}`);
|
|
119
|
+
} catch (error) {
|
|
120
|
+
if (error.message.includes('already exists')) {
|
|
121
|
+
logInfo(`Label already exists: ${label.name}`);
|
|
122
|
+
} else {
|
|
123
|
+
logWarning(`Failed to create label ${label.name}: ${error.message}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
logSuccess('GitHub labels created');
|
|
191
129
|
}
|
|
192
130
|
|
|
193
131
|
function createGitHubWorkflows() {
|
|
@@ -285,76 +223,146 @@ jobs:
|
|
|
285
223
|
logSuccess('GitHub workflows created');
|
|
286
224
|
}
|
|
287
225
|
|
|
288
|
-
function
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
{ name: 'status:approved', color: '0e8a16', description: 'Approved and ready to merge' },
|
|
297
|
-
{ name: 'status:changes-requested', color: 'd93f0b', description: 'Changes requested in review' },
|
|
298
|
-
{ name: 'ai-agent:cursor', color: '5319e7', description: 'Assigned to Cursor AI agent' },
|
|
299
|
-
{ name: 'ai-agent:claude', color: 'c2e0c6', description: 'Assigned to Claude AI agent' },
|
|
300
|
-
{ name: 'ai-agent:windsurf', color: 'bfdadc', description: 'Assigned to Windsurf AI agent' }
|
|
301
|
-
];
|
|
226
|
+
function createAgentFolders() {
|
|
227
|
+
// Create .cursor folder at top level with all contents
|
|
228
|
+
if (fs.existsSync('agents/cursor')) {
|
|
229
|
+
copyDirectory('agents/cursor', '.cursor');
|
|
230
|
+
logSuccess('Created .cursor folder with all contents');
|
|
231
|
+
} else {
|
|
232
|
+
logWarning('agents/cursor directory not found, skipping .cursor creation');
|
|
233
|
+
}
|
|
302
234
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
235
|
+
// Create .windsurf folder at top level with all contents
|
|
236
|
+
if (fs.existsSync('agents/windsurf')) {
|
|
237
|
+
copyDirectory('agents/windsurf', '.windsurf');
|
|
238
|
+
logSuccess('Created .windsurf folder with all contents');
|
|
239
|
+
} else {
|
|
240
|
+
logWarning('agents/windsurf directory not found, skipping .windsurf creation');
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Create CLAUDE.md at top level
|
|
244
|
+
if (fs.existsSync('agents/claude/CLAUDE.md')) {
|
|
245
|
+
const claudeContent = fs.readFileSync('agents/claude/CLAUDE.md', 'utf8');
|
|
246
|
+
writeFile('CLAUDE.md', claudeContent);
|
|
247
|
+
logSuccess('Created CLAUDE.md at top level');
|
|
248
|
+
} else {
|
|
249
|
+
logWarning('agents/claude/CLAUDE.md not found, skipping CLAUDE.md creation');
|
|
250
|
+
}
|
|
309
251
|
}
|
|
310
252
|
|
|
311
|
-
function
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
253
|
+
async function runWizard() {
|
|
254
|
+
logHeader('š® FRAIM Interactive Setup Wizard');
|
|
255
|
+
log('Welcome to the FRAIM setup wizard! I\'ll guide you through each step.\n');
|
|
256
|
+
|
|
257
|
+
try {
|
|
258
|
+
// Check prerequisites
|
|
259
|
+
logStep('Step 1: Checking Prerequisites');
|
|
260
|
+
|
|
261
|
+
// Check if gh CLI is available
|
|
262
|
+
try {
|
|
263
|
+
execSync('gh --version', { stdio: 'pipe' });
|
|
264
|
+
logSuccess('GitHub CLI (gh) is available');
|
|
265
|
+
} catch (error) {
|
|
266
|
+
logError('GitHub CLI (gh) is not installed or not available');
|
|
267
|
+
logInfo('Please install GitHub CLI: https://cli.github.com/');
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Check if we're in a git repository
|
|
272
|
+
try {
|
|
273
|
+
execSync('git rev-parse --git-dir', { stdio: 'pipe' });
|
|
274
|
+
logSuccess('Running in a git repository');
|
|
275
|
+
} catch (error) {
|
|
276
|
+
logError('Not in a git repository');
|
|
277
|
+
logInfo('Please run this command from within a git repository');
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Step 2: AI Agent Setup
|
|
282
|
+
logStep('Step 2: AI Agent Configuration');
|
|
283
|
+
const setupAgents = await askQuestion('Would you like to set up AI agent configurations (.cursor, .windsurf, CLAUDE.md)?', 'y');
|
|
284
|
+
|
|
285
|
+
if (setupAgents === 'y' || setupAgents === 'yes') {
|
|
286
|
+
createAgentFolders();
|
|
287
|
+
} else {
|
|
288
|
+
logInfo('Skipping AI agent setup');
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Step 3: GitHub Workflows
|
|
292
|
+
logStep('Step 3: GitHub Workflows');
|
|
293
|
+
const setupWorkflows = await askQuestion('Would you like to set up GitHub workflows for automation?', 'y');
|
|
294
|
+
|
|
295
|
+
if (setupWorkflows === 'y' || setupWorkflows === 'yes') {
|
|
296
|
+
ensureDirectory('.github/workflows');
|
|
297
|
+
createGitHubWorkflows();
|
|
298
|
+
} else {
|
|
299
|
+
logInfo('Skipping GitHub workflow setup');
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Step 4: GitHub Labels
|
|
303
|
+
logStep('Step 4: GitHub Labels');
|
|
304
|
+
const setupLabels = await askQuestion('Would you like to create GitHub labels for FRAIM?', 'y');
|
|
305
|
+
|
|
306
|
+
if (setupLabels === 'y' || setupLabels === 'yes') {
|
|
307
|
+
createGitHubLabels();
|
|
308
|
+
} else {
|
|
309
|
+
logInfo('Skipping GitHub label setup');
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Step 5: Summary
|
|
313
|
+
logStep('Step 5: Setup Summary');
|
|
314
|
+
logHeader('š Setup Complete!');
|
|
315
|
+
logSuccess('FRAIM has been successfully set up in your repository!');
|
|
316
|
+
logInfo('Next steps:');
|
|
317
|
+
logInfo('1. Commit and push these files to GitHub');
|
|
318
|
+
logInfo('2. Create your first issue with phase labels');
|
|
319
|
+
logInfo('3. Start coordinating your AI agents!');
|
|
320
|
+
|
|
321
|
+
logInfo('\nš Learn more about FRAIM:');
|
|
322
|
+
logInfo('https://github.com/mathursrus/Ashley-Calendar-AI/tree/master/FRAIM');
|
|
323
|
+
|
|
324
|
+
logInfo('\nš§ Learn the RIGOR methodology:');
|
|
325
|
+
logInfo('npx fraim-framework rigor');
|
|
326
|
+
|
|
327
|
+
} catch (error) {
|
|
328
|
+
logError(`Wizard failed: ${error.message}`);
|
|
329
|
+
process.exit(1);
|
|
330
|
+
}
|
|
337
331
|
}
|
|
338
332
|
|
|
339
333
|
function runSetup() {
|
|
340
|
-
logHeader('š FRAIM Setup
|
|
334
|
+
logHeader('š FRAIM Quick Setup');
|
|
341
335
|
log('Setting up FRAIM in current repository...\n');
|
|
342
336
|
|
|
343
337
|
try {
|
|
344
|
-
//
|
|
338
|
+
// Check prerequisites
|
|
339
|
+
try {
|
|
340
|
+
execSync('gh --version', { stdio: 'pipe' });
|
|
341
|
+
} catch (error) {
|
|
342
|
+
logError('GitHub CLI (gh) is not installed or not available');
|
|
343
|
+
logInfo('Please install GitHub CLI: https://cli.github.com/');
|
|
344
|
+
process.exit(1);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
try {
|
|
348
|
+
execSync('git rev-parse --git-dir', { stdio: 'pipe' });
|
|
349
|
+
} catch (error) {
|
|
350
|
+
logError('Not in a git repository');
|
|
351
|
+
logInfo('Please run this command from within a git repository');
|
|
352
|
+
process.exit(1);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Create everything at once
|
|
345
356
|
ensureDirectory('.github/workflows');
|
|
346
|
-
|
|
347
|
-
// Create all components
|
|
348
|
-
createAgentStructure();
|
|
357
|
+
createAgentFolders();
|
|
349
358
|
createGitHubWorkflows();
|
|
350
359
|
createGitHubLabels();
|
|
351
|
-
createFRAIMConfig();
|
|
352
360
|
|
|
353
361
|
logHeader('š Setup Complete!');
|
|
354
362
|
logSuccess('FRAIM has been successfully set up in your repository!');
|
|
355
363
|
logInfo('Next steps:');
|
|
356
364
|
logInfo('1. Commit and push these files to GitHub');
|
|
357
|
-
logInfo('2.
|
|
365
|
+
logInfo('2. The GitHub labels have been created automatically');
|
|
358
366
|
logInfo('3. Create your first issue with phase labels');
|
|
359
367
|
logInfo('4. Start coordinating your AI agents!');
|
|
360
368
|
|
|
@@ -375,4 +383,4 @@ if (require.main === module) {
|
|
|
375
383
|
runSetup();
|
|
376
384
|
}
|
|
377
385
|
|
|
378
|
-
module.exports = { runSetup };
|
|
386
|
+
module.exports = { runSetup, runWizard };
|