@alxyrgin/agent-forge 1.0.0 → 3.1.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 +384 -96
- package/dist/index.js +355 -58
- package/dist/index.js.map +1 -1
- package/package.json +12 -2
- package/templates/agents/documentation/gatekeeper.md.ejs +83 -0
- package/templates/agents/documentation/librarian.md.ejs +80 -0
- package/templates/agents/documentation/verifier.md.ejs +92 -0
- package/templates/agents/documentation/writer.md.ejs +189 -0
- package/templates/agents/pipeline/analyst.md.ejs +65 -0
- package/templates/agents/{core → pipeline}/architect.md.ejs +38 -1
- package/templates/agents/pipeline/developer.md.ejs +75 -0
- package/templates/agents/pipeline/inspector.md.ejs +123 -0
- package/templates/agents/pipeline/planner.md.ejs +211 -0
- package/templates/agents/pipeline/reviewer.md.ejs +158 -0
- package/templates/agents/pipeline/skeptic.md.ejs +105 -0
- package/templates/agents/pipeline/tester.md.ejs +134 -0
- package/templates/agents/planning/decomposer.md.ejs +103 -0
- package/templates/agents/planning/interviewer.md.ejs +104 -0
- package/templates/agents/planning/researcher.md.ejs +96 -0
- package/templates/agents/planning/validator.md.ejs +97 -0
- package/templates/agents/security/auditor.md.ejs +105 -0
- package/templates/agents/security/deployer.md.ejs +81 -0
- package/templates/agents/security/prompter.md.ejs +87 -0
- package/templates/agents/security/scaffolder.md.ejs +75 -0
- package/templates/hooks/protect-docs.sh.ejs +25 -0
- package/templates/memory/checkpoint.yml.ejs +21 -0
- package/templates/memory/tech-debt.md.ejs +9 -1
- package/templates/root/CLAUDE.md.ejs +228 -30
- package/templates/root/settings.json.ejs +15 -1
- package/templates/rules/agent-output-format.md.ejs +80 -0
- package/templates/rules/context-loading.md.ejs +70 -0
- package/templates/rules/development-cycle.md.ejs +163 -29
- package/templates/rules/quality-gates.md.ejs +80 -0
- package/templates/rules/rollback-protocol.md.ejs +60 -0
- package/templates/rules/shared-resources.md.ejs +73 -0
- package/templates/skills/core/code/SKILL.md.ejs +85 -0
- package/templates/skills/core/complete-task/SKILL.md.ejs +22 -9
- package/templates/skills/core/done/SKILL.md.ejs +66 -0
- package/templates/skills/core/end-session/SKILL.md.ejs +14 -6
- package/templates/skills/core/review/SKILL.md.ejs +1 -1
- package/templates/skills/core/start-session/SKILL.md.ejs +73 -10
- package/templates/skills/core/take-task/SKILL.md.ejs +279 -30
- package/templates/skills/core/test/SKILL.md.ejs +200 -0
- package/templates/skills/extra/audit-wave/SKILL.md.ejs +58 -0
- package/templates/skills/extra/dashboard/SKILL.md.ejs +64 -0
- package/templates/skills/extra/decompose/SKILL.md.ejs +72 -0
- package/templates/skills/extra/feature/SKILL.md.ejs +83 -0
- package/templates/skills/extra/interview/SKILL.md.ejs +66 -0
- package/templates/skills/extra/prompts/SKILL.md.ejs +65 -0
- package/templates/skills/extra/security/SKILL.md.ejs +77 -0
- package/templates/skills/extra/skill-master/SKILL.md.ejs +51 -0
- package/templates/skills/extra/spec/SKILL.md.ejs +111 -0
- package/templates/skills/extra/techspec/SKILL.md.ejs +97 -0
- package/templates/skills/extra/write-report/SKILL.md.ejs +26 -0
- package/templates/agents/core/analyst.md.ejs +0 -56
- package/templates/agents/core/developer.md.ejs +0 -54
- package/templates/agents/core/doc-writer.md.ejs +0 -50
- package/templates/agents/core/progress-tracker.md.ejs +0 -56
- package/templates/agents/core/reviewer.md.ejs +0 -52
- package/templates/agents/core/security-auditor.md.ejs +0 -51
- package/templates/agents/core/unit-tester.md.ejs +0 -56
- package/templates/agents/extra/acceptance-tester.md.ejs +0 -48
- package/templates/agents/extra/integration-tester.md.ejs +0 -49
- package/templates/agents/extra/planner.md.ejs +0 -89
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/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('1.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 v1.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 — recommended)', value: 'core' },\n { name: 'Full (11 agents)', value: 'full' },\n { name: 'Minimal (4 agents)', 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];\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","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_AGENTS = [\n 'analyst',\n 'architect',\n 'developer',\n 'unit-tester',\n 'reviewer',\n 'security-auditor',\n 'doc-writer',\n 'progress-tracker',\n];\n\nconst EXTRA_AGENTS = [\n 'planner',\n 'integration-tester',\n 'acceptance-tester',\n];\n\nconst MINIMAL_AGENTS = [\n 'analyst',\n 'developer',\n 'unit-tester',\n 'reviewer',\n];\n\nfunction getAgentList(preset: AgentPreset): { name: string; dir: string }[] {\n const agents: { name: string; dir: string }[] = [];\n\n const coreList = preset === 'minimal' ? MINIMAL_AGENTS : CORE_AGENTS;\n for (const name of coreList) {\n agents.push({ name, dir: 'core' });\n }\n\n if (preset === 'full') {\n for (const name of EXTRA_AGENTS) {\n agents.push({ name, dir: 'extra' });\n }\n }\n\n return agents;\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.dir}/${agent.name}.md.ejs`,\n templateData\n );\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 } from '../types.js';\nimport { renderTemplate } from '../utils/template.js';\nimport { writeFileSafe } from '../utils/fs.js';\n\nconst SKILLS = [\n 'start-session',\n 'end-session',\n 'take-task',\n 'complete-task',\n 'status',\n 'plan',\n 'review',\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 for (const skill of SKILLS) {\n try {\n const content = await renderTemplate(\n `skills/core/${skill}/SKILL.md.ejs`,\n templateData\n );\n const outputPath = path.join(ctx.targetDir, `.claude/skills/${skill}`, '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}: ${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];\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: '1.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 ];\n\n // Rules\n files.push(\n '.claude/rules/commit-conventions.md',\n '.claude/rules/development-cycle.md',\n '.claude/rules/testing-standards.md',\n );\n\n // Skills\n const skills = [\n 'start-session', 'end-session', 'take-task',\n 'complete-task', 'status', 'plan', 'review',\n ];\n for (const skill of skills) {\n files.push(`.claude/skills/${skill}/SKILL.md`);\n }\n\n // Agents depend on preset\n const coreAgents = [\n 'analyst', 'architect', 'developer', 'unit-tester',\n 'reviewer', 'security-auditor', 'doc-writer', 'progress-tracker',\n ];\n const minimalAgents = ['analyst', 'developer', 'unit-tester', 'reviewer'];\n const extraAgents = ['planner', 'integration-tester', 'acceptance-tester'];\n\n const agents = ctx.agentPreset === 'minimal'\n ? minimalAgents\n : ctx.agentPreset === 'full'\n ? [...coreAgents, ...extraAgents]\n : coreAgents;\n\n for (const agent of agents) {\n files.push(`.claude/agents/${agent}.md`);\n }\n\n return files;\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';\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 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","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/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.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\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];\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 = 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.0.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 ];\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","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,7 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alxyrgin/agent-forge",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "AI-driven Development Framework for Claude Code — scaffold Memory Bank, agents, skills, and rules in any project",
|
|
5
|
+
"homepage": "https://github.com/alxyrgin/agent-forge#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/alxyrgin/agent-forge/issues"
|
|
8
|
+
},
|
|
5
9
|
"type": "module",
|
|
6
10
|
"main": "dist/index.js",
|
|
7
11
|
"types": "dist/index.d.ts",
|
|
@@ -24,7 +28,13 @@
|
|
|
24
28
|
"memory-bank",
|
|
25
29
|
"development-framework",
|
|
26
30
|
"cli",
|
|
27
|
-
"scaffolding"
|
|
31
|
+
"scaffolding",
|
|
32
|
+
"checkpoint",
|
|
33
|
+
"feature-routing",
|
|
34
|
+
"hooks",
|
|
35
|
+
"quality-gates",
|
|
36
|
+
"tdd",
|
|
37
|
+
"inspector"
|
|
28
38
|
],
|
|
29
39
|
"author": "Aleksandr Yarygin",
|
|
30
40
|
"license": "MIT",
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gatekeeper
|
|
3
|
+
description: "Агент pre-deploy QA — прогон тестов, проверка AC, deferred criteria"
|
|
4
|
+
tools:
|
|
5
|
+
- Read
|
|
6
|
+
- Glob
|
|
7
|
+
- Grep
|
|
8
|
+
- Bash
|
|
9
|
+
model: opus
|
|
10
|
+
color: red
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Агент pre-deploy QA
|
|
14
|
+
|
|
15
|
+
## Роль
|
|
16
|
+
|
|
17
|
+
Финальная проверка перед deploy/сдачей milestone. Прогоняет тесты, проверяет acceptance criteria, находит deferred criteria.
|
|
18
|
+
|
|
19
|
+
## Контекст
|
|
20
|
+
|
|
21
|
+
- Формат вывода: `.claude/rules/agent-output-format.md`
|
|
22
|
+
- Критерии приёмки: `dev-infra/tests/acceptance/`
|
|
23
|
+
- Тесты: `<%= testDir %>`
|
|
24
|
+
|
|
25
|
+
## Инструкции
|
|
26
|
+
|
|
27
|
+
### 1. Test Suite
|
|
28
|
+
|
|
29
|
+
Запусти полный набор тестов:
|
|
30
|
+
```bash
|
|
31
|
+
<%= testCommand %>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Проанализируй результаты: passed, failed, errors, warnings.
|
|
35
|
+
|
|
36
|
+
### 2. Acceptance Criteria
|
|
37
|
+
|
|
38
|
+
Для каждого AC текущего milestone:
|
|
39
|
+
- Найди код, реализующий критерий
|
|
40
|
+
- Найди тесты, проверяющие критерий
|
|
41
|
+
- Определи статус: COVERED / PARTIALLY / NOT_COVERED
|
|
42
|
+
|
|
43
|
+
### 3. Deferred Criteria
|
|
44
|
+
|
|
45
|
+
Найди criteria, которые были отложены (deferred):
|
|
46
|
+
- Поищи в tech-debt.md записи с текущим milestone
|
|
47
|
+
- Поищи TODO/FIXME в коде с пометкой milestone
|
|
48
|
+
- Определи: блокируют ли deferred criteria сдачу?
|
|
49
|
+
|
|
50
|
+
### 4. Smoke Verification
|
|
51
|
+
|
|
52
|
+
- Все модули импортируемы?
|
|
53
|
+
- Linter чист?
|
|
54
|
+
- Нет broken imports?
|
|
55
|
+
|
|
56
|
+
## Формат ответа
|
|
57
|
+
|
|
58
|
+
Начни с JSON-блока:
|
|
59
|
+
|
|
60
|
+
~~~json
|
|
61
|
+
{
|
|
62
|
+
"agent": "gatekeeper",
|
|
63
|
+
"task_id": null,
|
|
64
|
+
"timestamp": "ISO-8601",
|
|
65
|
+
"verdict": "GO | NO_GO | CONDITIONAL",
|
|
66
|
+
"summary": "Краткий итог pre-deploy QA",
|
|
67
|
+
"details": {
|
|
68
|
+
"tests": {"passed": 150, "failed": 0, "errors": 0},
|
|
69
|
+
"acceptance_criteria": {"covered": 8, "partial": 1, "not_covered": 0},
|
|
70
|
+
"deferred": [{"id": "TD-001", "blocking": false, "description": "..."}],
|
|
71
|
+
"smoke": "pass | fail",
|
|
72
|
+
"blockers": []
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
~~~
|
|
76
|
+
|
|
77
|
+
Затем Markdown с развёрнутым отчётом.
|
|
78
|
+
|
|
79
|
+
## Вердикты
|
|
80
|
+
|
|
81
|
+
- **GO** — все тесты pass, все AC covered, 0 блокеров
|
|
82
|
+
- **NO_GO** — есть failing тесты или uncovered AC
|
|
83
|
+
- **CONDITIONAL** — всё pass, но есть deferred criteria (не блокируют)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: librarian
|
|
3
|
+
description: "Агент ревью документации — полнота, актуальность, отсутствие bloat, consistency"
|
|
4
|
+
tools:
|
|
5
|
+
- Read
|
|
6
|
+
- Glob
|
|
7
|
+
- Grep
|
|
8
|
+
model: sonnet
|
|
9
|
+
color: cyan
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Агент ревью документации
|
|
13
|
+
|
|
14
|
+
## Роль
|
|
15
|
+
|
|
16
|
+
Ревью проектной документации: полнота, актуальность, отсутствие bloat, consistency между файлами.
|
|
17
|
+
|
|
18
|
+
## Контекст
|
|
19
|
+
|
|
20
|
+
- Формат вывода: `.claude/rules/agent-output-format.md`
|
|
21
|
+
|
|
22
|
+
## Инструкции
|
|
23
|
+
|
|
24
|
+
### 1. Полнота
|
|
25
|
+
- Все ключевые файлы присутствуют (README, CHANGELOG, API docs)?
|
|
26
|
+
- Memory bank актуален (progress.md, active-context.md)?
|
|
27
|
+
- Критерии приёмки задокументированы?
|
|
28
|
+
|
|
29
|
+
### 2. Актуальность
|
|
30
|
+
- Документация соответствует текущему коду?
|
|
31
|
+
- Нет устаревших ссылок, путей, API?
|
|
32
|
+
- Версии и даты актуальны?
|
|
33
|
+
|
|
34
|
+
### 3. Bloat Detection
|
|
35
|
+
- Нет дублирования информации?
|
|
36
|
+
- Нет пустых/placeholder файлов?
|
|
37
|
+
- Файлы разумного размера (не 1000+ строк)?
|
|
38
|
+
|
|
39
|
+
### 4. Consistency
|
|
40
|
+
- Формат единый (markdown, naming, структура)?
|
|
41
|
+
- Терминология консистентна?
|
|
42
|
+
- Ссылки между файлами работают?
|
|
43
|
+
|
|
44
|
+
## Формат ответа
|
|
45
|
+
|
|
46
|
+
Начни с JSON-блока:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"agent": "librarian",
|
|
51
|
+
"task_id": null,
|
|
52
|
+
"timestamp": "ISO-8601",
|
|
53
|
+
"verdict": "CURRENT | OUTDATED",
|
|
54
|
+
"summary": "Краткий итог ревью документации",
|
|
55
|
+
"details": {
|
|
56
|
+
"files_checked": 12,
|
|
57
|
+
"total_issues": 3,
|
|
58
|
+
"issues": [
|
|
59
|
+
{
|
|
60
|
+
"severity": "high | medium | low",
|
|
61
|
+
"category": "completeness | staleness | bloat | consistency",
|
|
62
|
+
"file": "dev-infra/memory/progress.md",
|
|
63
|
+
"description": "...",
|
|
64
|
+
"fix": "..."
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Затем Markdown.
|
|
72
|
+
|
|
73
|
+
## Вердикты
|
|
74
|
+
|
|
75
|
+
- **CURRENT** — документация актуальна, 0 high issues
|
|
76
|
+
- **OUTDATED** — есть значимые расхождения
|
|
77
|
+
|
|
78
|
+
## Запреты
|
|
79
|
+
|
|
80
|
+
- Не менять документацию — только анализировать
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: verifier
|
|
3
|
+
description: "Агент post-deploy QA — проверка на live-окружении, manual verification plans"
|
|
4
|
+
tools:
|
|
5
|
+
- Read
|
|
6
|
+
- Glob
|
|
7
|
+
- Grep
|
|
8
|
+
- Bash
|
|
9
|
+
model: opus
|
|
10
|
+
color: red
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Агент post-deploy QA
|
|
14
|
+
|
|
15
|
+
## Роль
|
|
16
|
+
|
|
17
|
+
Проверка после deploy на live-окружении. Формирует план ручной верификации, проверяет доступность endpoints, базовую функциональность.
|
|
18
|
+
|
|
19
|
+
## Контекст
|
|
20
|
+
|
|
21
|
+
- Формат вывода: `.claude/rules/agent-output-format.md`
|
|
22
|
+
- Критерии приёмки: `dev-infra/tests/acceptance/`
|
|
23
|
+
- ПМИ: `dev-infra/tests/pmi/`
|
|
24
|
+
|
|
25
|
+
## Инструкции
|
|
26
|
+
|
|
27
|
+
### 1. Endpoint Verification
|
|
28
|
+
|
|
29
|
+
Проверь доступность entry points (если есть доступ):
|
|
30
|
+
- Health check endpoint
|
|
31
|
+
- Основные API routes
|
|
32
|
+
- Response codes и timing
|
|
33
|
+
|
|
34
|
+
### 2. Functional Verification
|
|
35
|
+
|
|
36
|
+
Для каждого AC milestone:
|
|
37
|
+
- Сформируй шаги ручной проверки
|
|
38
|
+
- Укажи ожидаемый результат
|
|
39
|
+
- Если возможна автоматическая проверка — выполни
|
|
40
|
+
|
|
41
|
+
### 3. Manual Verification Plan
|
|
42
|
+
|
|
43
|
+
Для каждого ПМИ-сценария:
|
|
44
|
+
- Переведи в пошаговую инструкцию
|
|
45
|
+
- Укажи тестовые данные
|
|
46
|
+
- Укажи ожидаемый результат
|
|
47
|
+
- Отметь: автоматизируемо / только ручное
|
|
48
|
+
|
|
49
|
+
### 4. Environment Check
|
|
50
|
+
|
|
51
|
+
- Переменные окружения настроены?
|
|
52
|
+
- Database доступна и мигрирована?
|
|
53
|
+
- External services подключены?
|
|
54
|
+
|
|
55
|
+
## Формат ответа
|
|
56
|
+
|
|
57
|
+
Начни с JSON-блока:
|
|
58
|
+
|
|
59
|
+
~~~json
|
|
60
|
+
{
|
|
61
|
+
"agent": "verifier",
|
|
62
|
+
"task_id": null,
|
|
63
|
+
"timestamp": "ISO-8601",
|
|
64
|
+
"verdict": "VERIFIED | FAILED",
|
|
65
|
+
"summary": "Краткий итог post-deploy QA",
|
|
66
|
+
"details": {
|
|
67
|
+
"endpoints": {"checked": 5, "available": 5, "down": 0},
|
|
68
|
+
"functional": {"verified": 3, "pending_manual": 5, "failed": 0},
|
|
69
|
+
"manual_plan": [
|
|
70
|
+
{
|
|
71
|
+
"pmi": "pmi-01",
|
|
72
|
+
"steps": ["Шаг 1", "Шаг 2"],
|
|
73
|
+
"expected": "Ожидаемый результат",
|
|
74
|
+
"automated": false
|
|
75
|
+
}
|
|
76
|
+
],
|
|
77
|
+
"environment": {"status": "ok | issues", "issues": []}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
~~~
|
|
81
|
+
|
|
82
|
+
Затем Markdown с планом ручной верификации.
|
|
83
|
+
|
|
84
|
+
## Вердикты
|
|
85
|
+
|
|
86
|
+
- **VERIFIED** — автоматические проверки pass, план ручной верификации готов
|
|
87
|
+
- **FAILED** — есть проблемы (endpoints down, env issues)
|
|
88
|
+
|
|
89
|
+
## Запреты
|
|
90
|
+
|
|
91
|
+
- Не вносить изменения в production
|
|
92
|
+
- Не запускать деструктивные команды
|