aiwg
Version:
Deployment tool and support utility for AI context. Copies agents, skills, commands, rules, and behaviors into the paths each AI platform reads (Claude Code, Codex, Copilot, Cursor, Warp, OpenClaw, and 6 more) so one source of truth works across 10 platfo
189 lines • 6.95 kB
JavaScript
/**
* WorkspaceCreator - Create framework-scoped workspaces
*
* Creates framework-specific directories and shared resources for
* multi-framework projects. Supports Claude, Codex, and Cursor frameworks.
*
* FID-007 Framework-Scoped Workspaces creation logic.
*
* @module src/plugin/workspace-creator
* @version 1.0.0
* @since 2025-10-23
*/
import * as fs from 'fs/promises';
import * as path from 'path';
// ===========================
// WorkspaceCreator Class
// ===========================
export class WorkspaceCreator {
projectRoot;
SUPPORTED_FRAMEWORKS = ['claude', 'codex', 'cursor'];
SHARED_DIRS = [
'intake',
'requirements',
'architecture',
'planning',
'testing',
'deployment',
'security',
'quality',
'risks',
'reports',
'working',
'handoffs',
'gates',
'decisions',
'team',
'management'
];
constructor(projectRoot) {
this.projectRoot = path.resolve(projectRoot);
}
/**
* Create framework-specific workspace
*
* @param framework - Framework name (claude, codex, cursor)
* @param options - Creation options
*/
async createFrameworkWorkspace(framework, options = {}) {
if (!this.SUPPORTED_FRAMEWORKS.includes(framework)) {
throw new Error(`Unsupported framework: ${framework}`);
}
const frameworkPath = path.join(this.projectRoot, '.aiwg', framework);
const sharedPath = path.join(this.projectRoot, '.aiwg', 'shared');
// Create framework directory structure
await fs.mkdir(frameworkPath, { recursive: true });
await fs.mkdir(path.join(frameworkPath, 'agents'), { recursive: true });
await fs.mkdir(path.join(frameworkPath, 'commands'), { recursive: true });
await fs.mkdir(path.join(frameworkPath, 'memory'), { recursive: true });
await fs.mkdir(path.join(frameworkPath, 'context'), { recursive: true });
// Create shared directory structure
await fs.mkdir(sharedPath, { recursive: true });
for (const dir of this.SHARED_DIRS) {
await fs.mkdir(path.join(sharedPath, dir), { recursive: true });
}
// Create default config file
const configPath = path.join(frameworkPath, 'settings.json');
try {
await fs.access(configPath);
// Config already exists, don't overwrite
}
catch {
await fs.writeFile(configPath, JSON.stringify({
framework,
version: options.version || '1.0.0',
created: new Date().toISOString()
}, null, 2));
}
// Create README
const readmePath = path.join(frameworkPath, 'README.md');
try {
await fs.access(readmePath);
}
catch {
await fs.writeFile(readmePath, `# ${framework.charAt(0).toUpperCase() + framework.slice(1)} Framework Workspace\n\nFramework-specific configuration and resources.\n`);
}
// Create .gitignore
const gitignorePath = path.join(frameworkPath, '.gitignore');
try {
await fs.access(gitignorePath);
}
catch {
await fs.writeFile(gitignorePath, '*.log\nmemory/\n*.tmp\n');
}
}
/**
* Add framework to existing project
*
* @param framework - Framework name to add
*/
async addFrameworkToProject(framework) {
// Create workspace for new framework
await this.createFrameworkWorkspace(framework);
// Update workspace registry
const registryPath = path.join(this.projectRoot, '.aiwg', 'registry.json');
let registry = { frameworks: [] };
try {
const content = await fs.readFile(registryPath, 'utf-8');
registry = JSON.parse(content);
}
catch {
// Registry doesn't exist yet
}
if (!registry.frameworks.includes(framework)) {
registry.frameworks.push(framework);
await fs.writeFile(registryPath, JSON.stringify(registry, null, 2));
}
// Update workspace.json
const workspacePath = path.join(this.projectRoot, '.aiwg', 'workspace.json');
try {
const content = await fs.readFile(workspacePath, 'utf-8');
const workspace = JSON.parse(content);
if (!workspace.frameworks) {
workspace.frameworks = [];
}
if (!workspace.frameworks.includes(framework)) {
workspace.frameworks.push(framework);
await fs.writeFile(workspacePath, JSON.stringify(workspace, null, 2));
}
}
catch {
// workspace.json doesn't exist
}
}
/**
* Initialize empty workspace structure
*
* @param options - Initialization options
*/
async initializeWorkspace(options = {}) {
const aiwgPath = path.join(this.projectRoot, '.aiwg');
// Create .aiwg directory
await fs.mkdir(aiwgPath, { recursive: true });
// Create shared directory with SDLC subdirs
const sharedPath = path.join(aiwgPath, 'shared');
await fs.mkdir(sharedPath, { recursive: true });
for (const dir of this.SHARED_DIRS) {
await fs.mkdir(path.join(sharedPath, dir), { recursive: true });
}
// Create workspace.json
const workspacePath = path.join(aiwgPath, 'workspace.json');
try {
await fs.access(workspacePath);
// Already exists, don't overwrite
}
catch {
await fs.writeFile(workspacePath, JSON.stringify({
version: '1.0.0',
frameworks: [],
created: new Date().toISOString()
}, null, 2));
}
// Create .gitignore
const gitignorePath = path.join(aiwgPath, '.gitignore');
try {
await fs.access(gitignorePath);
}
catch {
await fs.writeFile(gitignorePath, '*.log\nworking/\n*.tmp\n');
}
// Create README
const readmePath = path.join(aiwgPath, 'README.md');
try {
await fs.access(readmePath);
}
catch {
await fs.writeFile(readmePath, '# AIWG Workspace\n\nFramework-scoped workspace for AIWG.\n');
}
// Auto-detect and create framework workspaces if requested
if (options.autoDetect) {
const { FrameworkDetector } = await import('./framework-detector.js');
const detector = new FrameworkDetector(this.projectRoot);
const frameworks = await detector.detectFrameworks();
for (const framework of frameworks) {
await this.createFrameworkWorkspace(framework);
}
}
}
}
//# sourceMappingURL=workspace-creator.js.map