drm-core 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/cli/index.js +396 -201
  2. package/package.json +1 -1
  3. package/scaffold/.drm-core/checklists/campanha-pre-launch.md +49 -0
  4. package/scaffold/.drm-core/checklists/compliance-google.md +46 -0
  5. package/scaffold/.drm-core/checklists/compliance-meta.md +49 -0
  6. package/scaffold/.drm-core/checklists/compliance-tiktok.md +46 -0
  7. package/scaffold/.drm-core/checklists/compliance-vsl.md +48 -0
  8. package/scaffold/.drm-core/checklists/copy-quality-gate.md +55 -0
  9. package/scaffold/.drm-core/checklists/funil-pre-launch.md +66 -0
  10. package/scaffold/.drm-core/checklists/whatsapp-compliance.md +49 -0
  11. package/scaffold/.drm-core/data/agent-config.yaml +220 -0
  12. package/scaffold/.drm-core/data/workflow-chains.yaml +374 -0
  13. package/scaffold/.drm-core/tasks/analise/diagnostico-funil.md +314 -0
  14. package/scaffold/.drm-core/tasks/compliance/revisar-ad-meta.md +242 -0
  15. package/scaffold/.drm-core/tasks/copy/escrever-ad-meta.md +191 -0
  16. package/scaffold/.drm-core/tasks/copy/escrever-email-sequence.md +237 -0
  17. package/scaffold/.drm-core/tasks/copy/escrever-msgs-whatsapp.md +220 -0
  18. package/scaffold/.drm-core/tasks/copy/escrever-pagina-vendas.md +276 -0
  19. package/scaffold/.drm-core/tasks/copy/escrever-vsl-full.md +235 -0
  20. package/scaffold/.drm-core/tasks/direcao-criativa/criar-conceito.md +249 -0
  21. package/scaffold/.drm-core/tasks/direcao-criativa/validar-criativo.md +202 -0
  22. package/scaffold/.drm-core/tasks/estrategia/criar-briefing.md +274 -0
  23. package/scaffold/.drm-core/tasks/estrategia/pesquisa-mercado.md +200 -0
  24. package/scaffold/.drm-core/tasks/funil/arquitetar-funil-vsl.md +228 -0
  25. package/scaffold/.drm-core/tasks/funil/fluxo-whatsapp-backend.md +291 -0
  26. package/scaffold/.drm-core/tasks/trafego/escalar-campanha.md +256 -0
  27. package/scaffold/.drm-core/tasks/trafego/montar-campanha-meta.md +303 -0
  28. package/scaffold/.drm-core/templates/ad-meta-template.md +391 -0
  29. package/scaffold/.drm-core/templates/avatar-template.md +468 -0
  30. package/scaffold/.drm-core/templates/briefing-estrategico-template.md +462 -0
  31. package/scaffold/.drm-core/templates/compliance-report-template.md +86 -0
  32. package/scaffold/.drm-core/templates/estrutura-campanha-template.md +492 -0
  33. package/scaffold/.drm-core/templates/funil-vsl-template.md +470 -0
  34. package/scaffold/.drm-core/templates/msgs-whatsapp-template.md +516 -0
  35. package/scaffold/.drm-core/templates/pagina-vendas-template.md +517 -0
  36. package/scaffold/.drm-core/templates/relatorio-template.md +313 -0
  37. package/scaffold/.drm-core/templates/vsl-curta-template.md +341 -0
  38. package/scaffold/.drm-core/templates/vsl-full-template.md +780 -0
  39. package/scaffold/.drm-core/templates/vsl-mini-template.md +360 -0
  40. package/scaffold/.drm-core/workflows/backend-whatsapp.yaml +395 -0
  41. package/scaffold/.drm-core/workflows/campanha-trafego.yaml +465 -0
  42. package/scaffold/.drm-core/workflows/copy-review-loop.yaml +333 -0
  43. package/scaffold/.drm-core/workflows/funil-vsl-completo.yaml +544 -0
  44. package/scaffold/.drm-core/workflows/lancamento-produto.yaml +402 -0
  45. package/scaffold/.drm-core/workflows/microlead-pipeline.yaml +408 -0
  46. package/scaffold/.drm-core/workflows/otimizacao-cycle.yaml +394 -0
  47. package/scaffold/.drm-core/workflows/reativacao-cycle.yaml +468 -0
package/cli/index.js CHANGED
@@ -1,10 +1,6 @@
1
1
  /**
2
2
  * DRM CLI — Direct Response Marketing Framework
3
- *
4
- * Commands:
5
- * init <name> Create new DRM project
6
- * install Install DRM in existing project
7
- * doctor Diagnose DRM installation
3
+ * Orquestracao de agentes de IA para marketing de resposta direta
8
4
  */
9
5
 
10
6
  const { Command } = require('commander');
@@ -15,6 +11,185 @@ const chalk = require('chalk');
15
11
  const SCAFFOLD_DIR = path.join(__dirname, '..', 'scaffold');
16
12
  const VERSION = require('../package.json').version;
17
13
 
14
+ // ══════════════════════════════════════════════
15
+ // LOGO & BRANDING
16
+ // ══════════════════════════════════════════════
17
+
18
+ const LOGO = `
19
+ ${chalk.bold.cyan(' ╔══════════════════════════════════════════════════════╗')}
20
+ ${chalk.bold.cyan(' ║')} ${chalk.bold.cyan('║')}
21
+ ${chalk.bold.cyan(' ║')} ${chalk.bold.white('██████╗ ██████╗ ███╗ ███╗')} ${chalk.bold.cyan('║')}
22
+ ${chalk.bold.cyan(' ║')} ${chalk.bold.white('██╔══██╗ ██╔══██╗ ████╗ ████║')} ${chalk.bold.cyan('║')}
23
+ ${chalk.bold.cyan(' ║')} ${chalk.bold.white('██║ ██║ ██████╔╝ ██╔████╔██║')} ${chalk.bold.cyan('║')}
24
+ ${chalk.bold.cyan(' ║')} ${chalk.bold.white('██║ ██║ ██╔══██╗ ██║╚██╔╝██║')} ${chalk.bold.cyan('║')}
25
+ ${chalk.bold.cyan(' ║')} ${chalk.bold.white('██████╔╝ ██║ ██║ ██║ ╚═╝ ██║')} ${chalk.bold.cyan('║')}
26
+ ${chalk.bold.cyan(' ║')} ${chalk.bold.white('╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝')} ${chalk.bold.cyan('║')}
27
+ ${chalk.bold.cyan(' ║')} ${chalk.bold.cyan('║')}
28
+ ${chalk.bold.cyan(' ║')} ${chalk.gray('Direct Response Marketing Framework')} ${chalk.bold.cyan('║')}
29
+ ${chalk.bold.cyan(' ║')} ${chalk.gray(`v${VERSION} — Orquestracao de Agentes de IA`)} ${chalk.bold.cyan('║')}
30
+ ${chalk.bold.cyan(' ║')} ${chalk.bold.cyan('║')}
31
+ ${chalk.bold.cyan(' ╚══════════════════════════════════════════════════════╝')}
32
+ `;
33
+
34
+ const LOGO_MINI = `
35
+ ${chalk.bold.cyan(' ┌─────────────────────────────────────────┐')}
36
+ ${chalk.bold.cyan(' │')} ${chalk.bold.white('DRM')} ${chalk.gray('— Direct Response Marketing')} ${chalk.dim(`v${VERSION}`)} ${chalk.bold.cyan('│')}
37
+ ${chalk.bold.cyan(' └─────────────────────────────────────────┘')}
38
+ `;
39
+
40
+ const DIVIDER = chalk.gray(' ─────────────────────────────────────────');
41
+
42
+ // ══════════════════════════════════════════════
43
+ // AGENTS TABLE
44
+ // ══════════════════════════════════════════════
45
+
46
+ const AGENTS = [
47
+ { id: 'atena', icon: '⚔️', name: 'Atena', role: 'Estrategista / Master', refs: 'Kennedy, Abraham, Deiss' },
48
+ { id: 'apolo', icon: '✍️', name: 'Apolo', role: 'Copywriter', refs: 'Georgi, Schwartz, Halbert' },
49
+ { id: 'hermes', icon: '🚀', name: 'Hermes', role: 'Media Buyer', refs: 'Mandalia, Barbas, Shackelford' },
50
+ { id: 'zeus', icon: '👑', name: 'Zeus', role: 'Creative Director', refs: 'Ogilvy, Sullivan, Georgi' },
51
+ { id: 'cronos', icon: '📊', name: 'Cronos', role: 'Analista de Dados', refs: 'Hormozi, Sanocki, Chen' },
52
+ { id: 'hefesto', icon: '🔨', name: 'Hefesto', role: 'Editor de Video', refs: 'Agora, MindValley, Icaro' },
53
+ { id: 'afrodite', icon: '🎨', name: 'Afrodite', role: 'Designer', refs: 'Brunson, Wiebe, Laja' },
54
+ { id: 'temis', icon: '⚖️', name: 'Temis', role: 'Compliance', refs: 'Meta, Google, LGPD' },
55
+ { id: 'poseidon', icon: '🌊', name: 'Poseidon', role: 'Funnel Architect', refs: 'Brunson, Brown, Ladeira' },
56
+ ];
57
+
58
+ // ══════════════════════════════════════════════
59
+ // PROGRESS HELPERS
60
+ // ══════════════════════════════════════════════
61
+
62
+ function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
63
+
64
+ async function step(label, fn) {
65
+ const isTTY = process.stdout.isTTY;
66
+ if (isTTY) process.stdout.write(chalk.gray(` ◌ ${label}...`));
67
+ try {
68
+ await fn();
69
+ if (isTTY) {
70
+ process.stdout.clearLine(0);
71
+ process.stdout.cursorTo(0);
72
+ }
73
+ console.log(chalk.green(` ✓ ${label}`));
74
+ } catch (err) {
75
+ if (isTTY) {
76
+ process.stdout.clearLine(0);
77
+ process.stdout.cursorTo(0);
78
+ }
79
+ console.log(chalk.red(` ✗ ${label} — ${err.message}`));
80
+ throw err;
81
+ }
82
+ }
83
+
84
+ function printStats(targetDir) {
85
+ const counts = {
86
+ agents: 0, workflows: 0, templates: 0, checklists: 0, tasks: 0, rules: 0
87
+ };
88
+
89
+ const dirs = {
90
+ agents: '.drm-core/agents',
91
+ workflows: '.drm-core/workflows',
92
+ templates: '.drm-core/templates',
93
+ checklists: '.drm-core/checklists',
94
+ rules: '.drm-core/rules',
95
+ };
96
+
97
+ for (const [key, dir] of Object.entries(dirs)) {
98
+ const full = path.join(targetDir, dir);
99
+ if (fs.existsSync(full)) {
100
+ counts[key] = fs.readdirSync(full).filter(f => f.endsWith('.md') || f.endsWith('.yaml')).length;
101
+ }
102
+ }
103
+
104
+ // Count tasks recursively
105
+ const tasksDir = path.join(targetDir, '.drm-core/tasks');
106
+ if (fs.existsSync(tasksDir)) {
107
+ const countFiles = (dir) => {
108
+ let count = 0;
109
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
110
+ if (entry.isDirectory()) count += countFiles(path.join(dir, entry.name));
111
+ else if (entry.name.endsWith('.md')) count++;
112
+ }
113
+ return count;
114
+ };
115
+ counts.tasks = countFiles(tasksDir);
116
+ }
117
+
118
+ console.log('');
119
+ console.log(chalk.bold(' Framework Stats'));
120
+ console.log(DIVIDER);
121
+ console.log(` ${chalk.cyan('Agentes')} ${chalk.white(counts.agents)} ${chalk.gray('personas com referencias reais de DR')}`);
122
+ console.log(` ${chalk.cyan('Workflows')} ${chalk.white(counts.workflows)} ${chalk.gray('fluxos multi-agente declarativos')}`);
123
+ console.log(` ${chalk.cyan('Templates')} ${chalk.white(String(counts.templates).padStart(2))} ${chalk.gray('estruturas de entregaveis')}`);
124
+ console.log(` ${chalk.cyan('Tasks')} ${chalk.white(String(counts.tasks).padStart(2))} ${chalk.gray('definicoes step-by-step')}`);
125
+ console.log(` ${chalk.cyan('Checklists')} ${chalk.white(counts.checklists)} ${chalk.gray('quality gates e validacoes')}`);
126
+ console.log(` ${chalk.cyan('Rules')} ${chalk.white(counts.rules)} ${chalk.gray('regras de dominio')}`);
127
+ console.log(DIVIDER);
128
+ }
129
+
130
+ function printAgentsTable() {
131
+ console.log('');
132
+ console.log(chalk.bold(' Panteao de Agentes'));
133
+ console.log(DIVIDER);
134
+ console.log(chalk.gray(` ${'Agente'.padEnd(14)} ${'Papel'.padEnd(24)} Referencias`));
135
+ console.log(DIVIDER);
136
+ AGENTS.forEach(a => {
137
+ console.log(` ${chalk.cyan(`@${a.id}`.padEnd(14))} ${chalk.white(a.role.padEnd(24))} ${chalk.gray(a.refs)}`);
138
+ });
139
+ console.log(DIVIDER);
140
+ }
141
+
142
+ function printConstitution() {
143
+ console.log('');
144
+ console.log(chalk.bold(' Constitution'));
145
+ console.log(DIVIDER);
146
+ const articles = [
147
+ ['I', 'Conversao First', 'NON-NEGOTIABLE', chalk.red],
148
+ ['II', 'Agent Authority', 'NON-NEGOTIABLE', chalk.red],
149
+ ['III', 'Data-Driven', 'MUST', chalk.yellow],
150
+ ['IV', 'No Invention', 'MUST', chalk.yellow],
151
+ ['V', 'Compliance First', 'MUST', chalk.yellow],
152
+ ['VI', 'Copy is King', 'SHOULD', chalk.blue],
153
+ ];
154
+ articles.forEach(([num, name, sev, color]) => {
155
+ console.log(` ${chalk.gray(`Art. ${num}`.padEnd(10))} ${chalk.white(name.padEnd(20))} ${color(sev)}`);
156
+ });
157
+ console.log(DIVIDER);
158
+ }
159
+
160
+ function printFunnelDiagram() {
161
+ console.log('');
162
+ console.log(chalk.bold(' Modelo de Negocio'));
163
+ console.log(DIVIDER);
164
+ console.log(chalk.cyan(' Frontend (VSL)'));
165
+ console.log(chalk.white(' Ad → Microlead/VSL → LP → Checkout → Bump → Upsell → Downsell'));
166
+ console.log(chalk.gray(' │'));
167
+ console.log(chalk.gray(' ▼'));
168
+ console.log(chalk.cyan(' Backend (WhatsApp)'));
169
+ console.log(chalk.white(' API WhatsApp → Nutricao → Qualificacao → Oferta High-Ticket'));
170
+ console.log(DIVIDER);
171
+ }
172
+
173
+ function printNextSteps(name) {
174
+ console.log('');
175
+ console.log(chalk.bold(' Proximos Passos'));
176
+ console.log(DIVIDER);
177
+ if (name) {
178
+ console.log(chalk.white(` ${chalk.cyan('$')} cd ${name}`));
179
+ }
180
+ console.log(chalk.white(` ${chalk.cyan('$')} claude${' '.repeat(20)}${chalk.gray('# Abrir Claude Code')}`));
181
+ console.log(chalk.white(` ${chalk.cyan('$')} @atena${' '.repeat(20)}${chalk.gray('# Estrategista Master')}`));
182
+ console.log(chalk.white(` ${chalk.cyan('$')} /DRM:agents:apolo${' '.repeat(9)}${chalk.gray('# Copywriter')}`));
183
+ console.log(chalk.white(` ${chalk.cyan('$')} /DRM:agents:hermes${' '.repeat(8)}${chalk.gray('# Media Buyer')}`));
184
+ console.log('');
185
+ console.log(chalk.gray(' Tambem compativel com Gemini CLI e Antigravity.'));
186
+ console.log('');
187
+ }
188
+
189
+ // ══════════════════════════════════════════════
190
+ // COMMANDS
191
+ // ══════════════════════════════════════════════
192
+
18
193
  function createProgram() {
19
194
  const program = new Command();
20
195
 
@@ -27,50 +202,89 @@ function createProgram() {
27
202
  program
28
203
  .command('init <name>')
29
204
  .description('Criar novo projeto DRM')
30
- .action(async (name) => {
205
+ .option('--skip-git', 'Nao inicializar git')
206
+ .option('--minimal', 'Instalar apenas agentes e constitution')
207
+ .action(async (name, opts) => {
31
208
  const targetDir = path.resolve(process.cwd(), name);
32
209
 
33
210
  if (fs.existsSync(targetDir)) {
34
- console.error(chalk.red(`Erro: Diretorio "${name}" ja existe.`));
211
+ console.error(chalk.red(`\n Erro: Diretorio "${name}" ja existe.\n`));
35
212
  process.exit(1);
36
213
  }
37
214
 
38
- console.log(chalk.bold.cyan('\n⚔️ DRM — Direct Response Marketing Framework\n'));
39
- console.log(chalk.gray(`Criando projeto "${name}"...\n`));
215
+ console.log(LOGO);
216
+
217
+ console.log(chalk.bold(' Instalando Framework'));
218
+ console.log(DIVIDER);
40
219
 
41
- // Create directory
42
220
  fs.mkdirSync(targetDir, { recursive: true });
43
221
 
44
- // Copy scaffold
45
- await copyScaffold(targetDir);
222
+ await step('Constitution + Agentes (9 deuses)', async () => {
223
+ fs.copySync(path.join(SCAFFOLD_DIR, '.drm-core'), path.join(targetDir, '.drm-core'));
224
+ await sleep(100);
225
+ });
226
+
227
+ await step('Runtime config', async () => {
228
+ fs.copySync(path.join(SCAFFOLD_DIR, '.drm'), path.join(targetDir, '.drm'));
229
+ await sleep(50);
230
+ });
231
+
232
+ await step('Claude Code (commands + rules + settings)', async () => {
233
+ const srcClaude = path.join(SCAFFOLD_DIR, '.claude');
234
+ if (fs.existsSync(srcClaude)) {
235
+ fs.copySync(srcClaude, path.join(targetDir, '.claude'));
236
+ }
237
+ createClaudeMd(targetDir, name, true);
238
+ createSettingsJson(targetDir, true);
239
+ await sleep(50);
240
+ });
46
241
 
47
- // Create project package.json
242
+ await step('Gemini CLI + Antigravity', async () => {
243
+ const srcGemini = path.join(SCAFFOLD_DIR, '.gemini');
244
+ const srcAnti = path.join(SCAFFOLD_DIR, '.antigravity');
245
+ if (fs.existsSync(srcGemini)) fs.copySync(srcGemini, path.join(targetDir, '.gemini'));
246
+ if (fs.existsSync(srcAnti)) fs.copySync(srcAnti, path.join(targetDir, '.antigravity'));
247
+ await sleep(50);
248
+ });
249
+
250
+ await step('Estrutura de entregaveis (docs/)', async () => {
251
+ fs.copySync(path.join(SCAFFOLD_DIR, 'docs'), path.join(targetDir, 'docs'));
252
+ await sleep(50);
253
+ });
254
+
255
+ // package.json
48
256
  const projectPkg = {
49
257
  name: name,
50
258
  version: '1.0.0',
51
- description: '',
259
+ description: 'Projeto DRM — Direct Response Marketing',
52
260
  private: true,
53
- scripts: {},
54
- keywords: [],
261
+ scripts: { doctor: 'npx drm-core doctor' },
262
+ keywords: ['drm', 'direct-response-marketing'],
55
263
  license: 'UNLICENSED',
56
264
  type: 'commonjs'
57
265
  };
58
266
  fs.writeJsonSync(path.join(targetDir, 'package.json'), projectPkg, { spaces: 2 });
59
267
 
60
- // Init git
61
- try {
62
- const { execSync } = require('child_process');
63
- execSync('git init', { cwd: targetDir, stdio: 'ignore' });
64
- console.log(chalk.green(' Git inicializado'));
65
- } catch {
66
- console.log(chalk.yellow(' ⚠ Git nao encontrado — inicialize manualmente'));
268
+ // Git
269
+ if (!opts.skipGit) {
270
+ await step('Git init', async () => {
271
+ const { execSync } = require('child_process');
272
+ execSync('git init', { cwd: targetDir, stdio: 'ignore' });
273
+
274
+ // Create .gitignore
275
+ const gitignore = `node_modules/\n.env\n.drm/handoffs/\n.drm/cache/\n.DS_Store\n*.log\n`;
276
+ fs.writeFileSync(path.join(targetDir, '.gitignore'), gitignore);
277
+ await sleep(50);
278
+ });
67
279
  }
68
280
 
69
- // Create .claude/CLAUDE.md and settings.json
70
- createClaudeMd(targetDir, name);
71
- createSettingsJson(targetDir);
281
+ console.log(DIVIDER);
282
+ console.log(chalk.bold.green(`\n ✓ Projeto "${name}" criado com sucesso!`));
72
283
 
73
- console.log(chalk.bold.green('\n✓ Projeto DRM criado com sucesso!\n'));
284
+ printStats(targetDir);
285
+ printConstitution();
286
+ printAgentsTable();
287
+ printFunnelDiagram();
74
288
  printNextSteps(name);
75
289
  });
76
290
 
@@ -80,39 +294,78 @@ function createProgram() {
80
294
  .description('Instalar DRM em projeto existente')
81
295
  .action(async () => {
82
296
  const targetDir = process.cwd();
297
+ const projectName = path.basename(targetDir);
298
+
299
+ console.log(LOGO_MINI);
300
+
301
+ console.log(chalk.bold(' Instalando em projeto existente'));
302
+ console.log(DIVIDER);
83
303
 
84
- console.log(chalk.bold.cyan('\n⚔️ DRM Instalando em projeto existente\n'));
304
+ await step('Framework core (.drm-core/)', async () => {
305
+ fs.copySync(path.join(SCAFFOLD_DIR, '.drm-core'), path.join(targetDir, '.drm-core'), { overwrite: false });
306
+ await sleep(100);
307
+ });
308
+
309
+ await step('Runtime config (.drm/)', async () => {
310
+ const srcDrm = path.join(SCAFFOLD_DIR, '.drm');
311
+ const destDrm = path.join(targetDir, '.drm');
312
+ if (!fs.existsSync(destDrm)) fs.copySync(srcDrm, destDrm);
313
+ await sleep(50);
314
+ });
315
+
316
+ await step('Claude Code commands', async () => {
317
+ fs.copySync(
318
+ path.join(SCAFFOLD_DIR, '.claude/commands/DRM'),
319
+ path.join(targetDir, '.claude/commands/DRM'),
320
+ { overwrite: false }
321
+ );
322
+ await sleep(50);
323
+ });
324
+
325
+ await step('Claude Code rules', async () => {
326
+ const srcRules = path.join(SCAFFOLD_DIR, '.claude/rules');
327
+ if (fs.existsSync(srcRules)) {
328
+ fs.copySync(srcRules, path.join(targetDir, '.claude/rules'), { overwrite: false });
329
+ }
330
+ await sleep(50);
331
+ });
85
332
 
86
- // Copy scaffold (skip existing files)
87
- await copyScaffold(targetDir, { overwrite: false });
333
+ await step('Estrutura docs/', async () => {
334
+ fs.copySync(path.join(SCAFFOLD_DIR, 'docs'), path.join(targetDir, 'docs'), { overwrite: false });
335
+ await sleep(50);
336
+ });
88
337
 
89
- // Merge CLAUDE.md if exists
90
- const claudeMdPath = path.join(targetDir, '.claude', 'CLAUDE.md');
91
- if (fs.existsSync(claudeMdPath)) {
92
- const existing = fs.readFileSync(claudeMdPath, 'utf8');
93
- if (!existing.includes('DRM — Direct Response Marketing')) {
94
- const drmSection = getDrmClaudeMdSection();
95
- fs.appendFileSync(claudeMdPath, '\n\n' + drmSection);
96
- console.log(chalk.green(' ✓ CLAUDE.md atualizado (secao DRM adicionada)'));
338
+ // CLAUDE.md merge
339
+ await step('CLAUDE.md', async () => {
340
+ const claudeMdPath = path.join(targetDir, '.claude', 'CLAUDE.md');
341
+ if (fs.existsSync(claudeMdPath)) {
342
+ const existing = fs.readFileSync(claudeMdPath, 'utf8');
343
+ if (!existing.includes('DRM Direct Response Marketing')) {
344
+ fs.appendFileSync(claudeMdPath, '\n\n' + getDrmClaudeMdSection());
345
+ }
97
346
  } else {
98
- console.log(chalk.gray(' - CLAUDE.md ja contem secao DRM'));
347
+ createClaudeMd(targetDir, projectName, true);
99
348
  }
100
- } else {
101
- fs.ensureDirSync(path.join(targetDir, '.claude'));
102
- createClaudeMd(targetDir, path.basename(targetDir));
103
- }
349
+ await sleep(50);
350
+ });
104
351
 
105
- // Merge settings.json if exists
106
- const settingsPath = path.join(targetDir, '.claude', 'settings.json');
107
- if (fs.existsSync(settingsPath)) {
108
- mergeSettingsJson(settingsPath);
109
- console.log(chalk.green(' ✓ settings.json atualizado (deny/allow DRM adicionados)'));
110
- } else {
111
- createSettingsJson(targetDir);
112
- }
352
+ // settings.json merge
353
+ await step('settings.json', async () => {
354
+ const settingsPath = path.join(targetDir, '.claude', 'settings.json');
355
+ if (fs.existsSync(settingsPath)) {
356
+ mergeSettingsJson(settingsPath);
357
+ } else {
358
+ createSettingsJson(targetDir, true);
359
+ }
360
+ await sleep(50);
361
+ });
362
+
363
+ console.log(DIVIDER);
364
+ console.log(chalk.bold.green(`\n ✓ DRM instalado com sucesso!`));
113
365
 
114
- console.log(chalk.bold.green('\n✓ DRM instalado com sucesso!\n'));
115
- printAgents();
366
+ printStats(targetDir);
367
+ printAgentsTable();
368
+ printNextSteps(null);
116
369
  });
117
370
 
118
371
  // === doctor ===
@@ -122,88 +375,96 @@ function createProgram() {
122
375
  .action(() => {
123
376
  const targetDir = process.cwd();
124
377
 
125
- console.log(chalk.bold.cyan('\n⚔️ DRM Doctor — Diagnostico\n'));
378
+ console.log(LOGO_MINI);
379
+ console.log(chalk.bold(' Diagnostico'));
380
+ console.log(DIVIDER);
126
381
 
127
382
  const checks = [
128
- { name: '.drm-core/constitution.md', path: '.drm-core/constitution.md' },
129
- { name: '.drm-core/agents/ (9 agentes)', path: '.drm-core/agents/atena.md' },
130
- { name: '.drm-core/rules/ (4 rules)', path: '.drm-core/rules/copy-standards.md' },
131
- { name: '.drm/config.yaml', path: '.drm/config.yaml' },
132
- { name: '.claude/CLAUDE.md', path: '.claude/CLAUDE.md' },
133
- { name: '.claude/settings.json', path: '.claude/settings.json' },
134
- { name: '.claude/commands/DRM/', path: '.claude/commands/DRM/agents/atena.md' },
135
- { name: '.claude/rules/drm-*', path: '.claude/rules/drm-agent-authority.md' },
136
- { name: '.gemini/commands/', path: '.gemini/commands/drm-atena.toml', optional: true },
137
- { name: '.antigravity/rules/', path: '.antigravity/rules/agents/atena.md', optional: true },
383
+ { name: 'Constitution', path: '.drm-core/constitution.md' },
384
+ { name: 'Agentes (9)', path: '.drm-core/agents/atena.md' },
385
+ { name: 'Workflows (8)', path: '.drm-core/workflows/funil-vsl-completo.yaml' },
386
+ { name: 'Templates (12)', path: '.drm-core/templates/vsl-full-template.md' },
387
+ { name: 'Checklists (8)', path: '.drm-core/checklists/copy-quality-gate.md' },
388
+ { name: 'Tasks (15)', path: '.drm-core/tasks/copy/escrever-vsl-full.md' },
389
+ { name: 'Rules (4)', path: '.drm-core/rules/copy-standards.md' },
390
+ { name: 'Data files', path: '.drm-core/data/workflow-chains.yaml' },
391
+ { name: 'Runtime config', path: '.drm/config.yaml' },
392
+ { name: 'CLAUDE.md', path: '.claude/CLAUDE.md' },
393
+ { name: 'settings.json', path: '.claude/settings.json' },
394
+ { name: 'Slash commands (DRM)', path: '.claude/commands/DRM/agents/atena.md' },
395
+ { name: 'Governance rules', path: '.claude/rules/drm-agent-authority.md' },
396
+ { name: 'Gemini CLI', path: '.gemini/commands/drm-atena.toml', optional: true },
397
+ { name: 'Antigravity', path: '.antigravity/rules/agents/atena.md', optional: true },
138
398
  ];
139
399
 
140
- let passed = 0;
141
- let failed = 0;
142
- let optional = 0;
400
+ let passed = 0, failed = 0, skipped = 0;
143
401
 
144
- checks.forEach(({ name, path: checkPath, optional: isOptional }) => {
402
+ checks.forEach(({ name, path: checkPath, optional }) => {
145
403
  const fullPath = path.join(targetDir, checkPath);
146
404
  if (fs.existsSync(fullPath)) {
147
405
  console.log(chalk.green(` ✓ ${name}`));
148
406
  passed++;
149
- } else if (isOptional) {
150
- console.log(chalk.yellow(` ○ ${name} (opcional)`));
151
- optional++;
407
+ } else if (optional) {
408
+ console.log(chalk.gray(` ○ ${name} ${chalk.dim('(opcional)')}`));
409
+ skipped++;
152
410
  } else {
153
411
  console.log(chalk.red(` ✗ ${name}`));
154
412
  failed++;
155
413
  }
156
414
  });
157
415
 
158
- // Count agents
416
+ console.log(DIVIDER);
417
+
418
+ // Agent listing
159
419
  const agentsDir = path.join(targetDir, '.drm-core', 'agents');
160
420
  if (fs.existsSync(agentsDir)) {
161
- const agents = fs.readdirSync(agentsDir).filter(f => f.endsWith('.md'));
162
- console.log(chalk.gray(`\n Agentes: ${agents.map(a => a.replace('.md', '')).join(', ')}`));
421
+ const agentFiles = fs.readdirSync(agentsDir).filter(f => f.endsWith('.md'));
422
+ console.log('');
423
+ console.log(chalk.bold(' Agentes detectados'));
424
+ console.log(DIVIDER);
425
+ agentFiles.forEach(f => {
426
+ const id = f.replace('.md', '');
427
+ const agent = AGENTS.find(a => a.id === id);
428
+ if (agent) {
429
+ console.log(` ${agent.icon} ${chalk.cyan(`@${agent.id}`.padEnd(14))} ${chalk.white(agent.role)}`);
430
+ }
431
+ });
432
+ console.log(DIVIDER);
163
433
  }
164
434
 
165
- console.log(chalk.bold(`\n Resultado: ${passed} ok, ${failed} falha(s), ${optional} opcional(is)\n`));
166
-
167
- if (failed > 0) {
168
- console.log(chalk.yellow(' Execute "npx drm-core install" para corrigir.\n'));
169
- process.exit(1);
435
+ // Verdict
436
+ console.log('');
437
+ if (failed === 0) {
438
+ console.log(chalk.bold.green(` Framework DRM operacional (${passed}/${passed + failed} checks)`));
439
+ console.log(chalk.gray(' Use @atena para comecar.\n'));
170
440
  } else {
171
- console.log(chalk.green(' Framework DRM operacional. Use @atena para comecar.\n'));
441
+ console.log(chalk.bold.red(` ${failed} problema(s) encontrado(s)`));
442
+ console.log(chalk.yellow(' Execute "npx drm-core install" para corrigir.\n'));
443
+ process.exit(1);
172
444
  }
173
445
  });
174
446
 
175
- return program;
176
- }
177
-
178
- // === Helpers ===
179
-
180
- async function copyScaffold(targetDir, options = { overwrite: true }) {
181
- const items = [
182
- { src: '.drm-core', label: '.drm-core/ (framework)' },
183
- { src: '.drm', label: '.drm/ (runtime)' },
184
- { src: '.claude/commands/DRM', label: '.claude/commands/DRM/ (slash commands)' },
185
- { src: '.claude/rules', label: '.claude/rules/ (governance rules)', merge: true },
186
- { src: '.gemini', label: '.gemini/ (Gemini CLI)' },
187
- { src: '.antigravity', label: '.antigravity/ (Antigravity)' },
188
- { src: 'docs', label: 'docs/ (entregaveis)', merge: true },
189
- ];
190
-
191
- for (const item of items) {
192
- const srcPath = path.join(SCAFFOLD_DIR, item.src);
193
- const destPath = path.join(targetDir, item.src);
194
-
195
- if (!fs.existsSync(srcPath)) continue;
447
+ // === info ===
448
+ program
449
+ .command('info')
450
+ .description('Mostrar informacoes do framework')
451
+ .action(() => {
452
+ const targetDir = process.cwd();
196
453
 
197
- if (item.merge || options.overwrite) {
198
- fs.copySync(srcPath, destPath, { overwrite: options.overwrite });
199
- } else if (!fs.existsSync(destPath)) {
200
- fs.copySync(srcPath, destPath);
201
- }
454
+ console.log(LOGO);
455
+ printStats(targetDir);
456
+ printConstitution();
457
+ printAgentsTable();
458
+ printFunnelDiagram();
459
+ });
202
460
 
203
- console.log(chalk.green(` ${item.label}`));
204
- }
461
+ return program;
205
462
  }
206
463
 
464
+ // ══════════════════════════════════════════════
465
+ // HELPERS
466
+ // ══════════════════════════════════════════════
467
+
207
468
  function getDrmClaudeMdSection() {
208
469
  return `---
209
470
 
@@ -260,23 +521,17 @@ Frontend (VSL) -> Checkout -> Order Bump -> Upsell -> Downsell
260
521
  Backend (WhatsApp API) -> Nutricao -> Oferta High-Ticket -> Onboarding
261
522
 
262
523
  ---
263
- *DRM Framework v1.0*`;
524
+ *DRM Framework v${VERSION}*`;
264
525
  }
265
526
 
266
- function createClaudeMd(targetDir, projectName) {
527
+ function createClaudeMd(targetDir, projectName, silent) {
267
528
  const claudeDir = path.join(targetDir, '.claude');
268
529
  fs.ensureDirSync(claudeDir);
269
-
270
- const content = `# ${projectName}
271
-
272
- ${getDrmClaudeMdSection()}
273
- `;
274
-
530
+ const content = `# ${projectName}\n\n${getDrmClaudeMdSection()}\n`;
275
531
  fs.writeFileSync(path.join(claudeDir, 'CLAUDE.md'), content);
276
- console.log(chalk.green(' ✓ .claude/CLAUDE.md'));
277
532
  }
278
533
 
279
- function createSettingsJson(targetDir) {
534
+ function createSettingsJson(targetDir, silent) {
280
535
  const claudeDir = path.join(targetDir, '.claude');
281
536
  fs.ensureDirSync(claudeDir);
282
537
 
@@ -284,112 +539,52 @@ function createSettingsJson(targetDir) {
284
539
  language: 'portuguese',
285
540
  permissions: {
286
541
  deny: [
287
- 'Edit(.drm-core/constitution.md)',
288
- 'Write(.drm-core/constitution.md)',
289
- 'Edit(.drm-core/agents/**)',
290
- 'Write(.drm-core/agents/**)',
291
- 'Edit(.drm-core/tasks/**)',
292
- 'Write(.drm-core/tasks/**)',
293
- 'Edit(.drm-core/templates/**)',
294
- 'Write(.drm-core/templates/**)',
295
- 'Edit(.drm-core/workflows/**)',
296
- 'Write(.drm-core/workflows/**)',
297
- 'Edit(.drm-core/checklists/**)',
298
- 'Write(.drm-core/checklists/**)',
299
- 'Edit(.drm-core/rules/**)',
300
- 'Write(.drm-core/rules/**)'
542
+ 'Edit(.drm-core/constitution.md)', 'Write(.drm-core/constitution.md)',
543
+ 'Edit(.drm-core/agents/**)', 'Write(.drm-core/agents/**)',
544
+ 'Edit(.drm-core/tasks/**)', 'Write(.drm-core/tasks/**)',
545
+ 'Edit(.drm-core/templates/**)', 'Write(.drm-core/templates/**)',
546
+ 'Edit(.drm-core/workflows/**)', 'Write(.drm-core/workflows/**)',
547
+ 'Edit(.drm-core/checklists/**)', 'Write(.drm-core/checklists/**)',
548
+ 'Edit(.drm-core/rules/**)', 'Write(.drm-core/rules/**)'
301
549
  ],
302
550
  allow: [
303
551
  'Read(.drm-core/**)',
304
- 'Edit(.drm-core/data/**)',
305
- 'Write(.drm-core/data/**)',
306
- 'Edit(.drm/**)',
307
- 'Write(.drm/**)',
308
- 'Edit(docs/**)',
309
- 'Write(docs/**)'
552
+ 'Edit(.drm-core/data/**)', 'Write(.drm-core/data/**)',
553
+ 'Edit(.drm/**)', 'Write(.drm/**)',
554
+ 'Edit(docs/**)', 'Write(docs/**)'
310
555
  ]
311
556
  }
312
557
  };
313
558
 
314
559
  fs.writeJsonSync(path.join(claudeDir, 'settings.json'), settings, { spaces: 2 });
315
- console.log(chalk.green(' ✓ .claude/settings.json'));
316
560
  }
317
561
 
318
562
  function mergeSettingsJson(settingsPath) {
319
563
  const settings = fs.readJsonSync(settingsPath);
320
-
321
564
  if (!settings.permissions) settings.permissions = {};
322
565
  if (!settings.permissions.deny) settings.permissions.deny = [];
323
566
  if (!settings.permissions.allow) settings.permissions.allow = [];
324
567
 
325
- const drmDenyRules = [
326
- 'Edit(.drm-core/constitution.md)',
327
- 'Write(.drm-core/constitution.md)',
328
- 'Edit(.drm-core/agents/**)',
329
- 'Write(.drm-core/agents/**)',
330
- 'Edit(.drm-core/tasks/**)',
331
- 'Write(.drm-core/tasks/**)',
332
- 'Edit(.drm-core/templates/**)',
333
- 'Write(.drm-core/templates/**)',
334
- 'Edit(.drm-core/workflows/**)',
335
- 'Write(.drm-core/workflows/**)',
336
- 'Edit(.drm-core/checklists/**)',
337
- 'Write(.drm-core/checklists/**)',
338
- 'Edit(.drm-core/rules/**)',
339
- 'Write(.drm-core/rules/**)'
568
+ const drmDeny = [
569
+ 'Edit(.drm-core/constitution.md)', 'Write(.drm-core/constitution.md)',
570
+ 'Edit(.drm-core/agents/**)', 'Write(.drm-core/agents/**)',
571
+ 'Edit(.drm-core/tasks/**)', 'Write(.drm-core/tasks/**)',
572
+ 'Edit(.drm-core/templates/**)', 'Write(.drm-core/templates/**)',
573
+ 'Edit(.drm-core/workflows/**)', 'Write(.drm-core/workflows/**)',
574
+ 'Edit(.drm-core/checklists/**)', 'Write(.drm-core/checklists/**)',
575
+ 'Edit(.drm-core/rules/**)', 'Write(.drm-core/rules/**)'
340
576
  ];
341
-
342
- const drmAllowRules = [
343
- 'Read(.drm-core/**)',
344
- 'Edit(.drm-core/data/**)',
345
- 'Write(.drm-core/data/**)',
346
- 'Edit(.drm/**)',
347
- 'Write(.drm/**)'
577
+ const drmAllow = [
578
+ 'Read(.drm-core/**)', 'Edit(.drm-core/data/**)', 'Write(.drm-core/data/**)',
579
+ 'Edit(.drm/**)', 'Write(.drm/**)'
348
580
  ];
349
581
 
350
- drmDenyRules.forEach(rule => {
351
- if (!settings.permissions.deny.includes(rule)) {
352
- settings.permissions.deny.push(rule);
353
- }
354
- });
355
-
356
- drmAllowRules.forEach(rule => {
357
- if (!settings.permissions.allow.includes(rule)) {
358
- settings.permissions.allow.push(rule);
359
- }
360
- });
582
+ drmDeny.forEach(r => { if (!settings.permissions.deny.includes(r)) settings.permissions.deny.push(r); });
583
+ drmAllow.forEach(r => { if (!settings.permissions.allow.includes(r)) settings.permissions.allow.push(r); });
361
584
 
362
585
  fs.writeJsonSync(settingsPath, settings, { spaces: 2 });
363
586
  }
364
587
 
365
- function printNextSteps(name) {
366
- console.log(chalk.bold('Proximos passos:\n'));
367
- console.log(chalk.white(` cd ${name}`));
368
- console.log(chalk.white(' claude # Abrir Claude Code'));
369
- console.log(chalk.white(' @atena # Ativar estrategista'));
370
- console.log(chalk.white(' /DRM:agents:apolo # Ativar copywriter'));
371
- console.log(chalk.gray('\n Ou use Gemini CLI / Antigravity com os mesmos agentes.\n'));
372
- }
373
-
374
- function printAgents() {
375
- console.log(chalk.bold('Agentes disponiveis:\n'));
376
- const agents = [
377
- ['@atena', 'Estrategista / Master'],
378
- ['@apolo', 'Copywriter'],
379
- ['@hermes', 'Media Buyer'],
380
- ['@zeus', 'Creative Director'],
381
- ['@cronos', 'Analista de Dados'],
382
- ['@hefesto', 'Editor de Video'],
383
- ['@afrodite', 'Designer'],
384
- ['@temis', 'Compliance'],
385
- ['@poseidon', 'Funnel Architect'],
386
- ];
387
- agents.forEach(([name, role]) => {
388
- console.log(chalk.white(` ${chalk.cyan(name.padEnd(12))} ${role}`));
389
- });
390
- console.log('');
391
- }
392
-
393
588
  async function run(args = process.argv) {
394
589
  const program = createProgram();
395
590
  await program.parseAsync(args);