@alxyrgin/agent-forge 3.0.0 → 3.2.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/README.md +353 -118
- package/dist/index.js +262 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/config/linear-mapping.json.ejs +27 -0
- package/templates/root/CLAUDE.md.ejs +2 -0
- package/templates/rules/linear-sync.md.ejs +65 -0
- package/templates/skills/core/complete-task/SKILL.md.ejs +17 -0
- package/templates/skills/core/done/SKILL.md.ejs +18 -0
- package/templates/skills/core/end-session/SKILL.md.ejs +18 -0
- package/templates/skills/core/plan/SKILL.md.ejs +9 -0
- package/templates/skills/core/take-task/SKILL.md.ejs +9 -0
- package/templates/skills/extra/decompose/SKILL.md.ejs +9 -0
- package/templates/skills/extra/sync-linear/SKILL.md.ejs +87 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/prompts/project-setup.ts","../src/generators/memory-bank.ts","../src/utils/template.ts","../src/utils/fs.ts","../src/generators/agents.ts","../src/generators/skills.ts","../src/generators/rules.ts","../src/generators/claude-md.ts","../src/generators/infra.ts","../src/generators/hooks.ts","../src/generators/index.ts","../src/commands/doctor.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { initCommand } from './commands/init.js';\nimport { doctorCommand } from './commands/doctor.js';\n\nconst program = new Command();\n\nprogram\n .name('agent-forge')\n .description('AI-driven Development Framework for Claude Code')\n .version('3.0.0');\n\nprogram\n .command('init')\n .description('Initialize AI-driven development infrastructure in the current project')\n .option('-y, --yes', 'Skip prompts and use defaults')\n .option('--overwrite', 'Overwrite existing files')\n .action(initCommand);\n\nprogram\n .command('doctor')\n .description('Check integrity of the generated structure')\n .action(doctorCommand);\n\nprogram.parse();\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { promptProjectSetup, getDefaultContext } from '../prompts/project-setup.js';\nimport { generateAll } from '../generators/index.js';\n\ninterface InitOptions {\n yes?: boolean;\n overwrite?: boolean;\n}\n\nexport async function initCommand(options: InitOptions): Promise<void> {\n const targetDir = process.cwd();\n\n console.log();\n console.log(chalk.bold(' agent-forge v3.0.0'));\n console.log(chalk.dim(' AI-driven Development Framework for Claude Code'));\n console.log();\n\n let ctx;\n if (options.yes) {\n ctx = getDefaultContext(targetDir);\n console.log(chalk.dim(' Using default configuration (--yes)'));\n console.log();\n } else {\n ctx = await promptProjectSetup(targetDir);\n console.log();\n }\n\n const spinner = ora('Creating project structure...').start();\n\n try {\n const result = await generateAll(ctx, options.overwrite ?? false);\n\n spinner.succeed(\n chalk.green(`${result.filesCreated.length} files created`)\n );\n\n if (result.filesSkipped.length > 0) {\n console.log(\n chalk.yellow(` ${result.filesSkipped.length} files skipped (already exist)`)\n );\n }\n\n if (result.errors.length > 0) {\n console.log(chalk.red(` ${result.errors.length} errors:`));\n for (const err of result.errors) {\n console.log(chalk.red(` - ${err}`));\n }\n }\n\n console.log();\n console.log(chalk.bold(' Next steps:'));\n console.log(chalk.dim(' 1. Open Claude Code in this directory'));\n console.log(chalk.dim(' 2. /start-session — begin your first session'));\n console.log(chalk.dim(' 3. /plan init — create tasks from your documentation'));\n console.log();\n } catch (err) {\n spinner.fail(chalk.red('Failed to create project structure'));\n console.error(err);\n process.exit(1);\n }\n}\n","import inquirer from 'inquirer';\nimport type { ProjectContext, TeamMember, Milestone, AgentPreset, Language, CommitStyle } from '../types.js';\n\nfunction today(): string {\n return new Date().toISOString().split('T')[0];\n}\n\nconst STACK_CHOICES = [\n { name: 'Python', value: 'python' },\n { name: 'TypeScript / Node.js', value: 'typescript' },\n { name: 'Go', value: 'go' },\n { name: 'Rust', value: 'rust' },\n { name: 'Other', value: 'other' },\n];\n\nconst FRAMEWORK_MAP: Record<string, string[]> = {\n python: ['FastAPI', 'Django', 'Flask', 'None'],\n typescript: ['Next.js', 'Express', 'Fastify', 'None'],\n go: ['Gin', 'Echo', 'Chi', 'None'],\n rust: ['Actix', 'Axum', 'Rocket', 'None'],\n other: ['None'],\n};\n\nconst TEST_MAP: Record<string, { framework: string; command: string }> = {\n python: { framework: 'pytest', command: 'pytest' },\n typescript: { framework: 'vitest', command: 'npx vitest run' },\n go: { framework: 'go test', command: 'go test ./...' },\n rust: { framework: 'cargo test', command: 'cargo test' },\n other: { framework: 'custom', command: 'echo \"no tests configured\"' },\n};\n\nexport async function promptProjectSetup(targetDir: string): Promise<ProjectContext> {\n const base = await inquirer.prompt([\n {\n type: 'input',\n name: 'projectName',\n message: 'Project name:',\n default: targetDir.split('/').pop(),\n },\n {\n type: 'input',\n name: 'projectDescription',\n message: 'Project description:',\n default: 'AI-driven project',\n },\n {\n type: 'list',\n name: 'stack',\n message: 'Technology stack:',\n choices: STACK_CHOICES,\n },\n ]);\n\n const frameworks = FRAMEWORK_MAP[base.stack] || ['None'];\n const frameworkAnswer = await inquirer.prompt([\n {\n type: 'list',\n name: 'framework',\n message: 'Framework:',\n choices: frameworks,\n },\n ]);\n\n const testDefaults = TEST_MAP[base.stack] || TEST_MAP.other;\n const dirs = await inquirer.prompt([\n {\n type: 'input',\n name: 'testFramework',\n message: 'Test framework:',\n default: testDefaults.framework,\n },\n {\n type: 'input',\n name: 'testCommand',\n message: 'Test command:',\n default: testDefaults.command,\n },\n {\n type: 'input',\n name: 'srcDir',\n message: 'Source directory:',\n default: 'src/',\n },\n {\n type: 'input',\n name: 'testDir',\n message: 'Test directory:',\n default: base.stack === 'python' ? 'src/tests/' : 'tests/',\n },\n ]);\n\n // Team members\n const team: TeamMember[] = [];\n let addMore = true;\n let first = true;\n while (addMore) {\n const member = await inquirer.prompt([\n {\n type: 'input',\n name: 'name',\n message: first ? 'Team member name:' : 'Next team member name (leave empty to stop):',\n default: first ? undefined : '',\n },\n ]);\n\n if (!member.name) break;\n\n const details = await inquirer.prompt([\n {\n type: 'input',\n name: 'role',\n message: `${member.name}'s role:`,\n default: 'developer',\n },\n {\n type: 'input',\n name: 'email',\n message: `${member.name}'s email:`,\n },\n ]);\n\n team.push({ name: member.name, role: details.role, email: details.email });\n first = false;\n\n if (team.length >= 10) break;\n const cont = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'addMore',\n message: 'Add another team member?',\n default: false,\n },\n ]);\n addMore = cont.addMore;\n }\n\n // Milestones\n const milestones: Milestone[] = [];\n const addMilestones = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'add',\n message: 'Add milestones?',\n default: false,\n },\n ]);\n\n if (addMilestones.add) {\n let addMoreMs = true;\n while (addMoreMs) {\n const ms = await inquirer.prompt([\n {\n type: 'input',\n name: 'name',\n message: 'Milestone name:',\n },\n {\n type: 'input',\n name: 'deadline',\n message: 'Deadline (YYYY-MM-DD):',\n },\n {\n type: 'input',\n name: 'description',\n message: 'Description (optional):',\n default: '',\n },\n ]);\n milestones.push({\n name: ms.name,\n deadline: ms.deadline,\n description: ms.description || undefined,\n });\n\n const cont = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'addMore',\n message: 'Add another milestone?',\n default: false,\n },\n ]);\n addMoreMs = cont.addMore;\n }\n }\n\n const config = await inquirer.prompt([\n {\n type: 'list',\n name: 'agentPreset',\n message: 'Agent preset:',\n choices: [\n { name: 'Core (8 agents — development pipeline)', value: 'core' },\n { name: 'Full (20 agents — all categories + extra skills)', value: 'full' },\n { name: 'Minimal (5 agents — essentials + inspector)', value: 'minimal' },\n ],\n },\n {\n type: 'list',\n name: 'language',\n message: 'Instructions language:',\n choices: [\n { name: 'Russian', value: 'ru' },\n { name: 'English', value: 'en' },\n ],\n },\n {\n type: 'list',\n name: 'commitStyle',\n message: 'Commit style:',\n choices: [\n { name: 'Standard (type(scope): description)', value: 'standard' },\n { name: 'Conventional Commits', value: 'conventional' },\n ],\n },\n ]);\n\n return {\n projectName: base.projectName,\n projectDescription: base.projectDescription,\n stack: base.stack,\n framework: frameworkAnswer.framework,\n testFramework: dirs.testFramework,\n testCommand: dirs.testCommand,\n srcDir: dirs.srcDir,\n testDir: dirs.testDir,\n team,\n milestones,\n agentPreset: config.agentPreset as AgentPreset,\n language: config.language as Language,\n commitStyle: config.commitStyle as CommitStyle,\n today: today(),\n targetDir,\n };\n}\n\nexport function getDefaultContext(targetDir: string): ProjectContext {\n return {\n projectName: targetDir.split('/').pop() || 'my-project',\n projectDescription: 'AI-driven project',\n stack: 'typescript',\n framework: 'None',\n testFramework: 'vitest',\n testCommand: 'npx vitest run',\n srcDir: 'src/',\n testDir: 'tests/',\n team: [{ name: 'Developer', role: 'developer', email: '' }],\n milestones: [],\n agentPreset: 'core',\n language: 'en',\n commitStyle: 'standard',\n today: today(),\n targetDir,\n };\n}\n","import path from 'path';\nimport type { ProjectContext, GeneratorResult } from '../types.js';\nimport { renderTemplate } from '../utils/template.js';\nimport { writeFileSafe } from '../utils/fs.js';\n\nconst MEMORY_FILES = [\n 'active-context.md',\n 'progress.md',\n 'project-brief.md',\n 'decisions.md',\n 'tech-stack.md',\n 'tech-debt.md',\n 'patterns.md',\n 'troubleshooting.md',\n 'checkpoint.yml',\n];\n\nexport async function generateMemoryBank(\n ctx: ProjectContext,\n overwrite: boolean\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n filesCreated: [],\n filesSkipped: [],\n errors: [],\n };\n\n const templateData = {\n ...ctx,\n defaultBranch: 'main',\n };\n\n for (const file of MEMORY_FILES) {\n try {\n const content = await renderTemplate(`memory/${file}.ejs`, templateData);\n const outputPath = path.join(ctx.targetDir, 'dev-infra/memory', file);\n const status = await writeFileSafe(outputPath, content, overwrite);\n\n if (status === 'skipped') {\n result.filesSkipped.push(outputPath);\n } else {\n result.filesCreated.push(outputPath);\n }\n } catch (err) {\n result.errors.push(`Memory ${file}: ${err}`);\n }\n }\n\n return result;\n}\n","import ejs from 'ejs';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { readFile } from './fs.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// In dev: src/utils/template.ts -> ../../templates\n// In dist: dist/index.mjs -> ../templates\n// We try ../templates first (dist), then ../../templates (dev/test)\nimport fs from 'fs';\nconst distPath = path.resolve(__dirname, '../templates');\nconst devPath = path.resolve(__dirname, '../../templates');\nconst TEMPLATES_DIR = fs.existsSync(distPath) ? distPath : devPath;\n\nexport function getTemplatesDir(): string {\n return TEMPLATES_DIR;\n}\n\nexport async function renderTemplate(\n templatePath: string,\n data: Record<string, unknown>\n): Promise<string> {\n const fullPath = path.join(TEMPLATES_DIR, templatePath);\n const template = await readFile(fullPath);\n return ejs.render(template, data, {\n filename: fullPath,\n async: false,\n });\n}\n\nexport function renderString(\n template: string,\n data: Record<string, unknown>\n): string {\n return ejs.render(template, data);\n}\n","import fs from 'fs-extra';\nimport path from 'path';\n\nexport async function ensureDir(dirPath: string): Promise<void> {\n await fs.ensureDir(dirPath);\n}\n\nexport async function writeFileSafe(\n filePath: string,\n content: string,\n overwrite: boolean = false\n): Promise<'created' | 'skipped' | 'overwritten'> {\n const dir = path.dirname(filePath);\n await fs.ensureDir(dir);\n\n if (await fs.pathExists(filePath)) {\n if (!overwrite) {\n return 'skipped';\n }\n await fs.writeFile(filePath, content, 'utf-8');\n return 'overwritten';\n }\n\n await fs.writeFile(filePath, content, 'utf-8');\n return 'created';\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n return fs.pathExists(filePath);\n}\n\nexport async function readFile(filePath: string): Promise<string> {\n return fs.readFile(filePath, 'utf-8');\n}\n\nexport async function makeExecutable(filePath: string): Promise<void> {\n await fs.chmod(filePath, 0o755);\n}\n","import path from 'path';\nimport type { ProjectContext, GeneratorResult, AgentPreset } from '../types.js';\nimport { renderTemplate } from '../utils/template.js';\nimport { writeFileSafe } from '../utils/fs.js';\n\n// --- Agent categories ---\n\nconst PIPELINE_AGENTS = [\n 'analyst',\n 'architect',\n 'skeptic',\n 'developer',\n 'tester',\n 'inspector',\n 'reviewer',\n 'planner',\n];\n\nconst PLANNING_AGENTS = [\n 'researcher',\n 'validator',\n 'interviewer',\n 'decomposer',\n];\n\nconst SECURITY_AGENTS = [\n 'auditor',\n 'prompter',\n 'deployer',\n 'scaffolder',\n];\n\nconst DOCUMENTATION_AGENTS = [\n 'librarian',\n 'writer',\n 'gatekeeper',\n 'verifier',\n];\n\n// --- Presets ---\n\nconst MINIMAL_AGENTS = [\n 'analyst',\n 'developer',\n 'tester',\n 'reviewer',\n 'inspector',\n];\n\nconst CORE_AGENTS = [...PIPELINE_AGENTS];\n\nconst FULL_AGENTS = [\n ...PIPELINE_AGENTS,\n ...PLANNING_AGENTS,\n ...SECURITY_AGENTS,\n ...DOCUMENTATION_AGENTS,\n];\n\n// --- Helpers ---\n\nconst CATEGORY_MAP: Record<string, string> = {};\n\nfor (const name of PIPELINE_AGENTS) {\n CATEGORY_MAP[name] = 'pipeline';\n}\nfor (const name of PLANNING_AGENTS) {\n CATEGORY_MAP[name] = 'planning';\n}\nfor (const name of SECURITY_AGENTS) {\n CATEGORY_MAP[name] = 'security';\n}\nfor (const name of DOCUMENTATION_AGENTS) {\n CATEGORY_MAP[name] = 'documentation';\n}\n\n/**\n * Returns the template subdirectory for a given agent name.\n * Templates live at templates/agents/[category]/[name].md.ejs\n */\nexport function getAgentCategory(name: string): string {\n return CATEGORY_MAP[name] || 'pipeline';\n}\n\n/**\n * Returns the list of agents for the given preset.\n */\nexport function getAgentList(preset: AgentPreset): { name: string; category: string }[] {\n let names: string[];\n\n switch (preset) {\n case 'minimal':\n names = MINIMAL_AGENTS;\n break;\n case 'full':\n names = FULL_AGENTS;\n break;\n case 'core':\n default:\n names = CORE_AGENTS;\n break;\n }\n\n return names.map((name) => ({\n name,\n category: getAgentCategory(name),\n }));\n}\n\nexport async function generateAgents(\n ctx: ProjectContext,\n overwrite: boolean\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n filesCreated: [],\n filesSkipped: [],\n errors: [],\n };\n\n const agents = getAgentList(ctx.agentPreset);\n const templateData = {\n ...ctx,\n defaultBranch: 'main',\n };\n\n for (const agent of agents) {\n try {\n const content = await renderTemplate(\n `agents/${agent.category}/${agent.name}.md.ejs`,\n templateData\n );\n // Output is always flat: .claude/agents/[name].md\n const outputPath = path.join(ctx.targetDir, '.claude/agents', `${agent.name}.md`);\n const status = await writeFileSafe(outputPath, content, overwrite);\n\n if (status === 'skipped') {\n result.filesSkipped.push(outputPath);\n } else {\n result.filesCreated.push(outputPath);\n }\n } catch (err) {\n result.errors.push(`Agent ${agent.name}: ${err}`);\n }\n }\n\n return result;\n}\n","import path from 'path';\nimport type { ProjectContext, GeneratorResult, AgentPreset } from '../types.js';\nimport { renderTemplate } from '../utils/template.js';\nimport { writeFileSafe } from '../utils/fs.js';\n\nconst CORE_SKILLS = [\n 'start-session',\n 'end-session',\n 'take-task',\n 'complete-task',\n 'status',\n 'plan',\n 'review',\n 'code',\n 'test',\n 'done',\n];\n\nconst EXTRA_SKILLS = [\n 'interview',\n 'audit-wave',\n 'write-report',\n 'dashboard',\n 'skill-master',\n 'decompose',\n 'feature',\n 'security',\n 'spec',\n 'techspec',\n 'prompts',\n];\n\nfunction getSkillList(preset: AgentPreset): { name: string; dir: string }[] {\n const skills: { name: string; dir: string }[] = [];\n\n for (const name of CORE_SKILLS) {\n skills.push({ name, dir: 'core' });\n }\n\n if (preset === 'full') {\n for (const name of EXTRA_SKILLS) {\n skills.push({ name, dir: 'extra' });\n }\n }\n\n return skills;\n}\n\nexport async function generateSkills(\n ctx: ProjectContext,\n overwrite: boolean\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n filesCreated: [],\n filesSkipped: [],\n errors: [],\n };\n\n const templateData = {\n ...ctx,\n defaultBranch: 'main',\n };\n\n const skills = getSkillList(ctx.agentPreset);\n\n for (const skill of skills) {\n try {\n const content = await renderTemplate(\n `skills/${skill.dir}/${skill.name}/SKILL.md.ejs`,\n templateData\n );\n const outputPath = path.join(ctx.targetDir, `.claude/skills/${skill.name}`, 'SKILL.md');\n const status = await writeFileSafe(outputPath, content, overwrite);\n\n if (status === 'skipped') {\n result.filesSkipped.push(outputPath);\n } else {\n result.filesCreated.push(outputPath);\n }\n } catch (err) {\n result.errors.push(`Skill ${skill.name}: ${err}`);\n }\n }\n\n return result;\n}\n","import path from 'path';\nimport type { ProjectContext, GeneratorResult } from '../types.js';\nimport { renderTemplate } from '../utils/template.js';\nimport { writeFileSafe } from '../utils/fs.js';\n\nconst RULES = [\n 'commit-conventions',\n 'development-cycle',\n 'testing-standards',\n 'shared-resources',\n 'context-loading',\n 'agent-output-format',\n 'quality-gates',\n 'rollback-protocol',\n];\n\nexport async function generateRules(\n ctx: ProjectContext,\n overwrite: boolean\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n filesCreated: [],\n filesSkipped: [],\n errors: [],\n };\n\n const templateData = {\n ...ctx,\n defaultBranch: 'main',\n };\n\n for (const rule of RULES) {\n try {\n const content = await renderTemplate(`rules/${rule}.md.ejs`, templateData);\n const outputPath = path.join(ctx.targetDir, '.claude/rules', `${rule}.md`);\n const status = await writeFileSafe(outputPath, content, overwrite);\n\n if (status === 'skipped') {\n result.filesSkipped.push(outputPath);\n } else {\n result.filesCreated.push(outputPath);\n }\n } catch (err) {\n result.errors.push(`Rule ${rule}: ${err}`);\n }\n }\n\n return result;\n}\n","import path from 'path';\nimport type { ProjectContext, GeneratorResult } from '../types.js';\nimport { renderTemplate } from '../utils/template.js';\nimport { writeFileSafe } from '../utils/fs.js';\n\nexport async function generateClaudeMd(\n ctx: ProjectContext,\n overwrite: boolean\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n filesCreated: [],\n filesSkipped: [],\n errors: [],\n };\n\n const templateData = {\n ...ctx,\n defaultBranch: 'main',\n };\n\n // CLAUDE.md\n try {\n const content = await renderTemplate('root/CLAUDE.md.ejs', templateData);\n const outputPath = path.join(ctx.targetDir, '.claude/CLAUDE.md');\n const status = await writeFileSafe(outputPath, content, overwrite);\n\n if (status === 'skipped') {\n result.filesSkipped.push(outputPath);\n } else {\n result.filesCreated.push(outputPath);\n }\n } catch (err) {\n result.errors.push(`CLAUDE.md: ${err}`);\n }\n\n // settings.json\n try {\n const content = await renderTemplate('root/settings.json.ejs', templateData);\n const outputPath = path.join(ctx.targetDir, '.claude/settings.json');\n const status = await writeFileSafe(outputPath, content, overwrite);\n\n if (status === 'skipped') {\n result.filesSkipped.push(outputPath);\n } else {\n result.filesCreated.push(outputPath);\n }\n } catch (err) {\n result.errors.push(`settings.json: ${err}`);\n }\n\n return result;\n}\n","import path from 'path';\nimport type { ProjectContext, GeneratorResult } from '../types.js';\nimport { renderTemplate } from '../utils/template.js';\nimport { writeFileSafe, ensureDir } from '../utils/fs.js';\n\nexport async function generateInfra(\n ctx: ProjectContext,\n overwrite: boolean\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n filesCreated: [],\n filesSkipped: [],\n errors: [],\n };\n\n const templateData = {\n ...ctx,\n defaultBranch: 'main',\n };\n\n // tasks.json\n try {\n const content = await renderTemplate('tasks/tasks.json.ejs', templateData);\n const outputPath = path.join(ctx.targetDir, 'dev-infra/tasks/tasks.json');\n const status = await writeFileSafe(outputPath, content, overwrite);\n\n if (status === 'skipped') {\n result.filesSkipped.push(outputPath);\n } else {\n result.filesCreated.push(outputPath);\n }\n } catch (err) {\n result.errors.push(`tasks.json: ${err}`);\n }\n\n // Create empty directories with .gitkeep\n const dirs = [\n 'dev-infra/sessions',\n 'dev-infra/tests/acceptance',\n 'dev-infra/tests/pmi',\n 'dev-infra/tests/results',\n ];\n\n for (const dir of dirs) {\n try {\n const dirPath = path.join(ctx.targetDir, dir);\n await ensureDir(dirPath);\n const gitkeepPath = path.join(dirPath, '.gitkeep');\n const status = await writeFileSafe(gitkeepPath, '', overwrite);\n\n if (status === 'skipped') {\n result.filesSkipped.push(gitkeepPath);\n } else {\n result.filesCreated.push(gitkeepPath);\n }\n } catch (err) {\n result.errors.push(`Dir ${dir}: ${err}`);\n }\n }\n\n // .claude-forge.json — manifest for doctor command\n try {\n const manifest = {\n version: '3.0.0',\n createdAt: ctx.today,\n projectName: ctx.projectName,\n agentPreset: ctx.agentPreset,\n language: ctx.language,\n expectedFiles: getExpectedFiles(ctx),\n };\n const outputPath = path.join(ctx.targetDir, '.claude-forge.json');\n const status = await writeFileSafe(\n outputPath,\n JSON.stringify(manifest, null, 2) + '\\n',\n overwrite\n );\n\n if (status === 'skipped') {\n result.filesSkipped.push(outputPath);\n } else {\n result.filesCreated.push(outputPath);\n }\n } catch (err) {\n result.errors.push(`.claude-forge.json: ${err}`);\n }\n\n return result;\n}\n\nfunction getExpectedFiles(ctx: ProjectContext): string[] {\n const files = [\n '.claude/CLAUDE.md',\n '.claude/settings.json',\n '.claude-forge.json',\n 'dev-infra/tasks/tasks.json',\n 'dev-infra/memory/active-context.md',\n 'dev-infra/memory/progress.md',\n 'dev-infra/memory/project-brief.md',\n 'dev-infra/memory/decisions.md',\n 'dev-infra/memory/tech-stack.md',\n 'dev-infra/memory/tech-debt.md',\n 'dev-infra/memory/patterns.md',\n 'dev-infra/memory/troubleshooting.md',\n 'dev-infra/memory/checkpoint.yml',\n ];\n\n // Hooks\n files.push('.claude/hooks/protect-docs.sh');\n\n // Rules (8 total)\n files.push(\n '.claude/rules/commit-conventions.md',\n '.claude/rules/development-cycle.md',\n '.claude/rules/testing-standards.md',\n '.claude/rules/shared-resources.md',\n '.claude/rules/context-loading.md',\n '.claude/rules/agent-output-format.md',\n '.claude/rules/quality-gates.md',\n '.claude/rules/rollback-protocol.md',\n );\n\n // Skills (10 core + 11 extra for full)\n const coreSkills = [\n 'start-session', 'end-session', 'take-task',\n 'complete-task', 'status', 'plan', 'review',\n 'code', 'test', 'done',\n ];\n const extraSkills = [\n 'interview', 'audit-wave', 'write-report', 'dashboard', 'skill-master',\n 'decompose', 'feature', 'security', 'spec', 'techspec', 'prompts',\n ];\n const skills = ctx.agentPreset === 'full'\n ? [...coreSkills, ...extraSkills]\n : coreSkills;\n for (const skill of skills) {\n files.push(`.claude/skills/${skill}/SKILL.md`);\n }\n\n // Agents depend on preset\n const pipelineAgents = [\n 'analyst', 'architect', 'skeptic', 'developer',\n 'tester', 'inspector', 'reviewer', 'planner',\n ];\n const planningAgents = ['researcher', 'validator', 'interviewer', 'decomposer'];\n const securityAgents = ['auditor', 'prompter', 'deployer', 'scaffolder'];\n const documentationAgents = ['librarian', 'writer', 'gatekeeper', 'verifier'];\n\n const minimalAgents = ['analyst', 'developer', 'tester', 'reviewer', 'inspector'];\n\n const coreAgents = [...pipelineAgents];\n const fullAgents = [\n ...pipelineAgents,\n ...planningAgents,\n ...securityAgents,\n ...documentationAgents,\n ];\n\n const agents = ctx.agentPreset === 'minimal'\n ? minimalAgents\n : ctx.agentPreset === 'full'\n ? fullAgents\n : coreAgents;\n\n for (const agent of agents) {\n files.push(`.claude/agents/${agent}.md`);\n }\n\n return files;\n}\n","import path from 'path';\nimport type { ProjectContext, GeneratorResult } from '../types.js';\nimport { renderTemplate } from '../utils/template.js';\nimport { writeFileSafe, makeExecutable } from '../utils/fs.js';\n\nexport async function generateHooks(\n ctx: ProjectContext,\n overwrite: boolean\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n filesCreated: [],\n filesSkipped: [],\n errors: [],\n };\n\n const templateData = {\n ...ctx,\n defaultBranch: 'main',\n };\n\n try {\n const content = await renderTemplate('hooks/protect-docs.sh.ejs', templateData);\n const outputPath = path.join(ctx.targetDir, '.claude/hooks/protect-docs.sh');\n const status = await writeFileSafe(outputPath, content, overwrite);\n\n if (status === 'skipped') {\n result.filesSkipped.push(outputPath);\n } else {\n result.filesCreated.push(outputPath);\n await makeExecutable(outputPath);\n }\n } catch (err) {\n result.errors.push(`Hook protect-docs.sh: ${err}`);\n }\n\n return result;\n}\n","import type { ProjectContext, GeneratorResult } from '../types.js';\nimport { generateMemoryBank } from './memory-bank.js';\nimport { generateAgents } from './agents.js';\nimport { generateSkills } from './skills.js';\nimport { generateRules } from './rules.js';\nimport { generateClaudeMd } from './claude-md.js';\nimport { generateInfra } from './infra.js';\nimport { generateHooks } from './hooks.js';\n\nexport async function generateAll(\n ctx: ProjectContext,\n overwrite: boolean = false\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n filesCreated: [],\n filesSkipped: [],\n errors: [],\n };\n\n const generators = [\n generateClaudeMd,\n generateAgents,\n generateSkills,\n generateRules,\n generateMemoryBank,\n generateHooks,\n generateInfra,\n ];\n\n for (const generator of generators) {\n try {\n const partial = await generator(ctx, overwrite);\n result.filesCreated.push(...partial.filesCreated);\n result.filesSkipped.push(...partial.filesSkipped);\n result.errors.push(...partial.errors);\n } catch (err) {\n result.errors.push(`Generator error: ${err}`);\n }\n }\n\n return result;\n}\n","import path from 'path';\nimport chalk from 'chalk';\nimport { fileExists, readFile } from '../utils/fs.js';\nimport type { DoctorCheck } from '../types.js';\n\nexport async function doctorCommand(): Promise<void> {\n const targetDir = process.cwd();\n\n console.log();\n console.log(chalk.bold(' agent-forge doctor'));\n console.log(chalk.dim(' Checking project structure integrity...'));\n console.log();\n\n // Load manifest\n const manifestPath = path.join(targetDir, '.claude-forge.json');\n const manifestExists = await fileExists(manifestPath);\n\n if (!manifestExists) {\n console.log(chalk.red(' .claude-forge.json not found'));\n console.log(chalk.dim(' Run `agent-forge init` first to initialize the project.'));\n console.log();\n process.exit(1);\n }\n\n const manifestRaw = await readFile(manifestPath);\n let manifest: { version: string; expectedFiles: string[]; projectName: string };\n\n try {\n manifest = JSON.parse(manifestRaw);\n } catch {\n console.log(chalk.red(' .claude-forge.json is corrupted'));\n process.exit(1);\n }\n\n console.log(chalk.dim(` Project: ${manifest.projectName}`));\n console.log(chalk.dim(` Version: ${manifest.version}`));\n console.log();\n\n const checks: DoctorCheck[] = [];\n let okCount = 0;\n let failCount = 0;\n\n for (const file of manifest.expectedFiles) {\n const filePath = path.join(targetDir, file);\n const exists = await fileExists(filePath);\n\n const check: DoctorCheck = {\n name: file,\n path: filePath,\n exists,\n ok: exists,\n };\n\n if (exists) {\n // Check if file is not empty\n try {\n const content = await readFile(filePath);\n if (content.trim().length === 0) {\n check.ok = false;\n check.message = 'File is empty';\n }\n } catch {\n check.ok = false;\n check.message = 'Cannot read file';\n }\n } else {\n check.message = 'File not found';\n }\n\n checks.push(check);\n if (check.ok) okCount++;\n else failCount++;\n }\n\n // Display results grouped by category\n const categories: Record<string, DoctorCheck[]> = {};\n for (const check of checks) {\n const category = check.name.startsWith('.claude/agents')\n ? 'Agents'\n : check.name.startsWith('.claude/skills')\n ? 'Skills'\n : check.name.startsWith('.claude/rules')\n ? 'Rules'\n : check.name.startsWith('.claude/')\n ? 'Claude Config'\n : check.name.startsWith('dev-infra/memory')\n ? 'Memory Bank'\n : check.name.startsWith('dev-infra/')\n ? 'Infrastructure'\n : 'Other';\n\n if (!categories[category]) categories[category] = [];\n categories[category].push(check);\n }\n\n for (const [category, items] of Object.entries(categories)) {\n const allOk = items.every(c => c.ok);\n const icon = allOk ? chalk.green('OK') : chalk.red('!!');\n console.log(` ${icon} ${chalk.bold(category)}`);\n\n for (const item of items) {\n if (item.ok) {\n console.log(chalk.green(` + ${item.name}`));\n } else {\n console.log(chalk.red(` - ${item.name} (${item.message})`));\n }\n }\n console.log();\n }\n\n // Summary\n console.log(chalk.bold(' Summary'));\n console.log(chalk.green(` OK: ${okCount}`));\n if (failCount > 0) {\n console.log(chalk.red(` Missing/broken: ${failCount}`));\n console.log();\n console.log(chalk.dim(' Run `agent-forge init --overwrite` to regenerate missing files.'));\n } else {\n console.log(chalk.green(' All checks passed!'));\n }\n console.log();\n\n if (failCount > 0) {\n process.exit(1);\n }\n}\n"],"mappings":"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","names":["path","path","fs","path","path","path","path","path","path","path","path","path","path","path","path","path","path","path","path","chalk","chalk","path"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/prompts/project-setup.ts","../src/generators/memory-bank.ts","../src/utils/template.ts","../src/utils/fs.ts","../src/generators/agents.ts","../src/generators/skills.ts","../src/generators/rules.ts","../src/generators/claude-md.ts","../src/utils/merge.ts","../src/generators/infra.ts","../src/generators/hooks.ts","../src/generators/index.ts","../src/commands/doctor.ts","../src/commands/update.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { initCommand } from './commands/init.js';\nimport { doctorCommand } from './commands/doctor.js';\nimport { updateCommand } from './commands/update.js';\n\nconst program = new Command();\n\nprogram\n .name('agent-forge')\n .description('AI-driven Development Framework for Claude Code')\n .version('3.2.0');\n\nprogram\n .command('init')\n .description('Initialize AI-driven development infrastructure in the current project')\n .option('-y, --yes', 'Skip prompts and use defaults')\n .option('--overwrite', 'Overwrite existing files')\n .action(initCommand);\n\nprogram\n .command('doctor')\n .description('Check integrity of the generated structure')\n .action(doctorCommand);\n\nprogram\n .command('update')\n .description('Update framework files to the latest version (preserves user data)')\n .action(updateCommand);\n\nprogram.parse();\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { promptProjectSetup, getDefaultContext } from '../prompts/project-setup.js';\nimport { generateAll } from '../generators/index.js';\n\ninterface InitOptions {\n yes?: boolean;\n overwrite?: boolean;\n}\n\nexport async function initCommand(options: InitOptions): Promise<void> {\n const targetDir = process.cwd();\n\n console.log();\n console.log(chalk.bold(' agent-forge v3.0.0'));\n console.log(chalk.dim(' AI-driven Development Framework for Claude Code'));\n console.log();\n\n let ctx;\n if (options.yes) {\n ctx = getDefaultContext(targetDir);\n console.log(chalk.dim(' Using default configuration (--yes)'));\n console.log();\n } else {\n ctx = await promptProjectSetup(targetDir);\n console.log();\n }\n\n const spinner = ora('Creating project structure...').start();\n\n try {\n const result = await generateAll(ctx, options.overwrite ?? false);\n\n spinner.succeed(\n chalk.green(`${result.filesCreated.length} files created`)\n );\n\n if (result.filesSkipped.length > 0) {\n console.log(\n chalk.yellow(` ${result.filesSkipped.length} files skipped (already exist)`)\n );\n }\n\n if (result.errors.length > 0) {\n console.log(chalk.red(` ${result.errors.length} errors:`));\n for (const err of result.errors) {\n console.log(chalk.red(` - ${err}`));\n }\n }\n\n console.log();\n console.log(chalk.bold(' Next steps:'));\n console.log(chalk.dim(' 1. Open Claude Code in this directory'));\n console.log(chalk.dim(' 2. /start-session — begin your first session'));\n console.log(chalk.dim(' 3. /plan init — create tasks from your documentation'));\n console.log();\n } catch (err) {\n spinner.fail(chalk.red('Failed to create project structure'));\n console.error(err);\n process.exit(1);\n }\n}\n","import inquirer from 'inquirer';\nimport type { ProjectContext, TeamMember, Milestone, AgentPreset, Language, CommitStyle } from '../types.js';\n\nfunction today(): string {\n return new Date().toISOString().split('T')[0];\n}\n\nconst STACK_CHOICES = [\n { name: 'Python', value: 'python' },\n { name: 'TypeScript / Node.js', value: 'typescript' },\n { name: 'Go', value: 'go' },\n { name: 'Rust', value: 'rust' },\n { name: 'Other', value: 'other' },\n];\n\nconst FRAMEWORK_MAP: Record<string, string[]> = {\n python: ['FastAPI', 'Django', 'Flask', 'None'],\n typescript: ['Next.js', 'Express', 'Fastify', 'None'],\n go: ['Gin', 'Echo', 'Chi', 'None'],\n rust: ['Actix', 'Axum', 'Rocket', 'None'],\n other: ['None'],\n};\n\nconst TEST_MAP: Record<string, { framework: string; command: string }> = {\n python: { framework: 'pytest', command: 'pytest' },\n typescript: { framework: 'vitest', command: 'npx vitest run' },\n go: { framework: 'go test', command: 'go test ./...' },\n rust: { framework: 'cargo test', command: 'cargo test' },\n other: { framework: 'custom', command: 'echo \"no tests configured\"' },\n};\n\nexport async function promptProjectSetup(targetDir: string): Promise<ProjectContext> {\n const base = await inquirer.prompt([\n {\n type: 'input',\n name: 'projectName',\n message: 'Project name:',\n default: targetDir.split('/').pop(),\n },\n {\n type: 'input',\n name: 'projectDescription',\n message: 'Project description:',\n default: 'AI-driven project',\n },\n {\n type: 'list',\n name: 'stack',\n message: 'Technology stack:',\n choices: STACK_CHOICES,\n },\n ]);\n\n const frameworks = FRAMEWORK_MAP[base.stack] || ['None'];\n const frameworkAnswer = await inquirer.prompt([\n {\n type: 'list',\n name: 'framework',\n message: 'Framework:',\n choices: frameworks,\n },\n ]);\n\n const testDefaults = TEST_MAP[base.stack] || TEST_MAP.other;\n const dirs = await inquirer.prompt([\n {\n type: 'input',\n name: 'testFramework',\n message: 'Test framework:',\n default: testDefaults.framework,\n },\n {\n type: 'input',\n name: 'testCommand',\n message: 'Test command:',\n default: testDefaults.command,\n },\n {\n type: 'input',\n name: 'srcDir',\n message: 'Source directory:',\n default: 'src/',\n },\n {\n type: 'input',\n name: 'testDir',\n message: 'Test directory:',\n default: base.stack === 'python' ? 'src/tests/' : 'tests/',\n },\n ]);\n\n // Team members\n const team: TeamMember[] = [];\n let addMore = true;\n let first = true;\n while (addMore) {\n const member = await inquirer.prompt([\n {\n type: 'input',\n name: 'name',\n message: first ? 'Team member name:' : 'Next team member name (leave empty to stop):',\n default: first ? undefined : '',\n },\n ]);\n\n if (!member.name) break;\n\n const details = await inquirer.prompt([\n {\n type: 'input',\n name: 'role',\n message: `${member.name}'s role:`,\n default: 'developer',\n },\n {\n type: 'input',\n name: 'email',\n message: `${member.name}'s email:`,\n },\n ]);\n\n team.push({ name: member.name, role: details.role, email: details.email });\n first = false;\n\n if (team.length >= 10) break;\n const cont = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'addMore',\n message: 'Add another team member?',\n default: false,\n },\n ]);\n addMore = cont.addMore;\n }\n\n // Milestones\n const milestones: Milestone[] = [];\n const addMilestones = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'add',\n message: 'Add milestones?',\n default: false,\n },\n ]);\n\n if (addMilestones.add) {\n let addMoreMs = true;\n while (addMoreMs) {\n const ms = await inquirer.prompt([\n {\n type: 'input',\n name: 'name',\n message: 'Milestone name:',\n },\n {\n type: 'input',\n name: 'deadline',\n message: 'Deadline (YYYY-MM-DD):',\n },\n {\n type: 'input',\n name: 'description',\n message: 'Description (optional):',\n default: '',\n },\n ]);\n milestones.push({\n name: ms.name,\n deadline: ms.deadline,\n description: ms.description || undefined,\n });\n\n const cont = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'addMore',\n message: 'Add another milestone?',\n default: false,\n },\n ]);\n addMoreMs = cont.addMore;\n }\n }\n\n const config = await inquirer.prompt([\n {\n type: 'list',\n name: 'agentPreset',\n message: 'Agent preset:',\n choices: [\n { name: 'Core (8 agents — development pipeline)', value: 'core' },\n { name: 'Full (20 agents — all categories + extra skills)', value: 'full' },\n { name: 'Minimal (5 agents — essentials + inspector)', value: 'minimal' },\n ],\n },\n {\n type: 'list',\n name: 'language',\n message: 'Instructions language:',\n choices: [\n { name: 'Russian', value: 'ru' },\n { name: 'English', value: 'en' },\n ],\n },\n {\n type: 'list',\n name: 'commitStyle',\n message: 'Commit style:',\n choices: [\n { name: 'Standard (type(scope): description)', value: 'standard' },\n { name: 'Conventional Commits', value: 'conventional' },\n ],\n },\n ]);\n\n return {\n projectName: base.projectName,\n projectDescription: base.projectDescription,\n stack: base.stack,\n framework: frameworkAnswer.framework,\n testFramework: dirs.testFramework,\n testCommand: dirs.testCommand,\n srcDir: dirs.srcDir,\n testDir: dirs.testDir,\n team,\n milestones,\n agentPreset: config.agentPreset as AgentPreset,\n language: config.language as Language,\n commitStyle: config.commitStyle as CommitStyle,\n today: today(),\n targetDir,\n };\n}\n\nexport function getDefaultContext(targetDir: string): ProjectContext {\n return {\n projectName: targetDir.split('/').pop() || 'my-project',\n projectDescription: 'AI-driven project',\n stack: 'typescript',\n framework: 'None',\n testFramework: 'vitest',\n testCommand: 'npx vitest run',\n srcDir: 'src/',\n testDir: 'tests/',\n team: [{ name: 'Developer', role: 'developer', email: '' }],\n milestones: [],\n agentPreset: 'core',\n language: 'en',\n commitStyle: 'standard',\n today: today(),\n targetDir,\n };\n}\n","import path from 'path';\nimport type { ProjectContext, GeneratorResult } from '../types.js';\nimport { renderTemplate } from '../utils/template.js';\nimport { writeFileSafe } from '../utils/fs.js';\n\nconst MEMORY_FILES = [\n 'active-context.md',\n 'progress.md',\n 'project-brief.md',\n 'decisions.md',\n 'tech-stack.md',\n 'tech-debt.md',\n 'patterns.md',\n 'troubleshooting.md',\n 'checkpoint.yml',\n];\n\nexport async function generateMemoryBank(\n ctx: ProjectContext,\n overwrite: boolean\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n filesCreated: [],\n filesSkipped: [],\n errors: [],\n };\n\n const templateData = {\n ...ctx,\n defaultBranch: 'main',\n };\n\n for (const file of MEMORY_FILES) {\n try {\n const content = await renderTemplate(`memory/${file}.ejs`, templateData);\n const outputPath = path.join(ctx.targetDir, 'dev-infra/memory', file);\n const status = await writeFileSafe(outputPath, content, overwrite);\n\n if (status === 'skipped') {\n result.filesSkipped.push(outputPath);\n } else {\n result.filesCreated.push(outputPath);\n }\n } catch (err) {\n result.errors.push(`Memory ${file}: ${err}`);\n }\n }\n\n return result;\n}\n","import ejs from 'ejs';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { readFile } from './fs.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// In dev: src/utils/template.ts -> ../../templates\n// In dist: dist/index.mjs -> ../templates\n// We try ../templates first (dist), then ../../templates (dev/test)\nimport fs from 'fs';\nconst distPath = path.resolve(__dirname, '../templates');\nconst devPath = path.resolve(__dirname, '../../templates');\nconst TEMPLATES_DIR = fs.existsSync(distPath) ? distPath : devPath;\n\nexport function getTemplatesDir(): string {\n return TEMPLATES_DIR;\n}\n\nexport async function renderTemplate(\n templatePath: string,\n data: Record<string, unknown>\n): Promise<string> {\n const fullPath = path.join(TEMPLATES_DIR, templatePath);\n const template = await readFile(fullPath);\n return ejs.render(template, data, {\n filename: fullPath,\n async: false,\n });\n}\n\nexport function renderString(\n template: string,\n data: Record<string, unknown>\n): string {\n return ejs.render(template, data);\n}\n","import fs from 'fs-extra';\nimport path from 'path';\n\nexport async function ensureDir(dirPath: string): Promise<void> {\n await fs.ensureDir(dirPath);\n}\n\nexport async function writeFileSafe(\n filePath: string,\n content: string,\n overwrite: boolean = false\n): Promise<'created' | 'skipped' | 'overwritten'> {\n const dir = path.dirname(filePath);\n await fs.ensureDir(dir);\n\n if (await fs.pathExists(filePath)) {\n if (!overwrite) {\n return 'skipped';\n }\n await fs.writeFile(filePath, content, 'utf-8');\n return 'overwritten';\n }\n\n await fs.writeFile(filePath, content, 'utf-8');\n return 'created';\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n return fs.pathExists(filePath);\n}\n\nexport async function readFile(filePath: string): Promise<string> {\n return fs.readFile(filePath, 'utf-8');\n}\n\nexport async function makeExecutable(filePath: string): Promise<void> {\n await fs.chmod(filePath, 0o755);\n}\n","import path from 'path';\nimport type { ProjectContext, GeneratorResult, AgentPreset } from '../types.js';\nimport { renderTemplate } from '../utils/template.js';\nimport { writeFileSafe } from '../utils/fs.js';\n\n// --- Agent categories ---\n\nconst PIPELINE_AGENTS = [\n 'analyst',\n 'architect',\n 'skeptic',\n 'developer',\n 'tester',\n 'inspector',\n 'reviewer',\n 'planner',\n];\n\nconst PLANNING_AGENTS = [\n 'researcher',\n 'validator',\n 'interviewer',\n 'decomposer',\n];\n\nconst SECURITY_AGENTS = [\n 'auditor',\n 'prompter',\n 'deployer',\n 'scaffolder',\n];\n\nconst DOCUMENTATION_AGENTS = [\n 'librarian',\n 'writer',\n 'gatekeeper',\n 'verifier',\n];\n\n// --- Presets ---\n\nconst MINIMAL_AGENTS = [\n 'analyst',\n 'developer',\n 'tester',\n 'reviewer',\n 'inspector',\n];\n\nconst CORE_AGENTS = [...PIPELINE_AGENTS];\n\nconst FULL_AGENTS = [\n ...PIPELINE_AGENTS,\n ...PLANNING_AGENTS,\n ...SECURITY_AGENTS,\n ...DOCUMENTATION_AGENTS,\n];\n\n// --- Helpers ---\n\nconst CATEGORY_MAP: Record<string, string> = {};\n\nfor (const name of PIPELINE_AGENTS) {\n CATEGORY_MAP[name] = 'pipeline';\n}\nfor (const name of PLANNING_AGENTS) {\n CATEGORY_MAP[name] = 'planning';\n}\nfor (const name of SECURITY_AGENTS) {\n CATEGORY_MAP[name] = 'security';\n}\nfor (const name of DOCUMENTATION_AGENTS) {\n CATEGORY_MAP[name] = 'documentation';\n}\n\n/**\n * Returns the template subdirectory for a given agent name.\n * Templates live at templates/agents/[category]/[name].md.ejs\n */\nexport function getAgentCategory(name: string): string {\n return CATEGORY_MAP[name] || 'pipeline';\n}\n\n/**\n * Returns the list of agents for the given preset.\n */\nexport function getAgentList(preset: AgentPreset): { name: string; category: string }[] {\n let names: string[];\n\n switch (preset) {\n case 'minimal':\n names = MINIMAL_AGENTS;\n break;\n case 'full':\n names = FULL_AGENTS;\n break;\n case 'core':\n default:\n names = CORE_AGENTS;\n break;\n }\n\n return names.map((name) => ({\n name,\n category: getAgentCategory(name),\n }));\n}\n\nexport async function generateAgents(\n ctx: ProjectContext,\n overwrite: boolean\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n filesCreated: [],\n filesSkipped: [],\n errors: [],\n };\n\n const agents = getAgentList(ctx.agentPreset);\n const templateData = {\n ...ctx,\n defaultBranch: 'main',\n };\n\n for (const agent of agents) {\n try {\n const content = await renderTemplate(\n `agents/${agent.category}/${agent.name}.md.ejs`,\n templateData\n );\n // Output is always flat: .claude/agents/[name].md\n const outputPath = path.join(ctx.targetDir, '.claude/agents', `${agent.name}.md`);\n const status = await writeFileSafe(outputPath, content, overwrite);\n\n if (status === 'skipped') {\n result.filesSkipped.push(outputPath);\n } else {\n result.filesCreated.push(outputPath);\n }\n } catch (err) {\n result.errors.push(`Agent ${agent.name}: ${err}`);\n }\n }\n\n return result;\n}\n","import path from 'path';\nimport type { ProjectContext, GeneratorResult, AgentPreset } from '../types.js';\nimport { renderTemplate } from '../utils/template.js';\nimport { writeFileSafe } from '../utils/fs.js';\n\nconst CORE_SKILLS = [\n 'start-session',\n 'end-session',\n 'take-task',\n 'complete-task',\n 'status',\n 'plan',\n 'review',\n 'code',\n 'test',\n 'done',\n];\n\nconst EXTRA_SKILLS = [\n 'interview',\n 'audit-wave',\n 'write-report',\n 'dashboard',\n 'skill-master',\n 'decompose',\n 'feature',\n 'security',\n 'spec',\n 'techspec',\n 'prompts',\n 'sync-linear',\n];\n\nfunction getSkillList(preset: AgentPreset): { name: string; dir: string }[] {\n const skills: { name: string; dir: string }[] = [];\n\n for (const name of CORE_SKILLS) {\n skills.push({ name, dir: 'core' });\n }\n\n if (preset === 'full') {\n for (const name of EXTRA_SKILLS) {\n skills.push({ name, dir: 'extra' });\n }\n }\n\n return skills;\n}\n\nexport async function generateSkills(\n ctx: ProjectContext,\n overwrite: boolean\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n filesCreated: [],\n filesSkipped: [],\n errors: [],\n };\n\n const templateData = {\n ...ctx,\n defaultBranch: 'main',\n };\n\n const skills = getSkillList(ctx.agentPreset);\n\n for (const skill of skills) {\n try {\n const content = await renderTemplate(\n `skills/${skill.dir}/${skill.name}/SKILL.md.ejs`,\n templateData\n );\n const outputPath = path.join(ctx.targetDir, `.claude/skills/${skill.name}`, 'SKILL.md');\n const status = await writeFileSafe(outputPath, content, overwrite);\n\n if (status === 'skipped') {\n result.filesSkipped.push(outputPath);\n } else {\n result.filesCreated.push(outputPath);\n }\n } catch (err) {\n result.errors.push(`Skill ${skill.name}: ${err}`);\n }\n }\n\n return result;\n}\n","import path from 'path';\nimport type { ProjectContext, GeneratorResult } from '../types.js';\nimport { renderTemplate } from '../utils/template.js';\nimport { writeFileSafe } from '../utils/fs.js';\n\nconst RULES = [\n 'commit-conventions',\n 'development-cycle',\n 'testing-standards',\n 'shared-resources',\n 'context-loading',\n 'agent-output-format',\n 'quality-gates',\n 'rollback-protocol',\n 'linear-sync',\n];\n\nexport async function generateRules(\n ctx: ProjectContext,\n overwrite: boolean\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n filesCreated: [],\n filesSkipped: [],\n errors: [],\n };\n\n const templateData = {\n ...ctx,\n defaultBranch: 'main',\n };\n\n for (const rule of RULES) {\n try {\n const content = await renderTemplate(`rules/${rule}.md.ejs`, templateData);\n const outputPath = path.join(ctx.targetDir, '.claude/rules', `${rule}.md`);\n const status = await writeFileSafe(outputPath, content, overwrite);\n\n if (status === 'skipped') {\n result.filesSkipped.push(outputPath);\n } else {\n result.filesCreated.push(outputPath);\n }\n } catch (err) {\n result.errors.push(`Rule ${rule}: ${err}`);\n }\n }\n\n return result;\n}\n","import path from 'path';\nimport type { ProjectContext, GeneratorResult } from '../types.js';\nimport { renderTemplate } from '../utils/template.js';\nimport { writeFileSafe, fileExists, readFile } from '../utils/fs.js';\nimport { mergeSections } from '../utils/merge.js';\n\nexport async function generateClaudeMd(\n ctx: ProjectContext,\n overwrite: boolean\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n filesCreated: [],\n filesSkipped: [],\n errors: [],\n };\n\n const templateData = {\n ...ctx,\n defaultBranch: 'main',\n };\n\n // CLAUDE.md (with sectional merge on update)\n try {\n const content = await renderTemplate('root/CLAUDE.md.ejs', templateData);\n const outputPath = path.join(ctx.targetDir, '.claude/CLAUDE.md');\n\n const exists = await fileExists(outputPath);\n\n if (exists && overwrite) {\n // Sectional merge: update framework sections, preserve user sections\n const existingContent = await readFile(outputPath);\n const merged = mergeSections(existingContent, content);\n await writeFileSafe(outputPath, merged, true);\n result.filesCreated.push(outputPath);\n } else {\n // Normal: create or skip\n const status = await writeFileSafe(outputPath, content, overwrite);\n if (status === 'skipped') {\n result.filesSkipped.push(outputPath);\n } else {\n result.filesCreated.push(outputPath);\n }\n }\n } catch (err) {\n result.errors.push(`CLAUDE.md: ${err}`);\n }\n\n // settings.json\n try {\n const content = await renderTemplate('root/settings.json.ejs', templateData);\n const outputPath = path.join(ctx.targetDir, '.claude/settings.json');\n const status = await writeFileSafe(outputPath, content, overwrite);\n\n if (status === 'skipped') {\n result.filesSkipped.push(outputPath);\n } else {\n result.filesCreated.push(outputPath);\n }\n } catch (err) {\n result.errors.push(`settings.json: ${err}`);\n }\n\n return result;\n}\n","/**\n * Sectional merge for Markdown files.\n *\n * Parses Markdown into sections delimited by `## ` headers and\n * merges framework (template) sections with user-defined sections\n * so that `agent-forge update` preserves custom content.\n */\n\nexport interface Section {\n header: string; // full header line, e.g. \"## Agents\"\n content: string; // everything after header until next ## or EOF\n}\n\nexport interface ParsedMarkdown {\n preamble: string; // # title + content before the first ##\n sections: Section[];\n}\n\n/**\n * Parses Markdown into a preamble and an array of `## ` sections.\n *\n * Only `## ` (exactly two hashes followed by a space) is treated as\n * a section delimiter. `#`, `###`, `####` etc. are NOT delimiters\n * and stay inside the section they belong to.\n */\nexport function parseSections(markdown: string): ParsedMarkdown {\n const lines = markdown.split('\\n');\n\n let preamble = '';\n const sections: Section[] = [];\n let currentHeader: string | null = null;\n let currentContent = '';\n let foundFirstSection = false;\n\n for (const line of lines) {\n // Match lines that start with exactly \"## \" (not \"# \", \"### \", etc.)\n if (/^## /.test(line)) {\n if (foundFirstSection && currentHeader !== null) {\n sections.push({ header: currentHeader, content: currentContent });\n }\n\n if (!foundFirstSection) {\n // Everything accumulated so far is the preamble\n preamble = currentContent;\n foundFirstSection = true;\n currentContent = '';\n }\n\n currentHeader = line;\n currentContent = '';\n } else {\n currentContent += line + '\\n';\n }\n }\n\n // Flush the last section (or preamble if no sections found)\n if (foundFirstSection && currentHeader !== null) {\n sections.push({ header: currentHeader, content: currentContent });\n } else {\n preamble = currentContent;\n }\n\n return { preamble, sections };\n}\n\n/**\n * Normalises a `## ` header for comparison purposes.\n * Strips the leading `## `, trims whitespace and lowercases.\n */\nfunction normalizeHeader(header: string): string {\n return header.replace(/^##\\s+/, '').trim().toLowerCase();\n}\n\n/**\n * Merges an existing Markdown file with a template.\n *\n * Algorithm:\n * 1. Parse both `existing` and `template` into sections.\n * 2. Build a Set of normalised template headers.\n * 3. Identify *user sections* — sections present in `existing`\n * whose normalised headers are NOT in the template set.\n * 4. Result = template preamble + all template sections +\n * user sections appended at the end.\n *\n * If `existing` is empty or has no `## ` sections the template is\n * returned as-is.\n */\nexport function mergeSections(existing: string, template: string): string {\n if (!existing || !existing.trim()) {\n return template;\n }\n\n const parsedExisting = parseSections(existing);\n const parsedTemplate = parseSections(template);\n\n // If existing has no sections — nothing to preserve, return template\n if (parsedExisting.sections.length === 0) {\n return template;\n }\n\n // Set of normalised template headers\n const templateHeaders = new Set(\n parsedTemplate.sections.map((s) => normalizeHeader(s.header)),\n );\n\n // User sections: present in existing but absent from template\n const userSections = parsedExisting.sections.filter(\n (s) => !templateHeaders.has(normalizeHeader(s.header)),\n );\n\n // Assemble result\n let result = parsedTemplate.preamble;\n\n for (const section of parsedTemplate.sections) {\n result += section.header + '\\n';\n result += section.content;\n }\n\n for (const section of userSections) {\n result += section.header + '\\n';\n result += section.content;\n }\n\n return result;\n}\n","import path from 'path';\nimport type { ProjectContext, GeneratorResult } from '../types.js';\nimport { renderTemplate } from '../utils/template.js';\nimport { writeFileSafe, ensureDir } from '../utils/fs.js';\n\nexport async function generateInfra(\n ctx: ProjectContext,\n overwrite: boolean\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n filesCreated: [],\n filesSkipped: [],\n errors: [],\n };\n\n const templateData = {\n ...ctx,\n defaultBranch: 'main',\n };\n\n // tasks.json\n try {\n const content = await renderTemplate('tasks/tasks.json.ejs', templateData);\n const outputPath = path.join(ctx.targetDir, 'dev-infra/tasks/tasks.json');\n const status = await writeFileSafe(outputPath, content, overwrite);\n\n if (status === 'skipped') {\n result.filesSkipped.push(outputPath);\n } else {\n result.filesCreated.push(outputPath);\n }\n } catch (err) {\n result.errors.push(`tasks.json: ${err}`);\n }\n\n // linear-mapping.json\n try {\n const content = await renderTemplate('config/linear-mapping.json.ejs', templateData);\n const outputPath = path.join(ctx.targetDir, 'dev-infra/config/linear-mapping.json');\n const status = await writeFileSafe(outputPath, content, overwrite);\n\n if (status === 'skipped') {\n result.filesSkipped.push(outputPath);\n } else {\n result.filesCreated.push(outputPath);\n }\n } catch (err) {\n result.errors.push(`linear-mapping.json: ${err}`);\n }\n\n // Create empty directories with .gitkeep\n const dirs = [\n 'dev-infra/sessions',\n 'dev-infra/tests/acceptance',\n 'dev-infra/tests/pmi',\n 'dev-infra/tests/results',\n 'dev-infra/config',\n ];\n\n for (const dir of dirs) {\n try {\n const dirPath = path.join(ctx.targetDir, dir);\n await ensureDir(dirPath);\n const gitkeepPath = path.join(dirPath, '.gitkeep');\n const status = await writeFileSafe(gitkeepPath, '', overwrite);\n\n if (status === 'skipped') {\n result.filesSkipped.push(gitkeepPath);\n } else {\n result.filesCreated.push(gitkeepPath);\n }\n } catch (err) {\n result.errors.push(`Dir ${dir}: ${err}`);\n }\n }\n\n // .claude-forge.json — manifest for doctor command\n try {\n const manifest = buildManifest(ctx);\n\n const outputPath = path.join(ctx.targetDir, '.claude-forge.json');\n const status = await writeFileSafe(\n outputPath,\n JSON.stringify(manifest, null, 2) + '\\n',\n overwrite\n );\n\n if (status === 'skipped') {\n result.filesSkipped.push(outputPath);\n } else {\n result.filesCreated.push(outputPath);\n }\n } catch (err) {\n result.errors.push(`.claude-forge.json: ${err}`);\n }\n\n return result;\n}\n\nexport interface ForgeManifest {\n version: string;\n createdAt: string;\n updatedAt: string;\n projectName: string;\n projectDescription: string;\n agentPreset: string;\n language: string;\n stack: string;\n framework: string;\n testFramework: string;\n testCommand: string;\n srcDir: string;\n testDir: string;\n commitStyle: string;\n expectedFiles: string[];\n}\n\nexport function buildManifest(ctx: ProjectContext): ForgeManifest {\n return {\n version: '3.2.0',\n createdAt: ctx.today,\n updatedAt: ctx.today,\n projectName: ctx.projectName,\n projectDescription: ctx.projectDescription,\n language: ctx.language,\n agentPreset: ctx.agentPreset,\n stack: ctx.stack,\n framework: ctx.framework,\n testFramework: ctx.testFramework,\n testCommand: ctx.testCommand,\n srcDir: ctx.srcDir,\n testDir: ctx.testDir,\n commitStyle: ctx.commitStyle,\n expectedFiles: getExpectedFiles(ctx),\n };\n}\n\nexport function getExpectedFiles(ctx: ProjectContext): string[] {\n const files = [\n '.claude/CLAUDE.md',\n '.claude/settings.json',\n '.claude-forge.json',\n 'dev-infra/tasks/tasks.json',\n 'dev-infra/memory/active-context.md',\n 'dev-infra/memory/progress.md',\n 'dev-infra/memory/project-brief.md',\n 'dev-infra/memory/decisions.md',\n 'dev-infra/memory/tech-stack.md',\n 'dev-infra/memory/tech-debt.md',\n 'dev-infra/memory/patterns.md',\n 'dev-infra/memory/troubleshooting.md',\n 'dev-infra/memory/checkpoint.yml',\n 'dev-infra/config/linear-mapping.json',\n ];\n\n // Hooks\n files.push('.claude/hooks/protect-docs.sh');\n\n // Rules (8 total)\n files.push(\n '.claude/rules/commit-conventions.md',\n '.claude/rules/development-cycle.md',\n '.claude/rules/testing-standards.md',\n '.claude/rules/shared-resources.md',\n '.claude/rules/context-loading.md',\n '.claude/rules/agent-output-format.md',\n '.claude/rules/quality-gates.md',\n '.claude/rules/rollback-protocol.md',\n '.claude/rules/linear-sync.md',\n );\n\n // Skills (10 core + 11 extra for full)\n const coreSkills = [\n 'start-session', 'end-session', 'take-task',\n 'complete-task', 'status', 'plan', 'review',\n 'code', 'test', 'done',\n ];\n const extraSkills = [\n 'interview', 'audit-wave', 'write-report', 'dashboard', 'skill-master',\n 'decompose', 'feature', 'security', 'spec', 'techspec', 'prompts', 'sync-linear',\n ];\n const skills = ctx.agentPreset === 'full'\n ? [...coreSkills, ...extraSkills]\n : coreSkills;\n for (const skill of skills) {\n files.push(`.claude/skills/${skill}/SKILL.md`);\n }\n\n // Agents depend on preset\n const pipelineAgents = [\n 'analyst', 'architect', 'skeptic', 'developer',\n 'tester', 'inspector', 'reviewer', 'planner',\n ];\n const planningAgents = ['researcher', 'validator', 'interviewer', 'decomposer'];\n const securityAgents = ['auditor', 'prompter', 'deployer', 'scaffolder'];\n const documentationAgents = ['librarian', 'writer', 'gatekeeper', 'verifier'];\n\n const minimalAgents = ['analyst', 'developer', 'tester', 'reviewer', 'inspector'];\n\n const coreAgents = [...pipelineAgents];\n const fullAgents = [\n ...pipelineAgents,\n ...planningAgents,\n ...securityAgents,\n ...documentationAgents,\n ];\n\n const agents = ctx.agentPreset === 'minimal'\n ? minimalAgents\n : ctx.agentPreset === 'full'\n ? fullAgents\n : coreAgents;\n\n for (const agent of agents) {\n files.push(`.claude/agents/${agent}.md`);\n }\n\n return files;\n}\n","import path from 'path';\nimport type { ProjectContext, GeneratorResult } from '../types.js';\nimport { renderTemplate } from '../utils/template.js';\nimport { writeFileSafe, makeExecutable } from '../utils/fs.js';\n\nexport async function generateHooks(\n ctx: ProjectContext,\n overwrite: boolean\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n filesCreated: [],\n filesSkipped: [],\n errors: [],\n };\n\n const templateData = {\n ...ctx,\n defaultBranch: 'main',\n };\n\n try {\n const content = await renderTemplate('hooks/protect-docs.sh.ejs', templateData);\n const outputPath = path.join(ctx.targetDir, '.claude/hooks/protect-docs.sh');\n const status = await writeFileSafe(outputPath, content, overwrite);\n\n if (status === 'skipped') {\n result.filesSkipped.push(outputPath);\n } else {\n result.filesCreated.push(outputPath);\n await makeExecutable(outputPath);\n }\n } catch (err) {\n result.errors.push(`Hook protect-docs.sh: ${err}`);\n }\n\n return result;\n}\n","import type { ProjectContext, GeneratorResult } from '../types.js';\nimport { generateMemoryBank } from './memory-bank.js';\nimport { generateAgents } from './agents.js';\nimport { generateSkills } from './skills.js';\nimport { generateRules } from './rules.js';\nimport { generateClaudeMd } from './claude-md.js';\nimport { generateInfra } from './infra.js';\nimport { generateHooks } from './hooks.js';\n\nexport async function generateAll(\n ctx: ProjectContext,\n overwrite: boolean = false\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n filesCreated: [],\n filesSkipped: [],\n errors: [],\n };\n\n const generators = [\n generateClaudeMd,\n generateAgents,\n generateSkills,\n generateRules,\n generateMemoryBank,\n generateHooks,\n generateInfra,\n ];\n\n for (const generator of generators) {\n try {\n const partial = await generator(ctx, overwrite);\n result.filesCreated.push(...partial.filesCreated);\n result.filesSkipped.push(...partial.filesSkipped);\n result.errors.push(...partial.errors);\n } catch (err) {\n result.errors.push(`Generator error: ${err}`);\n }\n }\n\n return result;\n}\n","import path from 'path';\nimport chalk from 'chalk';\nimport { fileExists, readFile } from '../utils/fs.js';\nimport type { DoctorCheck } from '../types.js';\n\nexport async function doctorCommand(): Promise<void> {\n const targetDir = process.cwd();\n\n console.log();\n console.log(chalk.bold(' agent-forge doctor'));\n console.log(chalk.dim(' Checking project structure integrity...'));\n console.log();\n\n // Load manifest\n const manifestPath = path.join(targetDir, '.claude-forge.json');\n const manifestExists = await fileExists(manifestPath);\n\n if (!manifestExists) {\n console.log(chalk.red(' .claude-forge.json not found'));\n console.log(chalk.dim(' Run `agent-forge init` first to initialize the project.'));\n console.log();\n process.exit(1);\n }\n\n const manifestRaw = await readFile(manifestPath);\n let manifest: { version: string; expectedFiles: string[]; projectName: string };\n\n try {\n manifest = JSON.parse(manifestRaw);\n } catch {\n console.log(chalk.red(' .claude-forge.json is corrupted'));\n process.exit(1);\n }\n\n console.log(chalk.dim(` Project: ${manifest.projectName}`));\n console.log(chalk.dim(` Version: ${manifest.version}`));\n console.log();\n\n const checks: DoctorCheck[] = [];\n let okCount = 0;\n let failCount = 0;\n\n for (const file of manifest.expectedFiles) {\n const filePath = path.join(targetDir, file);\n const exists = await fileExists(filePath);\n\n const check: DoctorCheck = {\n name: file,\n path: filePath,\n exists,\n ok: exists,\n };\n\n if (exists) {\n // Check if file is not empty\n try {\n const content = await readFile(filePath);\n if (content.trim().length === 0) {\n check.ok = false;\n check.message = 'File is empty';\n }\n } catch {\n check.ok = false;\n check.message = 'Cannot read file';\n }\n } else {\n check.message = 'File not found';\n }\n\n checks.push(check);\n if (check.ok) okCount++;\n else failCount++;\n }\n\n // Display results grouped by category\n const categories: Record<string, DoctorCheck[]> = {};\n for (const check of checks) {\n const category = check.name.startsWith('.claude/agents')\n ? 'Agents'\n : check.name.startsWith('.claude/skills')\n ? 'Skills'\n : check.name.startsWith('.claude/rules')\n ? 'Rules'\n : check.name.startsWith('.claude/')\n ? 'Claude Config'\n : check.name.startsWith('dev-infra/memory')\n ? 'Memory Bank'\n : check.name.startsWith('dev-infra/')\n ? 'Infrastructure'\n : 'Other';\n\n if (!categories[category]) categories[category] = [];\n categories[category].push(check);\n }\n\n for (const [category, items] of Object.entries(categories)) {\n const allOk = items.every(c => c.ok);\n const icon = allOk ? chalk.green('OK') : chalk.red('!!');\n console.log(` ${icon} ${chalk.bold(category)}`);\n\n for (const item of items) {\n if (item.ok) {\n console.log(chalk.green(` + ${item.name}`));\n } else {\n console.log(chalk.red(` - ${item.name} (${item.message})`));\n }\n }\n console.log();\n }\n\n // Summary\n console.log(chalk.bold(' Summary'));\n console.log(chalk.green(` OK: ${okCount}`));\n if (failCount > 0) {\n console.log(chalk.red(` Missing/broken: ${failCount}`));\n console.log();\n console.log(chalk.dim(' Run `agent-forge init --overwrite` to regenerate missing files.'));\n } else {\n console.log(chalk.green(' All checks passed!'));\n }\n console.log();\n\n if (failCount > 0) {\n process.exit(1);\n }\n}\n","import path from 'path';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { fileExists, readFile, writeFileSafe } from '../utils/fs.js';\nimport { generateClaudeMd } from '../generators/claude-md.js';\nimport { generateAgents } from '../generators/agents.js';\nimport { generateSkills } from '../generators/skills.js';\nimport { generateRules } from '../generators/rules.js';\nimport { generateMemoryBank } from '../generators/memory-bank.js';\nimport { generateHooks } from '../generators/hooks.js';\nimport { generateInfra } from '../generators/infra.js';\nimport { buildManifest } from '../generators/infra.js';\nimport type { ForgeManifest } from '../generators/infra.js';\nimport type { ProjectContext, GeneratorResult, AgentPreset, Language, CommitStyle } from '../types.js';\n\nfunction today(): string {\n return new Date().toISOString().split('T')[0];\n}\n\nfunction contextFromManifest(manifest: ForgeManifest, targetDir: string): ProjectContext {\n return {\n projectName: manifest.projectName || targetDir.split('/').pop() || 'my-project',\n projectDescription: manifest.projectDescription || 'AI-driven project',\n stack: manifest.stack || 'typescript',\n framework: manifest.framework || 'None',\n testFramework: manifest.testFramework || 'vitest',\n testCommand: manifest.testCommand || 'npx vitest run',\n srcDir: manifest.srcDir || 'src/',\n testDir: manifest.testDir || 'tests/',\n team: [],\n milestones: [],\n agentPreset: (manifest.agentPreset as AgentPreset) || 'core',\n language: (manifest.language as Language) || 'ru',\n commitStyle: (manifest.commitStyle as CommitStyle) || 'standard',\n today: today(),\n targetDir,\n };\n}\n\nexport async function updateCommand(): Promise<void> {\n const targetDir = process.cwd();\n\n console.log();\n console.log(chalk.bold(' agent-forge update v3.0.0'));\n console.log(chalk.dim(' Updating framework files...'));\n console.log();\n\n // 1. Check .claude-forge.json exists\n const manifestPath = path.join(targetDir, '.claude-forge.json');\n const manifestExists = await fileExists(manifestPath);\n\n if (!manifestExists) {\n console.log(chalk.red(' .claude-forge.json not found'));\n console.log(\n chalk.dim(' This project is not initialized. Run `agent-forge init` first.')\n );\n console.log();\n process.exit(1);\n }\n\n // 2. Read existing manifest\n const manifestRaw = await readFile(manifestPath);\n let existingManifest: ForgeManifest;\n\n try {\n existingManifest = JSON.parse(manifestRaw);\n } catch {\n console.log(chalk.red(' .claude-forge.json is corrupted. Cannot update.'));\n console.log(\n chalk.dim(' Run `agent-forge init --overwrite` to reinitialize.')\n );\n console.log();\n process.exit(1);\n }\n\n const previousVersion = existingManifest.version || 'unknown';\n\n // 3. Build ProjectContext from manifest (no interactive prompts)\n const ctx = contextFromManifest(existingManifest, targetDir);\n\n const spinner = ora('Updating framework files...').start();\n\n try {\n const result: GeneratorResult = {\n filesCreated: [],\n filesSkipped: [],\n errors: [],\n };\n\n // 4. Framework files — overwrite=true\n const frameworkGenerators = [\n generateClaudeMd,\n generateAgents,\n generateSkills,\n generateRules,\n generateHooks,\n ];\n\n for (const generator of frameworkGenerators) {\n try {\n const partial = await generator(ctx, true);\n result.filesCreated.push(...partial.filesCreated);\n result.filesSkipped.push(...partial.filesSkipped);\n result.errors.push(...partial.errors);\n } catch (err) {\n result.errors.push(`Generator error: ${err}`);\n }\n }\n\n // 5. User data files — overwrite=false (preserve)\n const userDataGenerators = [\n generateMemoryBank,\n generateInfra,\n ];\n\n for (const generator of userDataGenerators) {\n try {\n const partial = await generator(ctx, false);\n result.filesCreated.push(...partial.filesCreated);\n result.filesSkipped.push(...partial.filesSkipped);\n result.errors.push(...partial.errors);\n } catch (err) {\n result.errors.push(`Generator error: ${err}`);\n }\n }\n\n // 6. Update .claude-forge.json manually (always overwrite)\n const updatedManifest = buildManifest(ctx);\n // Preserve original createdAt\n updatedManifest.createdAt = existingManifest.createdAt || updatedManifest.createdAt;\n updatedManifest.updatedAt = today();\n\n await writeFileSafe(\n manifestPath,\n JSON.stringify(updatedManifest, null, 2) + '\\n',\n true\n );\n\n spinner.succeed(chalk.green('Framework files updated'));\n\n // 7. Build report\n // Separate newly added files from overwritten files\n const newFiles = result.filesCreated.filter(f => !result.filesSkipped.includes(f));\n const updatedCount = newFiles.length;\n const skippedCount = result.filesSkipped.length;\n\n console.log();\n if (updatedCount > 0) {\n console.log(\n chalk.green(` + ${updatedCount} files updated/added`)\n );\n }\n if (skippedCount > 0) {\n console.log(\n chalk.yellow(` ~ ${skippedCount} files skipped (user data preserved)`)\n );\n }\n if (result.errors.length > 0) {\n console.log(chalk.red(` ! ${result.errors.length} errors:`));\n for (const err of result.errors) {\n console.log(chalk.red(` - ${err}`));\n }\n }\n\n console.log();\n if (previousVersion !== updatedManifest.version) {\n console.log(\n chalk.dim(` .claude-forge.json updated: ${previousVersion} -> v${updatedManifest.version}`)\n );\n } else {\n console.log(\n chalk.dim(` .claude-forge.json updated (v${updatedManifest.version})`)\n );\n }\n console.log();\n } catch (err) {\n spinner.fail(chalk.red('Failed to update framework files'));\n console.error(err);\n process.exit(1);\n }\n}\n"],"mappings":"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","names":["path","path","fs","path","path","path","path","path","path","path","path","path","path","path","path","path","path","path","path","chalk","chalk","path","path","chalk","ora","today","chalk","path","ora"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alxyrgin/agent-forge",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "AI-driven Development Framework for Claude Code — scaffold Memory Bank, agents, skills, and rules in any project",
|
|
5
5
|
"homepage": "https://github.com/alxyrgin/agent-forge#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"linear": {
|
|
3
|
+
"team": "",
|
|
4
|
+
"project": ""
|
|
5
|
+
},
|
|
6
|
+
"priority_map": {
|
|
7
|
+
"critical": 1,
|
|
8
|
+
"high": 2,
|
|
9
|
+
"medium": 3,
|
|
10
|
+
"low": 4
|
|
11
|
+
},
|
|
12
|
+
"status_map": {
|
|
13
|
+
"todo": "Todo",
|
|
14
|
+
"in_progress": "In Progress",
|
|
15
|
+
"done": "Done",
|
|
16
|
+
"blocked": "Blocked"
|
|
17
|
+
},
|
|
18
|
+
"assignee_map": {},
|
|
19
|
+
"labels": {},
|
|
20
|
+
"comment_on_verdicts": [
|
|
21
|
+
"reviewer",
|
|
22
|
+
"tester",
|
|
23
|
+
"inspector",
|
|
24
|
+
"session_end",
|
|
25
|
+
"task_complete"
|
|
26
|
+
]
|
|
27
|
+
}
|
|
@@ -264,6 +264,7 @@ Agent(subagent_type="verifier", prompt="...")
|
|
|
264
264
|
6. **Inspector после tester** — качество тестов проверяется всегда
|
|
265
265
|
7. **Tech-debt обязателен** — никогда не пропускать, для всех размеров
|
|
266
266
|
8. **Checkpoint после каждого шага** — восстановление при обрыве
|
|
267
|
+
9. **Linear sync non-blocking** — после изменения status задачи синхронизировать в Linear (если настроен). Ошибки sync не останавливают пайплайн
|
|
267
268
|
|
|
268
269
|
## Ключевые файлы
|
|
269
270
|
|
|
@@ -285,6 +286,7 @@ Agent(subagent_type="verifier", prompt="...")
|
|
|
285
286
|
| Shared Resources | `.claude/rules/shared-resources.md` |
|
|
286
287
|
| Quality Gates | `.claude/rules/quality-gates.md` |
|
|
287
288
|
| Agent Output Format | `.claude/rules/agent-output-format.md` |
|
|
289
|
+
| Linear маппинг | `dev-infra/config/linear-mapping.json` |
|
|
288
290
|
| Rollback Protocol | `.claude/rules/rollback-protocol.md` |
|
|
289
291
|
|
|
290
292
|
## Команда
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Linear Sync — правила синхронизации
|
|
2
|
+
|
|
3
|
+
## Принцип
|
|
4
|
+
|
|
5
|
+
- **tasks.json = source of truth**, Linear = зеркало (read-only mirror)
|
|
6
|
+
- Синхронизация однонаправленная: tasks.json → Linear
|
|
7
|
+
- Никогда не читать данные из Linear для обновления tasks.json
|
|
8
|
+
|
|
9
|
+
## Триггеры синхронизации
|
|
10
|
+
|
|
11
|
+
| Событие | Действие | Обязательность |
|
|
12
|
+
|---------|----------|----------------|
|
|
13
|
+
| Status change (take-task, complete-task) | Обновить state issue | Non-blocking |
|
|
14
|
+
| Новые задачи (plan init, decompose) | Предложить sync | Non-blocking |
|
|
15
|
+
| Verdict (reviewer, tester) | Добавить comment к issue | Non-blocking |
|
|
16
|
+
| Конец сессии (end-session) | Session summary comment | Non-blocking |
|
|
17
|
+
| Финализация (done) | Обновить все issues → Done | Non-blocking |
|
|
18
|
+
|
|
19
|
+
## Маппинг полей
|
|
20
|
+
|
|
21
|
+
| tasks.json | Linear | Примечание |
|
|
22
|
+
|-----------|--------|------------|
|
|
23
|
+
| title | title | Прямой маппинг |
|
|
24
|
+
| description + AC + TDD | description | Форматированный Markdown |
|
|
25
|
+
| priority | priority | Через priority_map |
|
|
26
|
+
| status | state | Через status_map |
|
|
27
|
+
| assignee | assigneeId | Через assignee_map |
|
|
28
|
+
| type / tags | labelIds | Через labels |
|
|
29
|
+
| deadline | dueDate | ISO 8601 |
|
|
30
|
+
| dependencies | blockedBy | Через linear_id зависимостей |
|
|
31
|
+
|
|
32
|
+
## Формат комментариев
|
|
33
|
+
|
|
34
|
+
При добавлении комментариев к issues использовать формат:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
### [Event Type] — [Timestamp]
|
|
38
|
+
|
|
39
|
+
[Содержимое]
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
_Synced by agent-forge_
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Типы комментариев
|
|
46
|
+
|
|
47
|
+
| Событие | Формат |
|
|
48
|
+
|---------|--------|
|
|
49
|
+
| Verdict (reviewer) | `### Code Review — YYYY-MM-DD\n\nVerdict: [verdict]\nFindings: [count]\n[summary]` |
|
|
50
|
+
| Verdict (tester) | `### Test Results — YYYY-MM-DD\n\nVerdict: [verdict]\nTests: [passed]/[total]\n[summary]` |
|
|
51
|
+
| Session end | `### Session Summary — YYYY-MM-DD\n\n[что сделано]\n[следующие шаги]` |
|
|
52
|
+
| Task complete | `### Task Completed — YYYY-MM-DD\n\n[summary of work done]` |
|
|
53
|
+
|
|
54
|
+
## Error Handling
|
|
55
|
+
|
|
56
|
+
1. **Non-blocking** — ошибка sync НЕ останавливает пайплайн разработки
|
|
57
|
+
2. **No retry** — при ошибке логировать warning и продолжить
|
|
58
|
+
3. **Graceful degradation** — если Linear MCP недоступен, пропустить sync молча
|
|
59
|
+
4. **Проверка доступности** — перед sync проверить наличие linear-mapping.json и что team/project заполнены
|
|
60
|
+
|
|
61
|
+
## Конфигурация
|
|
62
|
+
|
|
63
|
+
Файл: `dev-infra/config/linear-mapping.json`
|
|
64
|
+
|
|
65
|
+
Заполняется пользователем после `agent-forge init`. Пустые поля = sync отключён для этого маппинга.
|
|
@@ -48,3 +48,20 @@ active: false
|
|
|
48
48
|
- По приоритету и зависимостям
|
|
49
49
|
|
|
50
50
|
## 8. Предложить коммит
|
|
51
|
+
|
|
52
|
+
## Linear Sync
|
|
53
|
+
|
|
54
|
+
> Non-blocking. Если Linear MCP недоступен или linear-mapping.json не настроен — пропустить.
|
|
55
|
+
|
|
56
|
+
1. Проверь наличие `dev-infra/config/linear-mapping.json` и что `linear.team` заполнен
|
|
57
|
+
2. Если задача имеет `linear_id` — обнови issue:
|
|
58
|
+
- State → «Done» (через status_map)
|
|
59
|
+
- Добавь comment с summary выполненной работы:
|
|
60
|
+
```
|
|
61
|
+
### Task Completed — YYYY-MM-DD
|
|
62
|
+
|
|
63
|
+
[краткое описание что было сделано, какие файлы затронуты]
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
_Synced by agent-forge_
|
|
67
|
+
```
|
|
@@ -64,3 +64,21 @@ Agent(subagent_type="librarian", prompt="
|
|
|
64
64
|
- [ ] Документация актуальна
|
|
65
65
|
- [ ] PK files обновлены
|
|
66
66
|
- [ ] Коммит предложен
|
|
67
|
+
|
|
68
|
+
## Linear Sync
|
|
69
|
+
|
|
70
|
+
> Non-blocking. Если Linear MCP недоступен или linear-mapping.json не настроен — пропустить.
|
|
71
|
+
|
|
72
|
+
1. Проверь наличие `dev-infra/config/linear-mapping.json` и что `linear.team` заполнен
|
|
73
|
+
2. При финализации фичи — для всех задач фичи с `linear_id`:
|
|
74
|
+
- Обнови state → «Done» (через status_map)
|
|
75
|
+
- Добавь comment:
|
|
76
|
+
```
|
|
77
|
+
### Feature Finalized — YYYY-MM-DD
|
|
78
|
+
|
|
79
|
+
Feature [название] финализирована.
|
|
80
|
+
Задач завершено: N
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
_Synced by agent-forge_
|
|
84
|
+
```
|
|
@@ -87,3 +87,21 @@ memory(Участник): обновление после сессии YYYY-MM-D
|
|
|
87
87
|
- dev-infra/tasks/tasks.json (если обновлён)
|
|
88
88
|
|
|
89
89
|
**После коммита — `git push origin <%= defaultBranch || 'main' %>`.**
|
|
90
|
+
|
|
91
|
+
## Linear Sync
|
|
92
|
+
|
|
93
|
+
> Non-blocking. Если Linear MCP недоступен или linear-mapping.json не настроен — пропустить.
|
|
94
|
+
|
|
95
|
+
1. Проверь наличие `dev-infra/config/linear-mapping.json` и что `linear.team` заполнен
|
|
96
|
+
2. Для каждой задачи в статусе `in_progress` с `linear_id`:
|
|
97
|
+
- Добавь comment с session summary:
|
|
98
|
+
```
|
|
99
|
+
### Session Summary — YYYY-MM-DD
|
|
100
|
+
|
|
101
|
+
[что сделано за сессию]
|
|
102
|
+
[текущий статус задачи]
|
|
103
|
+
[следующие шаги]
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
_Synced by agent-forge_
|
|
107
|
+
```
|
|
@@ -56,3 +56,12 @@ Agent(subagent_type="planner", prompt="Режим: init. Документаци
|
|
|
56
56
|
## Режим `validate`
|
|
57
57
|
|
|
58
58
|
Шаги 1-2 как в replan, но показать только отчёт без предложений.
|
|
59
|
+
|
|
60
|
+
## Linear Sync
|
|
61
|
+
|
|
62
|
+
> Non-blocking. Если Linear MCP недоступен или linear-mapping.json не настроен — пропустить.
|
|
63
|
+
|
|
64
|
+
1. Проверь наличие `dev-infra/config/linear-mapping.json` и что `linear.team` заполнен
|
|
65
|
+
2. После `init` или `replan` — если были созданы новые задачи:
|
|
66
|
+
- Предложи пользователю: «Созданы новые задачи. Синхронизировать в Linear? (/sync-linear)»
|
|
67
|
+
- **Не запускай sync автоматически** — только предложи
|
|
@@ -316,3 +316,12 @@ Team Lead проверяет 3 источника:
|
|
|
316
316
|
4. Обнови active-context.md: убрать задачу, добавить результат
|
|
317
317
|
5. Очисти checkpoint: `active: false`
|
|
318
318
|
6. Предложи коммит
|
|
319
|
+
|
|
320
|
+
## Linear Sync
|
|
321
|
+
|
|
322
|
+
> Non-blocking. Если Linear MCP недоступен или linear-mapping.json не настроен — пропустить.
|
|
323
|
+
|
|
324
|
+
1. Проверь наличие `dev-infra/config/linear-mapping.json` и что `linear.team` заполнен
|
|
325
|
+
2. Если задача имеет `linear_id` — обнови issue:
|
|
326
|
+
- State → «In Progress» (через status_map)
|
|
327
|
+
3. Если задача не имеет `linear_id` — пропустить (будет создан при полном sync)
|
|
@@ -70,3 +70,12 @@ Agent(subagent_type="skeptic", prompt="Проверь задачи на мира
|
|
|
70
70
|
- [ ] Skeptic проверил
|
|
71
71
|
- [ ] Пользователь утвердил
|
|
72
72
|
- [ ] tasks.json обновлён
|
|
73
|
+
|
|
74
|
+
## Linear Sync
|
|
75
|
+
|
|
76
|
+
> Non-blocking. Если Linear MCP недоступен или linear-mapping.json не настроен — пропустить.
|
|
77
|
+
|
|
78
|
+
1. Проверь наличие `dev-infra/config/linear-mapping.json` и что `linear.team` заполнен
|
|
79
|
+
2. После записи задач в tasks.json:
|
|
80
|
+
- Предложи пользователю: «Создано N новых задач. Синхронизировать в Linear? (/sync-linear)»
|
|
81
|
+
- **Не запускай sync автоматически** — только предложи
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sync-linear
|
|
3
|
+
description: |
|
|
4
|
+
Синхронизация tasks.json → Linear (однонаправленная).
|
|
5
|
+
Создаёт/обновляет issues, устанавливает зависимости, сохраняет linear_id.
|
|
6
|
+
|
|
7
|
+
Use when: «синхронизируй linear», «sync linear», «обнови linear», «залей задачи в linear»
|
|
8
|
+
user-invocable: true
|
|
9
|
+
disable-model-invocation: false
|
|
10
|
+
argument-hint: "[all|milestone:X|task:ID]"
|
|
11
|
+
allowed-tools: Read, Write, Edit, Glob, Grep, Bash
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Синхронизация tasks.json → Linear
|
|
15
|
+
|
|
16
|
+
Аргумент: `$ARGUMENTS` — scope синхронизации.
|
|
17
|
+
|
|
18
|
+
## Определение scope
|
|
19
|
+
|
|
20
|
+
| Аргумент | Scope | Описание |
|
|
21
|
+
|----------|-------|----------|
|
|
22
|
+
| `all` | Все задачи | Полная синхронизация |
|
|
23
|
+
| `milestone:X` | Milestone | Задачи конкретного milestone |
|
|
24
|
+
| `task:ID` | Одна задача | Конкретная задача по ID |
|
|
25
|
+
| _(пусто)_ | Все задачи | По умолчанию — all |
|
|
26
|
+
|
|
27
|
+
## Шаг 0. Проверка доступности
|
|
28
|
+
|
|
29
|
+
1. Проверь наличие `dev-infra/config/linear-mapping.json`
|
|
30
|
+
2. Если нет — сообщи: «Конфигурация Linear не найдена. Запусти `agent-forge init` и заполни `dev-infra/config/linear-mapping.json`.»
|
|
31
|
+
3. Прочитай маппинг — проверь что team и project заполнены (не placeholder)
|
|
32
|
+
|
|
33
|
+
## Шаг 1. Загрузка данных
|
|
34
|
+
|
|
35
|
+
1. Прочитай `dev-infra/tasks/tasks.json`
|
|
36
|
+
2. Прочитай `dev-infra/config/linear-mapping.json`
|
|
37
|
+
3. Отфильтруй задачи по scope
|
|
38
|
+
|
|
39
|
+
## Шаг 2. Первый проход — создание/обновление issues
|
|
40
|
+
|
|
41
|
+
Для каждой задачи:
|
|
42
|
+
|
|
43
|
+
1. **Если есть `linear_id`** — обновить существующий issue:
|
|
44
|
+
- Используй Linear MCP `save_issue` с id = linear_id
|
|
45
|
+
- Обнови: title, description, state, priority, assignee, labels, dueDate
|
|
46
|
+
|
|
47
|
+
2. **Если нет `linear_id`** — создать новый issue:
|
|
48
|
+
- Используй Linear MCP `save_issue` без id
|
|
49
|
+
- Маппинг полей по linear-mapping.json:
|
|
50
|
+
- title = task.title
|
|
51
|
+
- description = сформировать из task.description + acceptance_criteria + tdd_anchors
|
|
52
|
+
- state = status_map[task.status]
|
|
53
|
+
- priority = priority_map[task.priority]
|
|
54
|
+
- assigneeId = assignee_map[task.assignee] (если есть)
|
|
55
|
+
- labelIds = labels[task.type] (если есть)
|
|
56
|
+
- dueDate = task.deadline (если есть)
|
|
57
|
+
- teamId = linear.team
|
|
58
|
+
- projectId = linear.project
|
|
59
|
+
- **Сохрани `linear_id` обратно в tasks.json**
|
|
60
|
+
|
|
61
|
+
## Шаг 3. Второй проход — зависимости
|
|
62
|
+
|
|
63
|
+
Для каждой задачи с `dependencies`:
|
|
64
|
+
- Если все зависимости имеют `linear_id`:
|
|
65
|
+
- Установи `blockedBy` через Linear MCP
|
|
66
|
+
|
|
67
|
+
## Шаг 4. Отчёт
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
## Linear Sync Report
|
|
71
|
+
|
|
72
|
+
| Метрика | Значение |
|
|
73
|
+
|---------|----------|
|
|
74
|
+
| Создано | N |
|
|
75
|
+
| Обновлено | M |
|
|
76
|
+
| Пропущено | K |
|
|
77
|
+
| Warnings | W |
|
|
78
|
+
|
|
79
|
+
### Warnings (если есть)
|
|
80
|
+
- [task_id]: [причина]
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Error Handling
|
|
84
|
+
|
|
85
|
+
- Linear MCP недоступен → сообщить пользователю, прервать
|
|
86
|
+
- Ошибка на одном issue → логировать warning, продолжить остальные
|
|
87
|
+
- Маппинг неполный (нет status/priority) → использовать default, логировать warning
|