@alxyrgin/agent-forge 1.0.0 → 3.0.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.
Files changed (64) hide show
  1. package/README.md +104 -51
  2. package/dist/index.js +194 -51
  3. package/dist/index.js.map +1 -1
  4. package/package.json +12 -2
  5. package/templates/agents/documentation/gatekeeper.md.ejs +83 -0
  6. package/templates/agents/documentation/librarian.md.ejs +80 -0
  7. package/templates/agents/documentation/verifier.md.ejs +92 -0
  8. package/templates/agents/documentation/writer.md.ejs +189 -0
  9. package/templates/agents/pipeline/analyst.md.ejs +65 -0
  10. package/templates/agents/{core → pipeline}/architect.md.ejs +38 -1
  11. package/templates/agents/pipeline/developer.md.ejs +75 -0
  12. package/templates/agents/pipeline/inspector.md.ejs +123 -0
  13. package/templates/agents/pipeline/planner.md.ejs +211 -0
  14. package/templates/agents/pipeline/reviewer.md.ejs +158 -0
  15. package/templates/agents/pipeline/skeptic.md.ejs +105 -0
  16. package/templates/agents/pipeline/tester.md.ejs +134 -0
  17. package/templates/agents/planning/decomposer.md.ejs +103 -0
  18. package/templates/agents/planning/interviewer.md.ejs +104 -0
  19. package/templates/agents/planning/researcher.md.ejs +96 -0
  20. package/templates/agents/planning/validator.md.ejs +97 -0
  21. package/templates/agents/security/auditor.md.ejs +105 -0
  22. package/templates/agents/security/deployer.md.ejs +81 -0
  23. package/templates/agents/security/prompter.md.ejs +87 -0
  24. package/templates/agents/security/scaffolder.md.ejs +75 -0
  25. package/templates/hooks/protect-docs.sh.ejs +25 -0
  26. package/templates/memory/checkpoint.yml.ejs +21 -0
  27. package/templates/memory/tech-debt.md.ejs +9 -1
  28. package/templates/root/CLAUDE.md.ejs +228 -30
  29. package/templates/root/settings.json.ejs +15 -1
  30. package/templates/rules/agent-output-format.md.ejs +80 -0
  31. package/templates/rules/context-loading.md.ejs +70 -0
  32. package/templates/rules/development-cycle.md.ejs +163 -29
  33. package/templates/rules/quality-gates.md.ejs +80 -0
  34. package/templates/rules/rollback-protocol.md.ejs +60 -0
  35. package/templates/rules/shared-resources.md.ejs +73 -0
  36. package/templates/skills/core/code/SKILL.md.ejs +85 -0
  37. package/templates/skills/core/complete-task/SKILL.md.ejs +22 -9
  38. package/templates/skills/core/done/SKILL.md.ejs +66 -0
  39. package/templates/skills/core/end-session/SKILL.md.ejs +14 -6
  40. package/templates/skills/core/review/SKILL.md.ejs +1 -1
  41. package/templates/skills/core/start-session/SKILL.md.ejs +73 -10
  42. package/templates/skills/core/take-task/SKILL.md.ejs +279 -30
  43. package/templates/skills/core/test/SKILL.md.ejs +200 -0
  44. package/templates/skills/extra/audit-wave/SKILL.md.ejs +58 -0
  45. package/templates/skills/extra/dashboard/SKILL.md.ejs +64 -0
  46. package/templates/skills/extra/decompose/SKILL.md.ejs +72 -0
  47. package/templates/skills/extra/feature/SKILL.md.ejs +83 -0
  48. package/templates/skills/extra/interview/SKILL.md.ejs +66 -0
  49. package/templates/skills/extra/prompts/SKILL.md.ejs +65 -0
  50. package/templates/skills/extra/security/SKILL.md.ejs +77 -0
  51. package/templates/skills/extra/skill-master/SKILL.md.ejs +51 -0
  52. package/templates/skills/extra/spec/SKILL.md.ejs +111 -0
  53. package/templates/skills/extra/techspec/SKILL.md.ejs +97 -0
  54. package/templates/skills/extra/write-report/SKILL.md.ejs +26 -0
  55. package/templates/agents/core/analyst.md.ejs +0 -56
  56. package/templates/agents/core/developer.md.ejs +0 -54
  57. package/templates/agents/core/doc-writer.md.ejs +0 -50
  58. package/templates/agents/core/progress-tracker.md.ejs +0 -56
  59. package/templates/agents/core/reviewer.md.ejs +0 -52
  60. package/templates/agents/core/security-auditor.md.ejs +0 -51
  61. package/templates/agents/core/unit-tester.md.ejs +0 -56
  62. package/templates/agents/extra/acceptance-tester.md.ejs +0 -48
  63. package/templates/agents/extra/integration-tester.md.ejs +0 -49
  64. 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"],"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"]}
package/package.json CHANGED
@@ -1,7 +1,11 @@
1
1
  {
2
2
  "name": "@alxyrgin/agent-forge",
3
- "version": "1.0.0",
3
+ "version": "3.0.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
+ - Не запускать деструктивные команды