@damenor/agent-docs 0.1.1 → 0.4.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 (41) hide show
  1. package/README.md +65 -29
  2. package/dist/index.js +3834 -217
  3. package/package.json +14 -11
  4. package/templates/modules/agents/.agents/agents/doc-designer.md +39 -37
  5. package/templates/modules/agents/.agents/agents/doc-maintainer.md +35 -35
  6. package/templates/modules/agents/.agents/agents/doc-reviewer.md +55 -46
  7. package/templates/modules/agents/.agents/agents/doc-writer.md +34 -33
  8. package/templates/modules/agents/.agents/agents/reviewer.md +114 -100
  9. package/templates/modules/agents/.agents/skills/doc-design/SKILL.md +176 -174
  10. package/templates/modules/agents/.agents/skills/doc-design/references/design-system-format.md +241 -247
  11. package/templates/modules/agents/.agents/skills/doc-maintain/SKILL.md +205 -195
  12. package/templates/modules/agents/.agents/skills/doc-maintain/references/triggers.md +171 -165
  13. package/templates/modules/agents/.agents/skills/doc-review/SKILL.md +245 -240
  14. package/templates/modules/agents/.agents/skills/doc-review/references/health-checklist.md +115 -112
  15. package/templates/modules/agents/.agents/skills/doc-scaffold/SKILL.md +164 -157
  16. package/templates/modules/agents/.agents/skills/doc-scaffold/references/diataxis-quick-ref.md +110 -110
  17. package/templates/modules/agents/.agents/skills/doc-write/SKILL.md +240 -212
  18. package/templates/modules/agents/.agents/skills/doc-write/references/adr-format.md +99 -93
  19. package/templates/modules/agents/.agents/skills/doc-write/references/diataxis-patterns.md +221 -200
  20. package/templates/base/AGENTS.md +0 -177
  21. package/templates/base/CHANGELOG.md +0 -86
  22. package/templates/base/README.md +0 -110
  23. package/templates/base/docs/CONTEXT.md +0 -111
  24. package/templates/base/docs/README.md +0 -131
  25. package/templates/base/docs/adr/TEMPLATE.md +0 -83
  26. package/templates/modules/design/docs/DESIGN.md +0 -253
  27. package/templates/modules/explanation/docs/explanation/agent-flow.md +0 -15
  28. package/templates/modules/explanation/docs/explanation/architecture.md +0 -138
  29. package/templates/modules/guides/docs/guides/deployment.md +0 -189
  30. package/templates/modules/guides/docs/guides/runbooks/TEMPLATE.md +0 -86
  31. package/templates/modules/guides/docs/guides/troubleshooting.md +0 -65
  32. package/templates/modules/operations/docs/operations/README.md +0 -115
  33. package/templates/modules/product/docs/product/overview.md +0 -90
  34. package/templates/modules/product/docs/roadmap.md +0 -80
  35. package/templates/modules/reference/docs/reference/api.md +0 -131
  36. package/templates/modules/reference/docs/reference/code-style.md +0 -275
  37. package/templates/modules/reference/docs/reference/configuration.md +0 -117
  38. package/templates/modules/reference/docs/reference/infrastructure.md +0 -191
  39. package/templates/modules/tutorials/docs/tutorials/environment-setup.md +0 -212
  40. package/templates/modules/tutorials/docs/tutorials/first-task.md +0 -246
  41. package/templates/modules/tutorials/docs/tutorials/quick-start.md +0 -146
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
- import * as p from "@clack/prompts";
5
- import pc2 from "picocolors";
6
- import path4 from "path";
7
- import fs3 from "fs";
4
+ import * as p2 from "@clack/prompts";
5
+ import pc4 from "picocolors";
6
+ import path7 from "path";
7
+ import fs7 from "fs";
8
8
  import url from "url";
9
9
 
10
10
  // src/utils/colors.ts
@@ -55,34 +55,21 @@ var DOC_MODULES = [
55
55
  label: "Tutoriales",
56
56
  hint: "quick-start, environment, first-task",
57
57
  templateDir: "tutorials",
58
- files: [
59
- "docs/tutorials/quick-start.md",
60
- "docs/tutorials/environment-setup.md",
61
- "docs/tutorials/first-task.md"
62
- ]
58
+ files: ["docs/tutorials/quick-start.md", "docs/tutorials/environment-setup.md", "docs/tutorials/first-task.md"]
63
59
  },
64
60
  {
65
61
  value: "guides",
66
62
  label: "Gu\xEDas",
67
63
  hint: "deployment, troubleshooting, runbooks",
68
64
  templateDir: "guides",
69
- files: [
70
- "docs/guides/deployment.md",
71
- "docs/guides/troubleshooting.md",
72
- "docs/guides/runbooks/TEMPLATE.md"
73
- ]
65
+ files: ["docs/guides/deployment.md", "docs/guides/troubleshooting.md", "docs/guides/runbooks/TEMPLATE.md"]
74
66
  },
75
67
  {
76
68
  value: "reference",
77
69
  label: "Referencia",
78
70
  hint: "API, config, infra, code-style",
79
71
  templateDir: "reference",
80
- files: [
81
- "docs/reference/api.md",
82
- "docs/reference/configuration.md",
83
- "docs/reference/infrastructure.md",
84
- "docs/reference/code-style.md"
85
- ]
72
+ files: ["docs/reference/api.md", "docs/reference/configuration.md", "docs/reference/infrastructure.md", "docs/reference/code-style.md"]
86
73
  },
87
74
  {
88
75
  value: "explanation",
@@ -225,96 +212,3729 @@ function detectStack(targetDir) {
225
212
  }
226
213
  return null;
227
214
  }
228
- function detectNodeStack(packageJsonContent, dir) {
229
- const pkg2 = JSON.parse(packageJsonContent);
230
- const deps = { ...pkg2.dependencies, ...pkg2.devDependencies };
231
- let framework;
232
- if (deps["next"]) framework = `Next.js ${deps["next"].replace("^", "").replace("~", "")}`;
233
- else if (deps["nuxt"]) framework = `Nuxt ${deps["nuxt"].replace("^", "").replace("~", "")}`;
234
- else if (deps["astro"]) framework = `Astro ${deps["astro"].replace("^", "").replace("~", "")}`;
235
- else if (deps["svelte"] || deps["@sveltejs/kit"]) framework = "SvelteKit";
236
- else if (deps["react"]) framework = `React ${deps["react"].replace("^", "").replace("~", "")}`;
237
- else if (deps["vue"]) framework = `Vue ${deps["vue"].replace("^", "").replace("~", "")}`;
238
- else if (deps["express"]) framework = "Express";
239
- else if (deps["fastify"]) framework = "Fastify";
240
- else if (deps["hono"]) framework = "Hono";
241
- else if (deps["@nestjs/core"]) framework = "NestJS";
242
- let packageManager = "npm";
243
- if (fs.existsSync(path.join(dir, "pnpm-lock.yaml"))) packageManager = "pnpm";
244
- else if (fs.existsSync(path.join(dir, "yarn.lock"))) packageManager = "yarn";
245
- else if (fs.existsSync(path.join(dir, "bun.lockb"))) packageManager = "bun";
246
- const scripts = pkg2.scripts || {};
247
- const run = packageManager === "npm" ? "npm run" : packageManager;
248
- const hasTypeScript = deps["typescript"] || fs.existsSync(path.join(dir, "tsconfig.json"));
249
- return {
250
- language: hasTypeScript ? "TypeScript" : "JavaScript",
251
- framework,
252
- packageManager,
253
- devCommand: scripts.dev ? `${run} dev` : void 0,
254
- buildCommand: scripts.build ? `${run} build` : void 0,
255
- testCommand: scripts.test ? `${run} test` : void 0,
256
- lintCommand: scripts.lint ? `${run} lint` : void 0
257
- };
215
+ function detectNodeStack(packageJsonContent, dir) {
216
+ const pkg2 = JSON.parse(packageJsonContent);
217
+ const deps = { ...pkg2.dependencies, ...pkg2.devDependencies };
218
+ let framework;
219
+ if (deps["next"]) framework = `Next.js ${deps["next"].replace("^", "").replace("~", "")}`;
220
+ else if (deps["nuxt"]) framework = `Nuxt ${deps["nuxt"].replace("^", "").replace("~", "")}`;
221
+ else if (deps["astro"]) framework = `Astro ${deps["astro"].replace("^", "").replace("~", "")}`;
222
+ else if (deps["svelte"] || deps["@sveltejs/kit"]) framework = "SvelteKit";
223
+ else if (deps["react"]) framework = `React ${deps["react"].replace("^", "").replace("~", "")}`;
224
+ else if (deps["vue"]) framework = `Vue ${deps["vue"].replace("^", "").replace("~", "")}`;
225
+ else if (deps["express"]) framework = "Express";
226
+ else if (deps["fastify"]) framework = "Fastify";
227
+ else if (deps["hono"]) framework = "Hono";
228
+ else if (deps["@nestjs/core"]) framework = "NestJS";
229
+ let packageManager = "npm";
230
+ if (fs.existsSync(path.join(dir, "pnpm-lock.yaml"))) packageManager = "pnpm";
231
+ else if (fs.existsSync(path.join(dir, "yarn.lock"))) packageManager = "yarn";
232
+ else if (fs.existsSync(path.join(dir, "bun.lockb"))) packageManager = "bun";
233
+ const scripts = pkg2.scripts || {};
234
+ const run = packageManager === "npm" ? "npm run" : packageManager;
235
+ const hasTypeScript = deps["typescript"] || fs.existsSync(path.join(dir, "tsconfig.json"));
236
+ return {
237
+ language: hasTypeScript ? "TypeScript" : "JavaScript",
238
+ framework,
239
+ packageManager,
240
+ devCommand: scripts.dev ? `${run} dev` : void 0,
241
+ buildCommand: scripts.build ? `${run} build` : void 0,
242
+ testCommand: scripts.test ? `${run} test` : void 0,
243
+ lintCommand: scripts.lint ? `${run} lint` : void 0
244
+ };
245
+ }
246
+ function formatStack(stack) {
247
+ const parts = [stack.language];
248
+ if (stack.framework) parts.push(stack.framework);
249
+ if (stack.packageManager) parts.push(`(${stack.packageManager})`);
250
+ return parts.join(" + ");
251
+ }
252
+
253
+ // src/generator.ts
254
+ import path6 from "path";
255
+ import { fileURLToPath } from "url";
256
+ import fs6 from "fs";
257
+
258
+ // src/conflict-resolver.ts
259
+ import * as p from "@clack/prompts";
260
+ import pc3 from "picocolors";
261
+ import fs5 from "fs";
262
+ import path5 from "path";
263
+
264
+ // src/conflict-detector.ts
265
+ import fs2 from "fs";
266
+ import path2 from "path";
267
+ function detectConflicts(plannedFiles, targetDir) {
268
+ const entries = [];
269
+ for (const plannedFile of plannedFiles) {
270
+ const targetPath = path2.join(targetDir, plannedFile.relativePath);
271
+ const exists = fs2.existsSync(targetPath);
272
+ const status = exists ? "conflict" : "no-conflict";
273
+ entries.push({
274
+ plannedFile,
275
+ status,
276
+ resolution: "skip",
277
+ result: exists ? "skipped" : "created"
278
+ });
279
+ }
280
+ return entries;
281
+ }
282
+
283
+ // src/merge-agents.ts
284
+ var HEADING_RE = /^## (.+)$/gm;
285
+ function parseSections(content) {
286
+ const sections = [];
287
+ let preamble = "";
288
+ let match;
289
+ HEADING_RE.lastIndex = 0;
290
+ const headingMatches = [];
291
+ while ((match = HEADING_RE.exec(content)) !== null) {
292
+ headingMatches.push({ index: match.index, heading: match[1] });
293
+ }
294
+ if (headingMatches.length === 0) {
295
+ return { preamble: content, sections: [] };
296
+ }
297
+ preamble = content.slice(0, headingMatches[0].index).trimEnd();
298
+ for (let i = 0; i < headingMatches.length; i++) {
299
+ const current = headingMatches[i];
300
+ const next = headingMatches[i + 1];
301
+ const sectionContent = next ? content.slice(current.index, next.index) : content.slice(current.index);
302
+ sections.push({
303
+ heading: current.heading,
304
+ content: sectionContent.trimEnd()
305
+ });
306
+ }
307
+ return { preamble, sections };
308
+ }
309
+ function mergeAgentsMd(existingContent, templateContent) {
310
+ const existing = parseSections(existingContent);
311
+ const template = parseSections(templateContent);
312
+ const existingHeadings = new Set(existing.sections.map((s) => s.heading));
313
+ const resultParts = [existing.preamble, ""];
314
+ for (const section of existing.sections) {
315
+ resultParts.push(section.content);
316
+ }
317
+ for (const section of template.sections) {
318
+ if (!existingHeadings.has(section.heading)) {
319
+ resultParts.push(section.content);
320
+ }
321
+ }
322
+ return resultParts.join("\n\n").trim() + "\n";
323
+ }
324
+ function isAgentsMd(relativePath) {
325
+ return relativePath.toLowerCase().endsWith("agents.md");
326
+ }
327
+
328
+ // src/report.ts
329
+ import pc2 from "picocolors";
330
+ function groupByResult(entries) {
331
+ const groups = { created: [], overwritten: [], skipped: [], merged: [] };
332
+ for (const entry of entries) {
333
+ switch (entry.result) {
334
+ case "created":
335
+ groups.created.push(entry.plannedFile.relativePath);
336
+ break;
337
+ case "overwritten":
338
+ groups.overwritten.push(entry.plannedFile.relativePath);
339
+ break;
340
+ case "skipped":
341
+ groups.skipped.push(entry.plannedFile.relativePath);
342
+ break;
343
+ case "merged":
344
+ groups.merged.push(entry.plannedFile.relativePath);
345
+ break;
346
+ }
347
+ }
348
+ return groups;
349
+ }
350
+ function formatFileList(files, maxDisplay = 5) {
351
+ if (files.length === 0) return "";
352
+ const display = files.slice(0, maxDisplay);
353
+ const remaining = files.length - maxDisplay;
354
+ const suffix = remaining > 0 ? `, ... (+${remaining})` : "";
355
+ return display.join(", ") + suffix;
356
+ }
357
+ function printReport(entries) {
358
+ const groups = groupByResult(entries);
359
+ const rows = [];
360
+ const statusMap = [
361
+ { icon: "\u2705", label: "Created", files: groups.created, count: groups.created.length },
362
+ { icon: "\u{1F504}", label: "Overwritten", files: groups.overwritten, count: groups.overwritten.length },
363
+ { icon: "\u23ED\uFE0F", label: "Skipped", files: groups.skipped, count: groups.skipped.length },
364
+ { icon: "\u{1F500}", label: "Merged", files: groups.merged, count: groups.merged.length }
365
+ ];
366
+ rows.push(`
367
+ ${pc2.bold("\u{1F4CA} Report:")}
368
+ `);
369
+ rows.push(` ${pc2.dim("Status".padEnd(20))} ${pc2.dim("Count")}`);
370
+ rows.push(` ${pc2.dim("\u2500".repeat(20))} ${pc2.dim("\u2500".repeat(5))}`);
371
+ for (const { icon, label, files, count } of statusMap) {
372
+ if (count > 0) {
373
+ const fileList = formatFileList(files);
374
+ rows.push(` ${icon} ${pc2.bold(label.padEnd(14))} ${String(count).padStart(3)} ${pc2.dim(fileList)}`);
375
+ }
376
+ }
377
+ console.log(rows.join("\n"));
378
+ }
379
+ function printSkippedWarning(entries) {
380
+ const skipped = entries.filter((e) => e.result === "skipped");
381
+ if (skipped.length === 0) return;
382
+ const fileList = skipped.map((e) => ` - ${e.plannedFile.relativePath}`).join("\n");
383
+ console.log(
384
+ `
385
+ ${pc2.yellow(`${icons.warning} ${pc2.bold(`${skipped.length} archivo${skipped.length > 1 ? "s" : ""} saltado${skipped.length > 1 ? "s" : ""}`)} \u2014 tu documentaci\xF3n puede estar incompleta:`)}
386
+ ${pc2.yellow(fileList)}
387
+
388
+ ${pc2.dim("\u{1F4A1} Ejecuta de nuevo con ")}${pc2.cyan("--force")}${pc2.dim(' para sobrescribir, o elige "overwrite" para esos archivos.')}`
389
+ );
390
+ }
391
+ function printDryRunReport(entries) {
392
+ const conflicts = entries.filter((e) => e.status === "conflict");
393
+ const clean = entries.filter((e) => e.status === "no-conflict");
394
+ console.log(`
395
+ ${pc2.blue("\u2139 Dry run \u2014 no files will be written")}
396
+ `);
397
+ console.log(`${pc2.bold("\u{1F4CA} Would generate:")}
398
+ `);
399
+ if (clean.length > 0) {
400
+ const fileList = formatFileList(clean.map((e) => e.plannedFile.relativePath));
401
+ console.log(` \u2705 ${pc2.bold("Would create".padEnd(14))} ${String(clean.length).padStart(3)} ${pc2.dim(fileList)}`);
402
+ }
403
+ if (conflicts.length > 0) {
404
+ const fileList = formatFileList(conflicts.map((e) => e.plannedFile.relativePath));
405
+ console.log(` \u26A0\uFE0F ${pc2.yellow(pc2.bold("Conflict".padEnd(14)))} ${String(conflicts.length).padStart(3)} ${pc2.dim(fileList)}`);
406
+ }
407
+ console.log(`
408
+ ${pc2.dim("Run without --dry-run to execute.")}`);
409
+ }
410
+
411
+ // src/utils/fs.ts
412
+ import fs3 from "fs";
413
+ import path3 from "path";
414
+ function ensureDir(dirPath) {
415
+ if (!fs3.existsSync(dirPath)) {
416
+ fs3.mkdirSync(dirPath, { recursive: true });
417
+ }
418
+ }
419
+ function isDirEmpty(dirPath) {
420
+ if (!fs3.existsSync(dirPath)) return true;
421
+ const files = fs3.readdirSync(dirPath);
422
+ return files.length === 0 || files.length === 1 && files[0] === ".git";
423
+ }
424
+
425
+ // src/conditional.ts
426
+ import fs4 from "fs";
427
+ import path4 from "path";
428
+ var FRONTEND_FRAMEWORKS = ["next.js", "nuxt", "astro", "svelte", "sveltekit", "react", "vue", "angular", "solid", "qwik"];
429
+ var BACKEND_FRAMEWORKS = [
430
+ "express",
431
+ "fastify",
432
+ "hono",
433
+ "nestjs",
434
+ "nest",
435
+ "django",
436
+ "fastapi",
437
+ "flask",
438
+ "gin",
439
+ "echo",
440
+ "fiber",
441
+ "actix",
442
+ "axum",
443
+ "rocket",
444
+ "spring boot"
445
+ ];
446
+ var DB_FILE_PATTERNS = [
447
+ "prisma/schema.prisma",
448
+ "drizzle.config.ts",
449
+ "drizzle.config.js",
450
+ "typeorm.config.ts",
451
+ "knexfile.ts",
452
+ "knexfile.js",
453
+ "sequelize.config.js",
454
+ "alembic.ini",
455
+ "migrations"
456
+ ];
457
+ function buildConditionContext(stack, targetDir) {
458
+ const lang = (stack?.language || "").toLowerCase();
459
+ const fw = (stack?.framework || "").toLowerCase();
460
+ const isNode = lang.includes("javascript") || lang.includes("typescript");
461
+ const isPython = lang.includes("python");
462
+ const isGo = lang.includes("go");
463
+ const isRust = lang.includes("rust");
464
+ const isJava = lang.includes("java") || lang.includes("kotlin");
465
+ const hasFrontend = FRONTEND_FRAMEWORKS.some((f) => fw.includes(f));
466
+ const hasBackend = BACKEND_FRAMEWORKS.some((f) => fw.includes(f));
467
+ const hasTypeScript = lang.includes("typescript");
468
+ let hasDatabase = false;
469
+ if (targetDir) {
470
+ hasDatabase = DB_FILE_PATTERNS.some((pattern) => {
471
+ const fullPath = path4.join(targetDir, pattern);
472
+ return fs4.existsSync(fullPath);
473
+ });
474
+ if (!hasDatabase && (fw.includes("django") || fw.includes("spring"))) {
475
+ hasDatabase = true;
476
+ }
477
+ }
478
+ let hasDocker = false;
479
+ if (targetDir) {
480
+ hasDocker = fs4.existsSync(path4.join(targetDir, "Dockerfile")) || fs4.existsSync(path4.join(targetDir, "docker-compose.yml")) || fs4.existsSync(path4.join(targetDir, "docker-compose.yaml"));
481
+ }
482
+ let hasCI = false;
483
+ if (targetDir) {
484
+ hasCI = fs4.existsSync(path4.join(targetDir, ".github", "workflows")) || fs4.existsSync(path4.join(targetDir, ".gitlab-ci.yml")) || fs4.existsSync(path4.join(targetDir, ".circleci"));
485
+ }
486
+ let hasMonorepo = false;
487
+ if (targetDir) {
488
+ const pkgPath = path4.join(targetDir, "package.json");
489
+ if (fs4.existsSync(pkgPath)) {
490
+ try {
491
+ const pkg2 = JSON.parse(fs4.readFileSync(pkgPath, "utf-8"));
492
+ hasMonorepo = !!(pkg2.workspaces || pkg2.pnpm?.workspaces);
493
+ } catch {
494
+ }
495
+ }
496
+ if (!hasMonorepo) {
497
+ hasMonorepo = fs4.existsSync(path4.join(targetDir, "packages"));
498
+ }
499
+ }
500
+ return {
501
+ hasDatabase,
502
+ hasFrontend,
503
+ hasBackend,
504
+ hasDocker,
505
+ hasCI,
506
+ isNode,
507
+ isPython,
508
+ isGo,
509
+ isRust,
510
+ isJava,
511
+ hasMonorepo,
512
+ hasTypeScript
513
+ };
514
+ }
515
+ function renderConditionalBlocks(content, ctx) {
516
+ const blockRegex = /\{\{#if\s+(\w+)\}\}([\s\S]*?)\{\{\/if\s+\1\}\}/g;
517
+ let result = content;
518
+ let prevResult = "";
519
+ let iterations = 0;
520
+ const MAX_ITERATIONS = 10;
521
+ while (result !== prevResult && iterations < MAX_ITERATIONS) {
522
+ prevResult = result;
523
+ result = result.replace(blockRegex, (_match, condition, block) => {
524
+ const value = ctx[condition];
525
+ return value ? block : "";
526
+ });
527
+ iterations++;
528
+ }
529
+ result = result.replace(/\n{3,}/g, "\n\n");
530
+ return result;
531
+ }
532
+
533
+ // src/conflict-resolver.ts
534
+ async function resolveConflicts(entries, options) {
535
+ const conflicts = entries.filter((e) => e.status === "conflict");
536
+ if (options.dryRun) {
537
+ printDryRunReport(entries);
538
+ return entries;
539
+ }
540
+ if (options.force) {
541
+ for (const entry of entries) {
542
+ if (entry.status === "conflict") {
543
+ entry.resolution = "overwrite";
544
+ entry.result = "overwritten";
545
+ } else {
546
+ entry.resolution = "skip";
547
+ entry.result = "created";
548
+ }
549
+ }
550
+ return entries;
551
+ }
552
+ if (conflicts.length === 0) {
553
+ for (const entry of entries) {
554
+ entry.resolution = "skip";
555
+ entry.result = "created";
556
+ }
557
+ return entries;
558
+ }
559
+ if (!isInteractive()) {
560
+ const skipped = conflicts.map((e) => e.plannedFile.relativePath).join(", ");
561
+ console.log(`${icons.warning} ${pc3.yellow(`${conflicts.length} file(s) conflict \u2014 skipping (non-interactive): ${skipped}`)}`);
562
+ for (const entry of entries) {
563
+ if (entry.status === "conflict") {
564
+ entry.resolution = "skip";
565
+ entry.result = "skipped";
566
+ }
567
+ }
568
+ return entries;
569
+ }
570
+ console.log(`
571
+ ${icons.warning} ${pc3.yellow(pc3.bold(`${conflicts.length} conflicting file${conflicts.length > 1 ? "s" : ""} detected:`))}
572
+ `);
573
+ const MAX_DISPLAY = 10;
574
+ const displayedConflicts = conflicts.slice(0, MAX_DISPLAY);
575
+ const remaining = conflicts.length - MAX_DISPLAY;
576
+ for (const entry of displayedConflicts) {
577
+ const isAgent = isAgentsMd(entry.plannedFile.relativePath);
578
+ const actionHint = isAgent ? `${pc3.dim("(merge recommended)")}` : "";
579
+ console.log(` ${icons.docs} ${brand.path(entry.plannedFile.relativePath)} ${actionHint}`);
580
+ }
581
+ if (remaining > 0) {
582
+ console.log(` ${pc3.dim(`...and ${remaining} more`)}`);
583
+ }
584
+ console.log("");
585
+ const defaultAction = await p.select({
586
+ message: "Default action for conflicting files",
587
+ options: [
588
+ { value: "skip", label: "Skip", hint: "keep existing files (recommended)" },
589
+ { value: "overwrite", label: "Overwrite", hint: "replace all with template content" }
590
+ ]
591
+ });
592
+ if (p.isCancel(defaultAction)) {
593
+ p.cancel("Operation cancelled.");
594
+ process.exit(0);
595
+ }
596
+ let perFileOverride = false;
597
+ if (conflicts.length <= 10) {
598
+ perFileOverride = true;
599
+ } else {
600
+ const wantsOverride = await p.confirm({
601
+ message: `You have ${conflicts.length} conflicts. Override per file?`,
602
+ initialValue: false
603
+ });
604
+ if (!p.isCancel(wantsOverride)) {
605
+ perFileOverride = wantsOverride;
606
+ }
607
+ }
608
+ for (const entry of conflicts) {
609
+ let resolution = defaultAction;
610
+ if (perFileOverride) {
611
+ const isAgent = isAgentsMd(entry.plannedFile.relativePath);
612
+ const options2 = [
613
+ { value: "skip", label: "Skip", hint: "keep existing" },
614
+ { value: "overwrite", label: "Overwrite", hint: "replace" }
615
+ ];
616
+ if (isAgent) {
617
+ options2.push({ value: "merge", label: "Merge", hint: "add missing sections" });
618
+ }
619
+ const picked = await p.select({
620
+ message: `${entry.plannedFile.relativePath}`,
621
+ options: options2,
622
+ initialValue: isAgent ? "merge" : "skip"
623
+ });
624
+ if (p.isCancel(picked)) {
625
+ p.cancel("Operation cancelled.");
626
+ process.exit(0);
627
+ }
628
+ resolution = picked;
629
+ }
630
+ entry.resolution = resolution;
631
+ }
632
+ return entries;
633
+ }
634
+ function executePlan(entries, options) {
635
+ for (const entry of entries) {
636
+ const targetPath = path5.join(options.targetDir, entry.plannedFile.relativePath);
637
+ switch (entry.resolution) {
638
+ case "skip": {
639
+ if (entry.status === "no-conflict") {
640
+ ensureDir(path5.dirname(targetPath));
641
+ writeWithReplacements(targetPath, entry.plannedFile.sourcePath, entry.plannedFile.replacements, options.conditionCtx, entry.plannedFile.content);
642
+ entry.result = "created";
643
+ } else {
644
+ entry.result = "skipped";
645
+ }
646
+ break;
647
+ }
648
+ case "overwrite": {
649
+ ensureDir(path5.dirname(targetPath));
650
+ writeWithReplacements(targetPath, entry.plannedFile.sourcePath, entry.plannedFile.replacements, options.conditionCtx, entry.plannedFile.content);
651
+ entry.result = entry.status === "conflict" ? "overwritten" : "created";
652
+ break;
653
+ }
654
+ case "merge": {
655
+ const existingContent = fs5.readFileSync(targetPath, "utf-8");
656
+ let templateContent = fs5.readFileSync(entry.plannedFile.sourcePath, "utf-8");
657
+ if (options.conditionCtx) {
658
+ templateContent = renderConditionalBlocks(templateContent, options.conditionCtx);
659
+ }
660
+ const merged = mergeAgentsMd(existingContent, templateContent);
661
+ let finalContent = merged;
662
+ for (const [key, value] of Object.entries(entry.plannedFile.replacements)) {
663
+ finalContent = finalContent.replaceAll(key, value);
664
+ }
665
+ fs5.writeFileSync(targetPath, finalContent, "utf-8");
666
+ entry.result = "merged";
667
+ break;
668
+ }
669
+ }
670
+ }
671
+ return entries;
672
+ }
673
+ function writeWithReplacements(targetPath, sourcePath, replacements, conditionCtx, inlineContent) {
674
+ let content;
675
+ if (inlineContent !== void 0) {
676
+ content = inlineContent;
677
+ } else {
678
+ content = fs5.readFileSync(sourcePath, "utf-8");
679
+ if (conditionCtx) {
680
+ content = renderConditionalBlocks(content, conditionCtx);
681
+ }
682
+ }
683
+ for (const [key, value] of Object.entries(replacements)) {
684
+ content = content.replaceAll(key, value);
685
+ }
686
+ fs5.writeFileSync(targetPath, content, "utf-8");
687
+ }
688
+ function isInteractive() {
689
+ if (process.env.CI === "true" || process.env.CI === "1") return false;
690
+ if (process.env.NODE_ENV === "test") return false;
691
+ return process.stdout.isTTY === true;
692
+ }
693
+ async function processConflicts(plannedFiles, options) {
694
+ const entries = detectConflicts(plannedFiles, options.targetDir);
695
+ const resolved = await resolveConflicts(entries, options);
696
+ if (options.dryRun) {
697
+ return [];
698
+ }
699
+ const results = executePlan(resolved, {
700
+ targetDir: options.targetDir,
701
+ conditionCtx: options.conditionCtx
702
+ });
703
+ printReport(results);
704
+ printSkippedWarning(results);
705
+ return results.filter((e) => e.result === "created" || e.result === "overwritten" || e.result === "merged").map((e) => e.plannedFile.relativePath);
706
+ }
707
+
708
+ // src/generators/i18n.ts
709
+ var registry = {};
710
+ function registerLabels(template, language, labels31) {
711
+ if (!registry[template]) {
712
+ registry[template] = {};
713
+ }
714
+ registry[template][language] = labels31;
715
+ }
716
+ function loadLabels(template, language) {
717
+ const langLabels = registry[template]?.[language];
718
+ if (langLabels) return langLabels;
719
+ const esLabels = registry[template]?.["es"];
720
+ if (esLabels) return esLabels;
721
+ return {};
722
+ }
723
+
724
+ // src/generators/agents/labels/es.ts
725
+ var labels = {
726
+ // ── Frontmatter ──
727
+ fmType: "agent-protocol",
728
+ fmTags: "agents, protocolo, operativo, ia",
729
+ // ── Título ──
730
+ title: "AGENTS.md \u2014 Protocolo Operativo",
731
+ subtitle: "Reglas que TODO agente de IA debe seguir al trabajar en este proyecto. Gu\xEDa extendida: `docs/internal/agent-guide.md`.",
732
+ // ── STOP ──
733
+ stopTitle: "STOP \u2014 Lee esto ANTES de hacer nada",
734
+ stop1: "**TRIAGE**: Clasifica la tarea (SMALL/MEDIUM/LARGE). No saltes este paso.",
735
+ stop2: "**LEE**: Lee la documentaci\xF3n indicada en la tabla ANTES de escribir c\xF3digo.",
736
+ stop3: "**PREGUNTA**: Si hay ambig\xFCedad, haz TODAS las preguntas en UN solo mensaje.",
737
+ stop4: "**NO IMPLEMENTES** sin seguir el protocolo completo (MEDIUM/LARGE).",
738
+ stop5: "**@reviewer**: Invoca ANTES de marcar la tarea como completada (MEDIUM/LARGE).",
739
+ // ── Triage ──
740
+ triageTitle: "Triage de tarea",
741
+ triageIntro: "Antes de ejecutar el protocolo, clasificar la tarea:",
742
+ triageSizeHeader: "Tama\xF1o",
743
+ triageCriteriaHeader: "Criterio",
744
+ triageProtocolHeader: "Protocolo",
745
+ triageSmall: "**SMALL**",
746
+ triageSmallCriteria: "\u22642 archivos, <50 l\xEDneas",
747
+ triageSmallProtocol: "Leer CONTEXT.md \u2192 implementar \u2192 lint \u2192 done",
748
+ triageMedium: "**MEDIUM**",
749
+ triageMediumCriteria: "3-10 archivos, feature moderada",
750
+ triageMediumProtocol: "Protocolo completo (sin subdelegaci\xF3n)",
751
+ triageLarge: "**LARGE**",
752
+ triageLargeCriteria: "Multi-d\xEDa, arquitectural",
753
+ triageLargeProtocol: "Protocolo completo + ADR + subdelegaci\xF3n",
754
+ triageExamples: "**Ejemplos**: SMALL = fix typo, cambiar color, corregir import. MEDIUM = nuevo endpoint, nuevo componente, nuevo servicio simple. LARGE = sistema de auth, integraci\xF3n con provider externo, sistema de notificaciones multi-canal.",
755
+ triageEscalate: "Si empiezas SMALL y la tarea crece \u2192 escalar a MEDIUM.",
756
+ // ── Stack ──
757
+ stackTitle: "Stack y convenciones",
758
+ stackSectionTitle: "Stack",
759
+ stackFrontend: "**Frontend**",
760
+ stackBackend: "**Backend**",
761
+ stackDatabase: "**Base de datos**",
762
+ stackCICD: "**CI/CD**",
763
+ stackPlaceholder: "[framework y versi\xF3n \u2014 ej.",
764
+ stackDbPlaceholder: "[tipo y versi\xF3n \u2014 ej.",
765
+ stackCIPlaceholder: "[plataforma \u2014 ej.",
766
+ stackAutoDetectTitle: "Detecci\xF3n autom\xE1tica de stack",
767
+ stackAutoDetectDesc: "Si el stack no est\xE1 rellenado arriba, el agente debe detectarlo:",
768
+ stackFileHeader: "Archivo detectado",
769
+ stackEcosystemHeader: "Ecosistema",
770
+ stackCommandsHeader: "Comandos probables",
771
+ // ── Convenciones ──
772
+ conventionsTitle: "Convenios obligatorios",
773
+ convLang: "**Idioma**: C\xF3digo en **ingl\xE9s**. Comentarios y docs en **espa\xF1ol**.",
774
+ convNaming: "**Nombramiento**: [convenci\xF3n de nombres \u2014 ej. camelCase variables/funciones, PascalCase componentes]",
775
+ convStructure: "**Estructura**: [convenci\xF3n \u2014 ej. feature-based folders]",
776
+ convTesting: "**Testing**: Todo c\xF3digo nuevo DEBE incluir tests.",
777
+ convLinting: "**Linting**: Pasar `npm run lint` sin errores antes de completar.",
778
+ convCommits: "**Commits**: Conventional Commits en espa\xF1ol: `tipo(alcance): descripci\xF3n`.",
779
+ convSecurity: "**Seguridad**: Nunca commitear secrets. Usar variables de entorno.",
780
+ convDeps: "**Dependencias**: No a\xF1adir sin justificaci\xF3n. Si se a\xF1ade \u2192 documentar en ADR.",
781
+ convA11y: "**Accesibilidad**: Todo componente UI cumple WCAG 2.1 AA.",
782
+ // ── Comandos ──
783
+ commandsTitle: "Comandos",
784
+ commandsHeaderCmd: "Comando",
785
+ commandsHeaderUsage: "Uso",
786
+ cmdDev: "Desarrollo con hot-reload",
787
+ cmdBuild: "Build producci\xF3n",
788
+ cmdTest: "Tests unitarios e integraci\xF3n",
789
+ cmdTestE2E: "Tests end-to-end",
790
+ cmdLint: "Linter (debe pasar sin errores)",
791
+ cmdTypecheck: "Verificaci\xF3n de tipos",
792
+ commandsDetail: "> **Detalle completo** de convenciones de git, commits, PRs y testing en [`docs/dev-workflow.md`](docs/dev-workflow.md).",
793
+ // ── ANTES ──
794
+ beforeTitle: "ANTES de cada tarea (MEDIUM/LARGE)",
795
+ before1Title: "1. Leer docs seg\xFAn tipo de tarea",
796
+ beforeTaskTypeHeader: "Tipo de tarea",
797
+ beforeDocHeader: "Documentaci\xF3n a leer primero",
798
+ beforeAny: "Cualquier tarea",
799
+ beforeFeature: "Feature nueva",
800
+ beforeBug: "Bug/UI/Estilo",
801
+ beforeAPI: "API/Backend",
802
+ beforeDeploy: "Deploy/Infra",
803
+ beforeArch: "Arquitectura",
804
+ before2Title: "2. Verificar ADRs existentes",
805
+ before2Desc: "Buscar en `docs/adr/` antes de tomar decisiones:",
806
+ before2Accept: "**Existe ADR aceptado** \u2192 SEGUIRLO. No reinventar.",
807
+ before2Contradict: "**Contradice lo que vas a hacer** \u2192 Plantear discusi\xF3n antes.",
808
+ before2None: "**No existe** \u2192 Evaluar si merece ADR (ver criterio y ejemplos en [`docs/adr/TEMPLATE.md`](docs/adr/TEMPLATE.md)).",
809
+ before3Title: "3. Verificar CONTEXT.md",
810
+ before3Desc: "Si la tarea usa t\xE9rminos que no est\xE1n en `docs/CONTEXT.md` \u2192 preparar para actualizar al terminar.",
811
+ before3Completeness: "Si `CONTEXT.md` tiene `completeness < 50%` \u2192 prioridad: completar CONTEXT.md antes de implementar features.",
812
+ before4Title: "4. Preguntar si hay ambig\xFCedad",
813
+ before4Desc: "Si despu\xE9s de leer la documentaci\xF3n hay ambig\xFCedad \u2192 **batch TODAS las preguntas en un solo mensaje**. Cada pregunta con opciones cuando sea posible. No preguntar una por una.",
814
+ before4DontAsk: "No preguntes si la tarea est\xE1 clara, es implementaci\xF3n est\xE1ndar, o la info est\xE1 en los docs.",
815
+ // ── DESPUÉS ──
816
+ afterTitle: "DESPU\xC9S de cada tarea (MEDIUM/LARGE)",
817
+ afterTreeTitle: "\xC1rbol post-tarea",
818
+ afterTreeNode1: "\xBFTomaste una decisi\xF3n?",
819
+ afterTreeNode1a: "Arquitect\xF3nica \u2192 docs/adr/ (ADR formal)",
820
+ afterTreeNode1b: "Implementaci\xF3n no obvia \u2192 JSDoc + docs/adr/ai-decisions.md",
821
+ afterTreeNode1c: "No \u2192 siguiente",
822
+ afterTreeNode2: "\xBFT\xE9rminos nuevos del dominio? \u2192 docs/CONTEXT.md",
823
+ afterTreeNode3: "\xBFEndpoints cambiados? \u2192 docs/reference/api.md",
824
+ afterTreeNode4: "\xBFUI/UX cambiada? \u2192 docs/DESIGN.md",
825
+ afterTreeNode5: "\xBFDeploy a producci\xF3n? \u2192 CHANGELOG.md + docs/guides/deployment.md",
826
+ afterTreeNode6: "\xBFFeature completado? \u2192 docs/roadmap.md",
827
+ afterTreeNode7: "\xBFGotcha descubierto? \u2192 docs/guides/troubleshooting.md",
828
+ afterTreeNode8: "\xBFRefactor de patrones? \u2192 Revisar architecture.md y ADRs",
829
+ afterGuide: "> **Gu\xEDa extendida** con diagramas y ejemplos en [`docs/internal/agent-guide.md`](docs/internal/agent-guide.md).",
830
+ afterSkill: "> **Alternativa**: Invocar skill `doc-maintain` para detectar cambios y sugerir actualizaciones autom\xE1ticamente.",
831
+ afterGoldenRule: "**Regla de oro**: Si cambias el c\xF3digo, cambias la documentaci\xF3n.",
832
+ // ── Quality Gate ──
833
+ qgTitle: "Quality Gate \u2014 @reviewer (MEDIUM/LARGE)",
834
+ qgIntro: "**ANTES de completar**, invocar `@reviewer` para verificar:",
835
+ qgItem1: "\u2705 Code style conforme a convenciones",
836
+ qgItem2: "\u2705 Sin duplicaci\xF3n \u2014 usa componentes/utilidades existentes",
837
+ qgItem3: "\u2705 Sigue la arquitectura del proyecto y respeta ADRs",
838
+ qgItem4: "\u2705 Sin vulnerabilidades de seguridad",
839
+ qgItem5: "\u2705 Tests incluidos para c\xF3digo nuevo",
840
+ qgItem6: "\u2705 Documentaci\xF3n actualizada",
841
+ qgItem7: "\u2705 Sin problemas de performance evidentes",
842
+ qgBlocking: "**\u274C BLOQUEANTE** \u2192 arreglar antes de completar.",
843
+ qgSuggested: "**\u26A0\uFE0F SUGERIDO** \u2192 recomendado pero no bloquea.",
844
+ // ── Subdelegación ──
845
+ subdelTitle: "Subdelegaci\xF3n",
846
+ subdelIntro: "Instrucciones m\xEDnimas al subagente:",
847
+ subdelExample: "> Lee AGENTS.md y sigue el protocolo completo. Tarea: [descripci\xF3n]. Docs relevantes: [lista].",
848
+ subdelNote: "No repitas convenciones \u2014 ya est\xE1n en AGENTS.md. Ver ejemplo completo en `docs/internal/agent-guide.md`.",
849
+ // ── Skills ──
850
+ skillsTitle: "Skills y agentes disponibles",
851
+ skillsList: "**Skills**: `doc-scaffold`, `doc-write`, `doc-design`, `doc-review`, `doc-maintain` \u2014 ver `.agents/skills/`",
852
+ agentsList: "**Agentes**: `@reviewer` (quality gate), `@doc-writer`, `@doc-reviewer`, `@doc-designer`, `@doc-maintainer` \u2014 ver `.agents/agents/`",
853
+ skillsGuide: "**Gu\xEDa extendida**: `docs/internal/agent-guide.md`",
854
+ // ── Tabla de detección de stack ──
855
+ stackRowPackage: "`package.json`",
856
+ stackRowNodeEco: "Node.js (npm/pnpm/yarn)",
857
+ stackRowNodeCmds: "`npm run dev`, `npm run build`",
858
+ stackRowPyReq: "`requirements.txt` / `pyproject.toml`",
859
+ stackRowPyEco: "Python (pip/poetry)",
860
+ stackRowPyCmds: "`python manage.py runserver`, `pytest`",
861
+ stackRowGo: "`go.mod`",
862
+ stackRowGoEco: "Go",
863
+ stackRowGoCmds: "`go run .`, `go test ./...`",
864
+ stackRowRust: "`Cargo.toml`",
865
+ stackRowRustEco: "Rust",
866
+ stackRowRustCmds: "`cargo run`, `cargo test`",
867
+ stackRowJava: "`pom.xml` / `build.gradle`",
868
+ stackRowJavaEco: "Java/Kotlin",
869
+ stackRowJavaCmds: "`mvn spring-boot:run`, `gradle bootRun`",
870
+ // ── Tabla de docs (ANTES) ──
871
+ beforeDocAny: "`docs/CONTEXT.md`",
872
+ beforeDocFeature: "`docs/roadmap.md`, `docs/explanation/architecture.md`, ADRs relevantes",
873
+ beforeDocBug: "`docs/DESIGN.md`, `docs/CONTEXT.md`",
874
+ beforeDocApi: "`docs/reference/api.md`, `docs/reference/configuration.md`",
875
+ beforeDocDeploy: "`docs/guides/deployment.md`, `docs/reference/infrastructure.md`",
876
+ beforeDocArch: "`docs/explanation/architecture.md`, `docs/adr/` (todos)",
877
+ // ── Comandos (valores) ──
878
+ cmdDevVal: "{{DEV_COMMAND}}",
879
+ cmdBuildVal: "{{BUILD_COMMAND}}",
880
+ cmdTestVal: "{{TEST_COMMAND}}",
881
+ cmdTestE2EVal: "[comando e2e]",
882
+ cmdLintVal: "{{LINT_COMMAND}}",
883
+ cmdTypecheckVal: "[comando typecheck]"
884
+ };
885
+
886
+ // src/generators/agents/labels/en.ts
887
+ var labels2 = {
888
+ // ── Frontmatter ──
889
+ fmType: "agent-protocol",
890
+ fmTags: "agents, protocol, operational, ai",
891
+ // ── Title ──
892
+ title: "AGENTS.md \u2014 Operational Protocol",
893
+ subtitle: "Rules that EVERY AI agent must follow when working on this project. Extended guide: `docs/internal/agent-guide.md`.",
894
+ // ── STOP ──
895
+ stopTitle: "STOP \u2014 Read this BEFORE doing anything",
896
+ stop1: "**TRIAGE**: Classify the task (SMALL/MEDIUM/LARGE). Don't skip this step.",
897
+ stop2: "**READ**: Read the documentation indicated in the table BEFORE writing code.",
898
+ stop3: "**ASK**: If there's ambiguity, ask ALL questions in ONE message.",
899
+ stop4: "**DON'T IMPLEMENT** without following the full protocol (MEDIUM/LARGE).",
900
+ stop5: "**@reviewer**: Invoke BEFORE marking the task as completed (MEDIUM/LARGE).",
901
+ // ── Triage ──
902
+ triageTitle: "Task Triage",
903
+ triageIntro: "Before executing the protocol, classify the task:",
904
+ triageSizeHeader: "Size",
905
+ triageCriteriaHeader: "Criteria",
906
+ triageProtocolHeader: "Protocol",
907
+ triageSmall: "**SMALL**",
908
+ triageSmallCriteria: "\u22642 files, <50 lines",
909
+ triageSmallProtocol: "Read CONTEXT.md \u2192 implement \u2192 lint \u2192 done",
910
+ triageMedium: "**MEDIUM**",
911
+ triageMediumCriteria: "3-10 files, moderate feature",
912
+ triageMediumProtocol: "Full protocol (no sub-delegation)",
913
+ triageLarge: "**LARGE**",
914
+ triageLargeCriteria: "Multi-day, architectural",
915
+ triageLargeProtocol: "Full protocol + ADR + sub-delegation",
916
+ triageExamples: "**Examples**: SMALL = fix typo, change color, correct import. MEDIUM = new endpoint, new component, simple service. LARGE = auth system, external provider integration, multi-channel notification system.",
917
+ triageEscalate: "If you start SMALL and the task grows \u2192 escalate to MEDIUM.",
918
+ // ── Stack ──
919
+ stackTitle: "Stack and Conventions",
920
+ stackSectionTitle: "Stack",
921
+ stackFrontend: "**Frontend**",
922
+ stackBackend: "**Backend**",
923
+ stackDatabase: "**Database**",
924
+ stackCICD: "**CI/CD**",
925
+ stackPlaceholder: "[framework and version \u2014 e.g.",
926
+ stackDbPlaceholder: "[type and version \u2014 e.g.",
927
+ stackCIPlaceholder: "[platform \u2014 e.g.",
928
+ stackAutoDetectTitle: "Automatic Stack Detection",
929
+ stackAutoDetectDesc: "If the stack is not filled above, the agent should detect it:",
930
+ stackFileHeader: "Detected File",
931
+ stackEcosystemHeader: "Ecosystem",
932
+ stackCommandsHeader: "Probable Commands",
933
+ // ── Conventions ──
934
+ conventionsTitle: "Mandatory Conventions",
935
+ convLang: "**Language**: Code in **English**. Comments and docs in **English**.",
936
+ convNaming: "**Naming**: [naming convention \u2014 e.g. camelCase variables/functions, PascalCase components]",
937
+ convStructure: "**Structure**: [convention \u2014 e.g. feature-based folders]",
938
+ convTesting: "**Testing**: All new code MUST include tests.",
939
+ convLinting: "**Linting**: Pass `npm run lint` without errors before completing.",
940
+ convCommits: "**Commits**: Conventional Commits in English: `type(scope): description`.",
941
+ convSecurity: "**Security**: Never commit secrets. Use environment variables.",
942
+ convDeps: "**Dependencies**: Don't add without justification. If added \u2192 document in ADR.",
943
+ convA11y: "**Accessibility**: All UI components comply with WCAG 2.1 AA.",
944
+ // ── Commands ──
945
+ commandsTitle: "Commands",
946
+ commandsHeaderCmd: "Command",
947
+ commandsHeaderUsage: "Usage",
948
+ cmdDev: "Development with hot-reload",
949
+ cmdBuild: "Production build",
950
+ cmdTest: "Unit and integration tests",
951
+ cmdTestE2E: "End-to-end tests",
952
+ cmdLint: "Linter (must pass without errors)",
953
+ cmdTypecheck: "Type verification",
954
+ commandsDetail: "> **Full details** of git conventions, commits, PRs and testing in [`docs/dev-workflow.md`](docs/dev-workflow.md).",
955
+ // ── BEFORE ──
956
+ beforeTitle: "BEFORE each task (MEDIUM/LARGE)",
957
+ before1Title: "1. Read docs based on task type",
958
+ beforeTaskTypeHeader: "Task Type",
959
+ beforeDocHeader: "Documentation to read first",
960
+ beforeAny: "Any task",
961
+ beforeFeature: "New feature",
962
+ beforeBug: "Bug/UI/Style",
963
+ beforeAPI: "API/Backend",
964
+ beforeDeploy: "Deploy/Infra",
965
+ beforeArch: "Architecture",
966
+ before2Title: "2. Check existing ADRs",
967
+ before2Desc: "Search in `docs/adr/` before making decisions:",
968
+ before2Accept: "**Accepted ADR exists** \u2192 FOLLOW IT. Don't reinvent.",
969
+ before2Contradict: "**Contradicts what you're about to do** \u2192 Raise discussion first.",
970
+ before2None: "**Doesn't exist** \u2192 Evaluate if it deserves an ADR (see criteria and examples in [`docs/adr/TEMPLATE.md`](docs/adr/TEMPLATE.md)).",
971
+ before3Title: "3. Check CONTEXT.md",
972
+ before3Desc: "If the task uses terms not in `docs/CONTEXT.md` \u2192 prepare to update when done.",
973
+ before3Completeness: "If `CONTEXT.md` has `completeness < 50%` \u2192 priority: complete CONTEXT.md before implementing features.",
974
+ before4Title: "4. Ask if there's ambiguity",
975
+ before4Desc: "After reading the documentation, if there's ambiguity \u2192 **batch ALL questions in one message**. Each question with options when possible. Don't ask one by one.",
976
+ before4DontAsk: "Don't ask if the task is clear, it's standard implementation, or the info is in the docs.",
977
+ // ── AFTER ──
978
+ afterTitle: "AFTER each task (MEDIUM/LARGE)",
979
+ afterTreeTitle: "Post-task tree",
980
+ afterTreeNode1: "Did you make a decision?",
981
+ afterTreeNode1a: "Architectural \u2192 docs/adr/ (formal ADR)",
982
+ afterTreeNode1b: "Non-obvious implementation \u2192 JSDoc + docs/adr/ai-decisions.md",
983
+ afterTreeNode1c: "No \u2192 next",
984
+ afterTreeNode2: "New domain terms? \u2192 docs/CONTEXT.md",
985
+ afterTreeNode3: "Endpoints changed? \u2192 docs/reference/api.md",
986
+ afterTreeNode4: "UI/UX changed? \u2192 docs/DESIGN.md",
987
+ afterTreeNode5: "Deploy to production? \u2192 CHANGELOG.md + docs/guides/deployment.md",
988
+ afterTreeNode6: "Feature completed? \u2192 docs/roadmap.md",
989
+ afterTreeNode7: "Gotcha discovered? \u2192 docs/guides/troubleshooting.md",
990
+ afterTreeNode8: "Pattern refactor? \u2192 Review architecture.md and ADRs",
991
+ afterGuide: "> **Extended guide** with diagrams and examples in [`docs/internal/agent-guide.md`](docs/internal/agent-guide.md).",
992
+ afterSkill: "> **Alternative**: Invoke skill `doc-maintain` to detect changes and suggest updates automatically.",
993
+ afterGoldenRule: "**Golden rule**: If you change the code, change the documentation.",
994
+ // ── Quality Gate ──
995
+ qgTitle: "Quality Gate \u2014 @reviewer (MEDIUM/LARGE)",
996
+ qgIntro: "**BEFORE completing**, invoke `@reviewer` to verify:",
997
+ qgItem1: "\u2705 Code style conforms to conventions",
998
+ qgItem2: "\u2705 No duplication \u2014 uses existing components/utilities",
999
+ qgItem3: "\u2705 Follows project architecture and respects ADRs",
1000
+ qgItem4: "\u2705 No security vulnerabilities",
1001
+ qgItem5: "\u2705 Tests included for new code",
1002
+ qgItem6: "\u2705 Documentation updated",
1003
+ qgItem7: "\u2705 No obvious performance issues",
1004
+ qgBlocking: "**\u274C BLOCKING** \u2192 fix before completing.",
1005
+ qgSuggested: "**\u26A0\uFE0F SUGGESTED** \u2192 recommended but doesn't block.",
1006
+ // ── Sub-delegation ──
1007
+ subdelTitle: "Sub-delegation",
1008
+ subdelIntro: "Minimum instructions to sub-agent:",
1009
+ subdelExample: "> Read AGENTS.md and follow the full protocol. Task: [description]. Relevant docs: [list].",
1010
+ subdelNote: "Don't repeat conventions \u2014 they're already in AGENTS.md. See complete example in `docs/internal/agent-guide.md`.",
1011
+ // ── Skills ──
1012
+ skillsTitle: "Available Skills and Agents",
1013
+ skillsList: "**Skills**: `doc-scaffold`, `doc-write`, `doc-design`, `doc-review`, `doc-maintain` \u2014 see `.agents/skills/`",
1014
+ agentsList: "**Agents**: `@reviewer` (quality gate), `@doc-writer`, `@doc-reviewer`, `@doc-designer`, `@doc-maintainer` \u2014 see `.agents/agents/`",
1015
+ skillsGuide: "**Extended guide**: `docs/internal/agent-guide.md`",
1016
+ // ── Stack detection table ──
1017
+ stackRowPackage: "`package.json`",
1018
+ stackRowNodeEco: "Node.js (npm/pnpm/yarn)",
1019
+ stackRowNodeCmds: "`npm run dev`, `npm run build`",
1020
+ stackRowPyReq: "`requirements.txt` / `pyproject.toml`",
1021
+ stackRowPyEco: "Python (pip/poetry)",
1022
+ stackRowPyCmds: "`python manage.py runserver`, `pytest`",
1023
+ stackRowGo: "`go.mod`",
1024
+ stackRowGoEco: "Go",
1025
+ stackRowGoCmds: "`go run .`, `go test ./...`",
1026
+ stackRowRust: "`Cargo.toml`",
1027
+ stackRowRustEco: "Rust",
1028
+ stackRowRustCmds: "`cargo run`, `cargo test`",
1029
+ stackRowJava: "`pom.xml` / `build.gradle`",
1030
+ stackRowJavaEco: "Java/Kotlin",
1031
+ stackRowJavaCmds: "`mvn spring-boot:run`, `gradle bootRun`",
1032
+ // ── Docs table (BEFORE) ──
1033
+ beforeDocAny: "`docs/CONTEXT.md`",
1034
+ beforeDocFeature: "`docs/roadmap.md`, `docs/explanation/architecture.md`, relevant ADRs",
1035
+ beforeDocBug: "`docs/DESIGN.md`, `docs/CONTEXT.md`",
1036
+ beforeDocApi: "`docs/reference/api.md`, `docs/reference/configuration.md`",
1037
+ beforeDocDeploy: "`docs/guides/deployment.md`, `docs/reference/infrastructure.md`",
1038
+ beforeDocArch: "`docs/explanation/architecture.md`, `docs/adr/` (all)",
1039
+ // ── Commands (values) ──
1040
+ cmdDevVal: "{{DEV_COMMAND}}",
1041
+ cmdBuildVal: "{{BUILD_COMMAND}}",
1042
+ cmdTestVal: "{{TEST_COMMAND}}",
1043
+ cmdTestE2EVal: "[e2e command]",
1044
+ cmdLintVal: "{{LINT_COMMAND}}",
1045
+ cmdTypecheckVal: "[typecheck command]"
1046
+ };
1047
+
1048
+ // src/generators/agents/generator.ts
1049
+ registerLabels("agents", "es", labels);
1050
+ registerLabels("agents", "en", labels2);
1051
+ function fmtStack(options) {
1052
+ const s = options.stack;
1053
+ if (!s) return "[TECNOLOG\xCDA PRINCIPAL]";
1054
+ const parts = [s.language];
1055
+ if (s.framework) parts.push(s.framework);
1056
+ return parts.join(" + ");
1057
+ }
1058
+ function fmtFramework(options) {
1059
+ return options.stack?.framework || "[framework]";
1060
+ }
1061
+ function generate(options) {
1062
+ const labels31 = loadLabels("agents", options.language);
1063
+ const t = (key) => labels31[key] || `[${key}]`;
1064
+ const today = options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1065
+ const stackStr = fmtStack(options);
1066
+ const fw = fmtFramework(options);
1067
+ let md = `---
1068
+ project: "${options.projectName}"
1069
+ stack: "${stackStr}"
1070
+ created: "2025-01-01"
1071
+ updated: "${today}"
1072
+ status: active
1073
+ type: ${t("fmType")}
1074
+ tags: [${t("fmTags")}]
1075
+ ---
1076
+
1077
+ `;
1078
+ md += `# ${t("title")}
1079
+
1080
+ `;
1081
+ md += `${t("subtitle")}
1082
+
1083
+ `;
1084
+ md += "---\n\n";
1085
+ md += `## ${t("stopTitle")}
1086
+
1087
+ `;
1088
+ md += `1. ${t("stop1")}
1089
+ `;
1090
+ md += `2. ${t("stop2")}
1091
+ `;
1092
+ md += `3. ${t("stop3")}
1093
+ `;
1094
+ md += `4. ${t("stop4")}
1095
+ `;
1096
+ md += `5. ${t("stop5")}
1097
+
1098
+ `;
1099
+ md += "---\n\n";
1100
+ md += `## ${t("triageTitle")}
1101
+
1102
+ `;
1103
+ md += `${t("triageIntro")}
1104
+
1105
+ `;
1106
+ md += `| ${t("triageSizeHeader")} | ${t("triageCriteriaHeader")} | ${t("triageProtocolHeader")} |
1107
+ `;
1108
+ md += `|--------|----------|-----------|
1109
+ `;
1110
+ md += `| ${t("triageSmall")} | ${t("triageSmallCriteria")} | ${t("triageSmallProtocol")} |
1111
+ `;
1112
+ md += `| ${t("triageMedium")} | ${t("triageMediumCriteria")} | ${t("triageMediumProtocol")} |
1113
+ `;
1114
+ md += `| ${t("triageLarge")} | ${t("triageLargeCriteria")} | ${t("triageLargeProtocol")} |
1115
+
1116
+ `;
1117
+ md += `${t("triageExamples")}
1118
+
1119
+ `;
1120
+ md += `${t("triageEscalate")}
1121
+
1122
+ `;
1123
+ md += "---\n\n";
1124
+ md += `## ${t("stackTitle")}
1125
+
1126
+ `;
1127
+ md += `### ${t("stackSectionTitle")}
1128
+ `;
1129
+ if (options.conditionCtx.hasFrontend) {
1130
+ md += `- ${t("stackFrontend")}: ${t("stackPlaceholder")} ${fw}]
1131
+ `;
1132
+ }
1133
+ if (options.conditionCtx.hasBackend) {
1134
+ md += `- ${t("stackBackend")}: ${t("stackPlaceholder")} ${fw}]
1135
+ `;
1136
+ }
1137
+ if (options.conditionCtx.hasDatabase) {
1138
+ md += `- ${t("stackDatabase")}: ${t("stackDbPlaceholder")} ${stackStr}]
1139
+ `;
1140
+ }
1141
+ md += `- ${t("stackCICD")}: ${t("stackCIPlaceholder")} ${stackStr}]
1142
+
1143
+ `;
1144
+ md += `### ${t("stackAutoDetectTitle")}
1145
+
1146
+ `;
1147
+ md += `${t("stackAutoDetectDesc")}
1148
+
1149
+ `;
1150
+ md += `| ${t("stackFileHeader")} | ${t("stackEcosystemHeader")} | ${t("stackCommandsHeader")} |
1151
+ `;
1152
+ md += `|-------------------|------------|--------------------|
1153
+ `;
1154
+ md += `| ${t("stackRowPackage")} | ${t("stackRowNodeEco")} | ${t("stackRowNodeCmds")} |
1155
+ `;
1156
+ md += `| ${t("stackRowPyReq")} | ${t("stackRowPyEco")} | ${t("stackRowPyCmds")} |
1157
+ `;
1158
+ md += `| ${t("stackRowGo")} | ${t("stackRowGoEco")} | ${t("stackRowGoCmds")} |
1159
+ `;
1160
+ md += `| ${t("stackRowRust")} | ${t("stackRowRustEco")} | ${t("stackRowRustCmds")} |
1161
+ `;
1162
+ md += `| ${t("stackRowJava")} | ${t("stackRowJavaEco")} | ${t("stackRowJavaCmds")} |
1163
+
1164
+ `;
1165
+ md += `### ${t("conventionsTitle")}
1166
+ `;
1167
+ md += `1. ${t("convLang")}
1168
+ `;
1169
+ md += `2. ${t("convNaming")}
1170
+ `;
1171
+ md += `3. ${t("convStructure")}
1172
+ `;
1173
+ md += `4. ${t("convTesting")}
1174
+ `;
1175
+ md += `5. ${t("convLinting")}
1176
+ `;
1177
+ md += `6. ${t("convCommits")}
1178
+ `;
1179
+ md += `7. ${t("convSecurity")}
1180
+ `;
1181
+ md += `8. ${t("convDeps")}
1182
+ `;
1183
+ md += `9. ${t("convA11y")}
1184
+
1185
+ `;
1186
+ md += `### ${t("commandsTitle")}
1187
+
1188
+ `;
1189
+ md += `| ${t("commandsHeaderCmd")} | ${t("commandsHeaderUsage")} |
1190
+ `;
1191
+ md += `|---------|-----|
1192
+ `;
1193
+ md += `| \`${t("cmdDevVal")}\` | ${t("cmdDev")} |
1194
+ `;
1195
+ md += `| \`${t("cmdBuildVal")}\` | ${t("cmdBuild")} |
1196
+ `;
1197
+ md += `| \`${t("cmdTestVal")}\` | ${t("cmdTest")} |
1198
+ `;
1199
+ md += `| \`${t("cmdTestE2EVal")}\` | ${t("cmdTestE2E")} |
1200
+ `;
1201
+ md += `| \`${t("cmdLintVal")}\` | ${t("cmdLint")} |
1202
+ `;
1203
+ md += `| \`${t("cmdTypecheckVal")}\` | ${t("cmdTypecheck")} |
1204
+
1205
+ `;
1206
+ md += `${t("commandsDetail")}
1207
+
1208
+ `;
1209
+ md += "---\n\n";
1210
+ md += `## ${t("beforeTitle")}
1211
+
1212
+ `;
1213
+ md += `### ${t("before1Title")}
1214
+
1215
+ `;
1216
+ md += `| ${t("beforeTaskTypeHeader")} | ${t("beforeDocHeader")} |
1217
+ `;
1218
+ md += `|---------------|------------------------------|
1219
+ `;
1220
+ md += `| ${t("beforeAny")} | ${t("beforeDocAny")} |
1221
+ `;
1222
+ md += `| ${t("beforeFeature")} | ${t("beforeDocFeature")} |
1223
+ `;
1224
+ md += `| ${t("beforeBug")} | ${t("beforeDocBug")} |
1225
+ `;
1226
+ md += `| ${t("beforeAPI")} | ${t("beforeDocApi")} |
1227
+ `;
1228
+ md += `| ${t("beforeDeploy")} | ${t("beforeDocDeploy")} |
1229
+ `;
1230
+ md += `| ${t("beforeArch")} | ${t("beforeDocArch")} |
1231
+
1232
+ `;
1233
+ md += `### ${t("before2Title")}
1234
+
1235
+ `;
1236
+ md += `${t("before2Desc")}
1237
+ `;
1238
+ md += `- ${t("before2Accept")}
1239
+ `;
1240
+ md += `- ${t("before2Contradict")}
1241
+ `;
1242
+ md += `- ${t("before2None")}
1243
+
1244
+ `;
1245
+ md += `### ${t("before3Title")}
1246
+
1247
+ `;
1248
+ md += `${t("before3Desc")}
1249
+
1250
+ `;
1251
+ md += `${t("before3Completeness")}
1252
+
1253
+ `;
1254
+ md += `### ${t("before4Title")}
1255
+
1256
+ `;
1257
+ md += `${t("before4Desc")}
1258
+
1259
+ `;
1260
+ md += `${t("before4DontAsk")}
1261
+
1262
+ `;
1263
+ md += "---\n\n";
1264
+ md += `## ${t("afterTitle")}
1265
+
1266
+ `;
1267
+ md += `### ${t("afterTreeTitle")}
1268
+
1269
+ `;
1270
+ md += "```\n";
1271
+ md += `${t("afterTreeNode1")}
1272
+ `;
1273
+ md += ` \u251C\u2500\u2500 ${t("afterTreeNode1a")}
1274
+ `;
1275
+ md += ` \u251C\u2500\u2500 ${t("afterTreeNode1b")}
1276
+ `;
1277
+ md += ` \u2514\u2500\u2500 ${t("afterTreeNode1c")}
1278
+ `;
1279
+ md += `${t("afterTreeNode2")}
1280
+ `;
1281
+ md += `${t("afterTreeNode3")}
1282
+ `;
1283
+ md += `${t("afterTreeNode4")}
1284
+ `;
1285
+ md += `${t("afterTreeNode5")}
1286
+ `;
1287
+ md += `${t("afterTreeNode6")}
1288
+ `;
1289
+ md += `${t("afterTreeNode7")}
1290
+ `;
1291
+ md += `${t("afterTreeNode8")}
1292
+ `;
1293
+ md += "```\n\n";
1294
+ md += `${t("afterGuide")}
1295
+ `;
1296
+ md += `${t("afterSkill")}
1297
+
1298
+ `;
1299
+ md += `${t("afterGoldenRule")}
1300
+
1301
+ `;
1302
+ md += "---\n\n";
1303
+ md += `## ${t("qgTitle")}
1304
+
1305
+ `;
1306
+ md += `${t("qgIntro")}
1307
+ `;
1308
+ md += `- ${t("qgItem1")}
1309
+ `;
1310
+ md += `- ${t("qgItem2")}
1311
+ `;
1312
+ md += `- ${t("qgItem3")}
1313
+ `;
1314
+ md += `- ${t("qgItem4")}
1315
+ `;
1316
+ md += `- ${t("qgItem5")}
1317
+ `;
1318
+ md += `- ${t("qgItem6")}
1319
+ `;
1320
+ md += `- ${t("qgItem7")}
1321
+
1322
+ `;
1323
+ md += `- ${t("qgBlocking")}
1324
+ `;
1325
+ md += `- ${t("qgSuggested")}
1326
+
1327
+ `;
1328
+ md += "---\n\n";
1329
+ md += `## ${t("subdelTitle")}
1330
+
1331
+ `;
1332
+ md += `${t("subdelIntro")}
1333
+ `;
1334
+ md += `${t("subdelExample")}
1335
+
1336
+ `;
1337
+ md += `${t("subdelNote")}
1338
+
1339
+ `;
1340
+ md += "---\n\n";
1341
+ md += `## ${t("skillsTitle")}
1342
+
1343
+ `;
1344
+ md += `- ${t("skillsList")}
1345
+ `;
1346
+ md += `- ${t("agentsList")}
1347
+ `;
1348
+ md += `- ${t("skillsGuide")}
1349
+ `;
1350
+ return md;
1351
+ }
1352
+
1353
+ // src/generators/context/labels/es.ts
1354
+ var labels3 = {
1355
+ fmType: "domain-language",
1356
+ fmTags: "contexto, dominio, vocabulario, glosario",
1357
+ title: "CONTEXT.md \u2014 Lenguaje del Dominio",
1358
+ intro: "Este archivo define el vocabulario compartido que se usa en este proyecto. Todo t\xE9rmino de negocio o concepto clave del dominio debe estar documentado aqu\xED.",
1359
+ introGap: "Si un t\xE9rmino aparece en el c\xF3digo, la documentaci\xF3n o las conversaciones del equipo y NO est\xE1 en este archivo, es un gap que debe cubrirse.",
1360
+ entitiesTitle: "Entidades principales",
1361
+ entitiesTerm: "T\xE9rmino",
1362
+ entitiesDef: "Definici\xF3n",
1363
+ entitiesExample: "Ejemplo de uso",
1364
+ entitiesTech: "Equivalente t\xE9cnico",
1365
+ statesTitle: "Estados y flujos",
1366
+ statesState: "Estado",
1367
+ statesMeaning: "Significa",
1368
+ statesTransitions: "Transiciones posibles",
1369
+ rolesTitle: "Roles y permisos",
1370
+ rolesRole: "Rol",
1371
+ rolesWho: "Qui\xE9n es",
1372
+ rolesWhat: "Qu\xE9 puede hacer",
1373
+ bizTermsTitle: "T\xE9rminos de negocio",
1374
+ bizTermsTerm: "T\xE9rmino",
1375
+ bizTermsDef: "Definici\xF3n",
1376
+ bizTermsNotes: "Notas",
1377
+ techTermsTitle: "T\xE9rminos t\xE9cnicos internos",
1378
+ techTermsTerm: "T\xE9rmino",
1379
+ techTermsDef: "Definici\xF3n",
1380
+ techTermsWhy: "Por qu\xE9 existe",
1381
+ relationsTitle: "Relaciones entre conceptos",
1382
+ relationsCode: "[Entidad 1] \u2500\u2500\u2500 1:N \u2500\u2500\u2500\u2192 [Entidad 2]\n \u2514\u2500\u2500\u2192 [Entidad 3] (a trav\xE9s de [Entidad 4])",
1383
+ dialogTitle: "Ejemplo de di\xE1logo usando el dominio",
1384
+ dialogIntro: "Este ejemplo muestra c\xF3mo se usa el vocabulario en una conversaci\xF3n real del equipo:",
1385
+ dialogPM: '**Product Manager**: "El cliente necesita que los [T\xE9rmino 1] en estado [Estado A] se puedan convertir autom\xE1ticamente en [T\xE9rmino 2] cuando pasen a [Estado B]."',
1386
+ dialogDev: '**Developer**: "Entendido. \xBFEsa conversaci\xF3n aplica para todos los [Rol 1] o solo para los que tienen permiso de [acci\xF3n]?"',
1387
+ dialogPM2: '**Product Manager**: "Solo para [Rol 1]. Los [Rol 2] solo ven el [T\xE9rmino 1] pero no pueden convertirlo."',
1388
+ dialogDev2: '**Developer**: "Perfecto. Voy a a\xF1adir un bot\xF3n de conversi\xF3n en la vista de [T\xE9rmino 1] para [Rol 1], visible solo cuando est\xE9 en [Estado A]. \xBFEl [T\xE9rmino 2] resultante empieza en [Estado C]?"',
1389
+ dialogPM3: '**Product Manager**: "S\xED, empieza en [Estado C] y necesita aprobaci\xF3n de un [Rol 2] para pasar a [Estado D]."',
1390
+ ambTitle: "Ambig\xFCedades flagadas",
1391
+ ambIntro: "Estos t\xE9rminos tienen significados que podr\xEDan confundirse. Prestar atenci\xF3n al contexto:",
1392
+ ambTerm: "T\xE9rmino",
1393
+ ambConfusion: "Confusi\xF3n posible",
1394
+ ambClarification: "Aclaraci\xF3n",
1395
+ updateTitle: "C\xF3mo actualizar este archivo",
1396
+ update1: "Identificar si es una **entidad**, un **estado**, un **rol**, un **t\xE9rmino de negocio** o un **t\xE9rmino t\xE9cnico**.",
1397
+ update2: "A\xF1adirlo en la secci\xF3n correspondiente con: definici\xF3n, ejemplo de uso, y equivalente t\xE9cnico.",
1398
+ update3: "Si tiene relaciones con otras entidades, actualizar el diagrama de relaciones.",
1399
+ update4: 'Si es ambiguo o se confunde con otro t\xE9rmino, a\xF1adirlo en "Ambig\xFCedades flagadas".',
1400
+ update5: "Si se introdujo un nuevo estado o flujo, actualizar la tabla de estados.",
1401
+ updateRule: "**Regla**: Todo t\xE9rmino que aparezca en c\xF3digo, APIs, UI o conversaciones del equipo DEBE estar aqu\xED. Si no est\xE1, es un bug de documentaci\xF3n.",
1402
+ updateIntro: "Cuando se a\xF1ada un nuevo t\xE9rmino al dominio:"
1403
+ };
1404
+
1405
+ // src/generators/context/labels/en.ts
1406
+ var labels4 = {
1407
+ fmType: "domain-language",
1408
+ fmTags: "context, domain, vocabulary, glossary",
1409
+ title: "CONTEXT.md \u2014 Domain Language",
1410
+ intro: "This file defines the shared vocabulary used in this project. Every business term or key domain concept must be documented here.",
1411
+ introGap: "If a term appears in code, documentation or team conversations and is NOT in this file, it's a gap that needs to be covered.",
1412
+ entitiesTitle: "Main Entities",
1413
+ entitiesTerm: "Term",
1414
+ entitiesDef: "Definition",
1415
+ entitiesExample: "Usage Example",
1416
+ entitiesTech: "Technical Equivalent",
1417
+ statesTitle: "States and Flows",
1418
+ statesState: "State",
1419
+ statesMeaning: "Meaning",
1420
+ statesTransitions: "Possible Transitions",
1421
+ rolesTitle: "Roles and Permissions",
1422
+ rolesRole: "Role",
1423
+ rolesWho: "Who it is",
1424
+ rolesWhat: "What they can do",
1425
+ bizTermsTitle: "Business Terms",
1426
+ bizTermsTerm: "Term",
1427
+ bizTermsDef: "Definition",
1428
+ bizTermsNotes: "Notes",
1429
+ techTermsTitle: "Internal Technical Terms",
1430
+ techTermsTerm: "Term",
1431
+ techTermsDef: "Definition",
1432
+ techTermsWhy: "Why it exists",
1433
+ relationsTitle: "Relationships Between Concepts",
1434
+ relationsCode: "[Entity 1] \u2500\u2500\u2500 1:N \u2500\u2500\u2500\u2192 [Entity 2]\n \u2514\u2500\u2500\u2192 [Entity 3] (via [Entity 4])",
1435
+ dialogTitle: "Example Dialogue Using Domain Terms",
1436
+ dialogIntro: "This example shows how vocabulary is used in a real team conversation:",
1437
+ dialogPM: '**Product Manager**: "The client needs [Term 1] in state [State A] to be automatically converted to [Term 2] when they reach [State B]."',
1438
+ dialogDev: '**Developer**: "Understood. Does this conversion apply to all [Role 1] or only those with [action] permission?"',
1439
+ dialogPM2: '**Product Manager**: "Only for [Role 1]. [Role 2] can only see the [Term 1] but cannot convert it."',
1440
+ dialogDev2: `**Developer**: "Perfect. I'll add a conversion button on the [Term 1] view for [Role 1], visible only when in [State A]. Does the resulting [Term 2] start in [State C]?"`,
1441
+ dialogPM3: '**Product Manager**: "Yes, it starts in [State C] and needs approval from a [Role 2] to move to [State D]."',
1442
+ ambTitle: "Flagged Ambiguities",
1443
+ ambIntro: "These terms have meanings that could be confused. Pay attention to context:",
1444
+ ambTerm: "Term",
1445
+ ambConfusion: "Possible Confusion",
1446
+ ambClarification: "Clarification",
1447
+ updateTitle: "How to Update This File",
1448
+ update1: "Identify if it's an **entity**, **state**, **role**, **business term** or **technical term**.",
1449
+ update2: "Add it in the corresponding section with: definition, usage example, and technical equivalent.",
1450
+ update3: "If it has relationships with other entities, update the relationship diagram.",
1451
+ update4: `If it's ambiguous or confused with another term, add it in "Flagged Ambiguities".`,
1452
+ update5: "If a new state or flow was introduced, update the states table.",
1453
+ updateRule: "**Rule**: Every term that appears in code, APIs, UI or team conversations MUST be here. If it's not, it's a documentation bug.",
1454
+ updateIntro: "When adding a new domain term:"
1455
+ };
1456
+
1457
+ // src/generators/context/generator.ts
1458
+ registerLabels("context", "es", labels3);
1459
+ registerLabels("context", "en", labels4);
1460
+ function generate2(options) {
1461
+ const labels31 = loadLabels("context", options.language);
1462
+ const t = (key) => labels31[key] || `[${key}]`;
1463
+ const today = options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1464
+ let md = `---
1465
+ created: "2025-01-01"
1466
+ updated: "${today}"
1467
+ status: active
1468
+ completeness: "15%"
1469
+ type: ${t("fmType")}
1470
+ tags: [${t("fmTags")}]
1471
+ ---
1472
+
1473
+ # ${t("title")}
1474
+
1475
+ ${t("intro")}
1476
+
1477
+ ${t("introGap")}
1478
+
1479
+ ---
1480
+
1481
+ ## ${t("entitiesTitle")}
1482
+
1483
+ | ${t("entitiesTerm")} | ${t("entitiesDef")} | ${t("entitiesExample")} | ${t("entitiesTech")} |
1484
+ |---------|-----------|----------------|-------------------|
1485
+ | **${t("placeholder")}** | [definici\xF3n] | "ejemplo de uso" | \`[codigo]\` |
1486
+
1487
+ ## ${t("statesTitle")}
1488
+
1489
+ | ${t("statesState")} | ${t("statesMeaning")} | ${t("statesTransitions")} |
1490
+ |-------|---------|----------------------|
1491
+ | **[Estado]** | [significado] | \u2192 [otro estado] |
1492
+
1493
+ ## ${t("rolesTitle")}
1494
+
1495
+ | ${t("rolesRole")} | ${t("rolesWho")} | ${t("rolesWhat")} |
1496
+ |-----|----------|----------------|
1497
+ | **[Rol]** | [descripci\xF3n] | [acciones] |
1498
+
1499
+ ## ${t("bizTermsTitle")}
1500
+
1501
+ | ${t("bizTermsTerm")} | ${t("bizTermsDef")} | ${t("bizTermsNotes")} |
1502
+ |---------|-----------|-------|
1503
+ | **[T\xE9rmino]** | [definici\xF3n] | [notas] |
1504
+
1505
+ ## ${t("techTermsTitle")}
1506
+
1507
+ | ${t("techTermsTerm")} | ${t("techTermsDef")} | ${t("techTermsWhy")} |
1508
+ |---------|-----------|----------------|
1509
+ | **[T\xE9rmino]** | [definici\xF3n] | [raz\xF3n] |
1510
+
1511
+ ---
1512
+
1513
+ ## ${t("relationsTitle")}
1514
+
1515
+ \`\`\`
1516
+ ${t("relationsCode")}
1517
+ \`\`\`
1518
+
1519
+ ---
1520
+
1521
+ ## ${t("dialogTitle")}
1522
+
1523
+ ${t("dialogIntro")}
1524
+
1525
+ > ${t("dialogPM")}
1526
+ >
1527
+ > ${t("dialogDev")}
1528
+ >
1529
+ > ${t("dialogPM2")}
1530
+ >
1531
+ > ${t("dialogDev2")}
1532
+ >
1533
+ > ${t("dialogPM3")}
1534
+
1535
+ ---
1536
+
1537
+ ## ${t("ambTitle")}
1538
+
1539
+ ${t("ambIntro")}
1540
+
1541
+ | ${t("ambTerm")} | ${t("ambConfusion")} | ${t("ambClarification")} |
1542
+ |------|-------------------|-----------|
1543
+ | **[t\xE9rmino]** | [confusi\xF3n] | [aclaraci\xF3n] |
1544
+
1545
+ ---
1546
+
1547
+ ## ${t("updateTitle")}
1548
+
1549
+ ${t("updateIntro")}
1550
+
1551
+ 1. ${t("update1")}
1552
+ 2. ${t("update2")}
1553
+ 3. ${t("update3")}
1554
+ 4. ${t("update4")}
1555
+ 5. ${t("update5")}
1556
+
1557
+ ${t("updateRule")}
1558
+ `;
1559
+ return md;
1560
+ }
1561
+
1562
+ // src/generators/changelog/labels/es.ts
1563
+ var labels5 = {
1564
+ fmType: "changelog",
1565
+ fmTags: "changelog, releases, cambios",
1566
+ title: "Changelog",
1567
+ intro: "Todos los cambios notables de este proyecto se documentar\xE1n en este archivo.",
1568
+ format: "El formato est\xE1 basado en [Keep a Changelog](https://keepachangelog.com/es-ES/1.1.0/).",
1569
+ unreleased: "Unreleased",
1570
+ added: "Added",
1571
+ addedInitial: "Documentaci\xF3n del proyecto inicializada con `@damenor/agent-docs`",
1572
+ addedProtocol: "Agents.md como protocolo operativo para agentes de IA",
1573
+ addedContext: "Contexto de lenguaje del dominio (CONTEXT.md)",
1574
+ addedDiataxis: "Estructura de documentaci\xF3n Di\xE1taxis (tutorials, guides, reference, explanation)",
1575
+ templateTitle: "Template \u2014 C\xF3mo usar este archivo",
1576
+ whenTitle: "Cu\xE1ndo actualizar",
1577
+ whenFeature: "**Feature nueva** \u2192 `### Added`",
1578
+ whenBug: "**Bug fix** \u2192 `### Fixed`",
1579
+ whenChange: "**Cambio de comportamiento** \u2192 `### Changed`",
1580
+ whenRemove: "**Feature eliminada** \u2192 `### Removed`",
1581
+ whenSecurity: "**Fix de seguridad** \u2192 `### Security`",
1582
+ whenDep: "**Nueva dependencia** \u2192 `### Added` + explicar motivo en ADR si es significativa",
1583
+ formatTitle: "Formato",
1584
+ formatExample: "## [versi\xF3n] \u2014 YYYY-MM-DD\n\n### Added\n- Feature X que hace Y (#issue)\n\n### Fixed\n- Bug donde Z pasaba cuando W (#issue)\n\n### Changed\n- Comportamiento de V cambi\xF3 para mejorar U (#issue)",
1585
+ rulesTitle: "Reglas",
1586
+ rule1: "**Una entrada por cambio** \u2014 no agrupar cambios no relacionados.",
1587
+ rule2: "**Referenciar issues** \u2014 incluir n\xFAmero de issue/PR cuando sea posible.",
1588
+ rule3: "**Perspectiva del usuario** \u2014 describir qu\xE9 cambi\xF3 para el USUARIO, no la implementaci\xF3n.",
1589
+ rule4: "**Orden cronol\xF3gico inverso** \u2014 versi\xF3n m\xE1s reciente arriba.",
1590
+ rule5: "**No editar entradas pasadas** \u2014 una vez publicadas, son inmutables."
1591
+ };
1592
+
1593
+ // src/generators/changelog/labels/en.ts
1594
+ var labels6 = {
1595
+ fmType: "changelog",
1596
+ fmTags: "changelog, releases, changes",
1597
+ title: "Changelog",
1598
+ intro: "All notable changes to this project will be documented in this file.",
1599
+ format: "The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).",
1600
+ unreleased: "Unreleased",
1601
+ added: "Added",
1602
+ addedInitial: "Project documentation initialized with `@damenor/agent-docs`",
1603
+ addedProtocol: "Agents.md operational protocol for AI agents",
1604
+ addedContext: "Domain language context (CONTEXT.md)",
1605
+ addedDiataxis: "Di\xE1taxis documentation structure (tutorials, guides, reference, explanation)",
1606
+ templateTitle: "Template \u2014 How to use this file",
1607
+ whenTitle: "When to update",
1608
+ whenFeature: "**New feature** \u2192 `### Added`",
1609
+ whenBug: "**Bug fix** \u2192 `### Fixed`",
1610
+ whenChange: "**Behavior change** \u2192 `### Changed`",
1611
+ whenRemove: "**Removed feature** \u2192 `### Removed`",
1612
+ whenSecurity: "**Security fix** \u2192 `### Security`",
1613
+ whenDep: "**New dependency** \u2192 `### Added` + explain why in ADR if significant",
1614
+ formatTitle: "Format",
1615
+ formatExample: "## [version] \u2014 YYYY-MM-DD\n\n### Added\n- Feature X that does Y (#issue)\n\n### Fixed\n- Bug where Z happened when W (#issue)\n\n### Changed\n- Behavior of V changed to improve U (#issue)",
1616
+ rulesTitle: "Rules",
1617
+ rule1: "**One entry per change** \u2014 don't group unrelated changes.",
1618
+ rule2: "**Reference issues** \u2014 include the issue/PR number when possible.",
1619
+ rule3: "**User perspective** \u2014 describe what changed for the USER, not the implementation.",
1620
+ rule4: "**Reverse chronological** \u2014 newest version at the top.",
1621
+ rule5: "**Don't edit past entries** \u2014 once published, they're immutable."
1622
+ };
1623
+
1624
+ // src/generators/changelog/generator.ts
1625
+ registerLabels("changelog", "es", labels5);
1626
+ registerLabels("changelog", "en", labels6);
1627
+ function generate3(options) {
1628
+ const labels31 = loadLabels("changelog", options.language);
1629
+ const t = (key) => labels31[key] || `[${key}]`;
1630
+ return `---
1631
+ created: "2025-01-01"
1632
+ updated: "${options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0]}"
1633
+ type: ${t("fmType")}
1634
+ tags: [${t("fmTags")}]
1635
+ ---
1636
+
1637
+ # ${t("title")}
1638
+
1639
+ ${t("intro")}
1640
+
1641
+ ${t("format")}
1642
+
1643
+ ## [${t("unreleased")}]
1644
+
1645
+ ### ${t("added")}
1646
+ - ${t("addedInitial")}
1647
+ - ${t("addedProtocol")}
1648
+ - ${t("addedContext")}
1649
+ - ${t("addedDiataxis")}
1650
+
1651
+ ---
1652
+
1653
+ ## ${t("templateTitle")}
1654
+
1655
+ ### ${t("whenTitle")}
1656
+
1657
+ - ${t("whenFeature")}
1658
+ - ${t("whenBug")}
1659
+ - ${t("whenChange")}
1660
+ - ${t("whenRemove")}
1661
+ - ${t("whenSecurity")}
1662
+ - ${t("whenDep")}
1663
+
1664
+ ### ${t("formatTitle")}
1665
+
1666
+ \`\`\`markdown
1667
+ ${t("formatExample")}
1668
+ \`\`\`
1669
+
1670
+ ### ${t("rulesTitle")}
1671
+
1672
+ 1. ${t("rule1")}
1673
+ 2. ${t("rule2")}
1674
+ 3. ${t("rule3")}
1675
+ 4. ${t("rule4")}
1676
+ 5. ${t("rule5")}
1677
+ `;
1678
+ }
1679
+
1680
+ // src/generators/quick-start/labels/es.ts
1681
+ var labels7 = {
1682
+ fmType: "tutorial",
1683
+ fmTags: "tutorial, quick-start, inicio, setup",
1684
+ title: "Quick Start \u2014 Arrancar en 15 minutos",
1685
+ intro: "Este tutorial te lleva desde cero hasta tener el proyecto corriendo localmente. Al terminar, tendr\xE1s el servidor de desarrollo funcionando y podr\xE1s hacer tu primer cambio.",
1686
+ time: "**Tiempo estimado**",
1687
+ audience: "**Audiencia**",
1688
+ prereqTitle: "Prerrequisitos",
1689
+ prereqTool: "Herramienta",
1690
+ prereqVersion: "Versi\xF3n m\xEDnima",
1691
+ prereqVerify: "C\xF3mo verificar",
1692
+ prereqInstall: "C\xF3mo instalar",
1693
+ step1Title: "Paso 1: Clonar el repositorio",
1694
+ step1Clone: "git clone [URL_DEL_REPOSITORIO]",
1695
+ step1Cd: "cd [NOMBRE_DEL_PROYECTO]",
1696
+ step1Check: "Verificar que est\xE1s en la branch correcta:",
1697
+ step1Result: "# Deber\xEDa mostrar: * main",
1698
+ step2Title: "Paso 2: Instalar dependencias",
1699
+ step2Install: "[npm install]",
1700
+ step2Error: "Si hay errores:",
1701
+ step2Error1: "Verificar que la versi\xF3n de [Node / Python] sea la correcta.",
1702
+ step2Error2: "Borrar `[node_modules]` y `[package-lock.json]` y volver a ejecutar.",
1703
+ step2Error3: "Si persiste, ver [`troubleshooting.md`](../guides/troubleshooting.md).",
1704
+ step3Title: "Paso 3: Configurar variables de entorno",
1705
+ step3Copy: "Copiar el archivo de ejemplo:",
1706
+ step3Env: "Abrir `.env` y completar los valores necesarios. Los valores m\xEDnimos para desarrollo local son:",
1707
+ step3Ref: "Ver la referencia completa de variables en [`docs/reference/configuration.md`](../reference/configuration.md).",
1708
+ step4Title: "Paso 4: Inicializar la base de datos *(si aplica)*",
1709
+ step4Migrate: "[comando de migraci\xF3n \u2014 ej. npm run db:migrate]",
1710
+ step4Seed: "[comando de seed \u2014 ej. npm run db:seed]",
1711
+ step5Title: "Paso 5: Arrancar el servidor de desarrollo",
1712
+ step5Cmd: "[npm run dev]",
1713
+ step5Result: "Deber\xEDas ver algo como:",
1714
+ step5Open: "Abrir `http://localhost:3000` en el navegador.",
1715
+ step6Title: "Paso 6: Verificar que todo funciona",
1716
+ step6Test: "Ejecutar los tests:",
1717
+ step6TestCmd: "[npm run test]",
1718
+ step6TestFail: "Si alg\xFAn test falla:",
1719
+ step6TestFail1: "Verificar que la base de datos est\xE9 configurada correctamente.",
1720
+ step6TestFail2: "Verificar que las variables de entorno est\xE9n completas.",
1721
+ step6TestFail3: "Ver [`troubleshooting.md`](../guides/troubleshooting.md).",
1722
+ step6Lint: "Ejecutar el linter:",
1723
+ step6LintCmd: "[npm run lint]",
1724
+ nextTitle: "Siguientes pasos",
1725
+ next1: "Para configurar tu entorno completo (editor, extensiones, herramientas):",
1726
+ next2: "Para hacer tu primera contribuci\xF3n (branch \u2192 c\xF3digo \u2192 PR):",
1727
+ next3: "Para entender la arquitectura del proyecto:",
1728
+ next4: "Para conocer el vocabulario del dominio:",
1729
+ envBlock: "# Obligatorios para arrancar\nAPP_ENV=development\nAPP_PORT=3000\n[DATABASE_URL]=[URL de desarrollo local]\n\n# Opcionales (tienen defaults para desarrollo)\n[LOG_LEVEL]=debug"
1730
+ };
1731
+
1732
+ // src/generators/quick-start/labels/en.ts
1733
+ var labels8 = {
1734
+ fmType: "tutorial",
1735
+ fmTags: "tutorial, quick-start, setup",
1736
+ title: "Quick Start \u2014 Get Running in 15 Minutes",
1737
+ intro: "This tutorial takes you from zero to having the project running locally. When done, you'll have the development server working and be able to make your first change.",
1738
+ time: "**Estimated time**",
1739
+ audience: "**Audience**",
1740
+ prereqTitle: "Prerequisites",
1741
+ prereqTool: "Tool",
1742
+ prereqVersion: "Minimum Version",
1743
+ prereqVerify: "How to Verify",
1744
+ prereqInstall: "How to Install",
1745
+ step1Title: "Step 1: Clone the repository",
1746
+ step1Clone: "git clone [REPOSITORY_URL]",
1747
+ step1Cd: "cd [PROJECT_NAME]",
1748
+ step1Check: "Verify you're on the correct branch:",
1749
+ step1Result: "# Should show: * main",
1750
+ step2Title: "Step 2: Install dependencies",
1751
+ step2Install: "[npm install]",
1752
+ step2Error: "If there are errors:",
1753
+ step2Error1: "Verify that [Node / Python] version is correct.",
1754
+ step2Error2: "Delete `[node_modules]` and `[package-lock.json]` and re-run.",
1755
+ step2Error3: "If it persists, see [`troubleshooting.md`](../guides/troubleshooting.md).",
1756
+ step3Title: "Step 3: Configure environment variables",
1757
+ step3Copy: "Copy the example file:",
1758
+ step3Env: "Open `.env` and fill in the necessary values. The minimum values for local development are:",
1759
+ step3Ref: "See the full variable reference in [`docs/reference/configuration.md`](../reference/configuration.md).",
1760
+ step4Title: "Step 4: Initialize the database *(if applicable)*",
1761
+ step4Migrate: "[migration command \u2014 e.g. npm run db:migrate]",
1762
+ step4Seed: "[seed command \u2014 e.g. npm run db:seed]",
1763
+ step5Title: "Step 5: Start the development server",
1764
+ step5Cmd: "[npm run dev]",
1765
+ step5Result: "You should see something like:",
1766
+ step5Open: "Open `http://localhost:3000` in the browser.",
1767
+ step6Title: "Step 6: Verify everything works",
1768
+ step6Test: "Run the tests:",
1769
+ step6TestCmd: "[npm run test]",
1770
+ step6TestFail: "If any test fails:",
1771
+ step6TestFail1: "Verify the database is configured correctly.",
1772
+ step6TestFail2: "Verify environment variables are complete.",
1773
+ step6TestFail3: "See [`troubleshooting.md`](../guides/troubleshooting.md).",
1774
+ step6Lint: "Run the linter:",
1775
+ step6LintCmd: "[npm run lint]",
1776
+ nextTitle: "Next Steps",
1777
+ next1: "To set up your complete environment (editor, extensions, tools):",
1778
+ next2: "To make your first contribution (branch \u2192 code \u2192 PR):",
1779
+ next3: "To understand the project architecture:",
1780
+ next4: "To learn the domain vocabulary:",
1781
+ envBlock: "# Required to start\nAPP_ENV=development\nAPP_PORT=3000\n[DATABASE_URL]=[local development URL]\n\n# Optional (have defaults for development)\n[LOG_LEVEL]=debug"
1782
+ };
1783
+
1784
+ // src/generators/quick-start/generator.ts
1785
+ registerLabels("quick-start", "es", labels7);
1786
+ registerLabels("quick-start", "en", labels8);
1787
+ function generate4(options) {
1788
+ const labels31 = loadLabels("quick-start", options.language);
1789
+ const t = (key) => labels31[key] || `[${key}]`;
1790
+ const today = options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1791
+ const isEs = options.language === "es";
1792
+ let md = `---
1793
+ created: "${today}"
1794
+ status: active
1795
+ type: ${t("fmType")}
1796
+ tags: [${t("fmTags")}]
1797
+ ---
1798
+
1799
+ # ${t("title")}
1800
+
1801
+ ${t("intro")}
1802
+
1803
+ ${t("time")}: 15 minutos.
1804
+ ${t("audience")}: Developers que se incorporan al proyecto por primera vez.
1805
+
1806
+ ---
1807
+
1808
+ ## ${t("prereqTitle")}
1809
+
1810
+ Antes de empezar, necesitas tener instalado:
1811
+
1812
+ | ${t("prereqTool")} | ${t("prereqVersion")} | ${t("prereqVerify")} | ${t("prereqInstall")} |
1813
+ |------------|---------------|----------------|---------------|
1814
+ | **[Node.js / Python / etc.]** | [versi\xF3n] | \`[node --version]\` | [nodejs.org / enlace] |
1815
+ | **[Git]** | [versi\xF3n] | \`git --version\` | [git-scm.com] |
1816
+ | **[Package manager]** | [versi\xF3n] | \`[npm --version]\` | Viene con Node.js |
1817
+ | **[Editor recomendado]** | \u2014 | \u2014 | [VS Code / etc.] |
1818
+
1819
+ Si necesitas ayuda con la instalaci\xF3n completa, ver [\`environment-setup.md\`](environment-setup.md).
1820
+
1821
+ ---
1822
+
1823
+ ## ${t("step1Title")}
1824
+
1825
+ \`\`\`bash
1826
+ ${t("step1Clone")}
1827
+ ${t("step1Cd")}
1828
+ \`\`\`
1829
+
1830
+ ${t("step1Check")}
1831
+
1832
+ \`\`\`bash
1833
+ git branch
1834
+ ${t("step1Result")}
1835
+ \`\`\`
1836
+
1837
+ ---
1838
+
1839
+ ## ${t("step2Title")}
1840
+
1841
+ \`\`\`bash
1842
+ ${t("step2Install")}
1843
+ \`\`\`
1844
+
1845
+ ${isEs ? "Este comando descarga todas las dependencias del proyecto." : "This command downloads all project dependencies."} ${t("step2Error")}
1846
+
1847
+ - ${t("step2Error1")}
1848
+ - ${t("step2Error2")}
1849
+ - ${t("step2Error3")}
1850
+
1851
+ ---
1852
+
1853
+ ## ${t("step3Title")}
1854
+
1855
+ ${t("step3Copy")}
1856
+
1857
+ \`\`\`bash
1858
+ cp .env.example .env
1859
+ \`\`\`
1860
+
1861
+ ${t("step3Env")}
1862
+
1863
+ \`\`\`env
1864
+ ${t("envBlock")}
1865
+ \`\`\`
1866
+
1867
+ ${t("step3Ref")}
1868
+
1869
+ ---
1870
+
1871
+ ## ${t("step4Title")}
1872
+
1873
+ ${options.conditionCtx.hasDatabase ? `\`\`\`bash
1874
+ ${t("step4Migrate")}
1875
+ \`\`\`
1876
+
1877
+ ${isEs ? "Opcionalmente, cargar datos de prueba:" : "Optionally, load test data:"}
1878
+
1879
+ \`\`\`bash
1880
+ ${t("step4Seed")}
1881
+ \`\`\`` : `*${isEs ? "Este proyecto no usa base de datos \u2014 saltar este paso." : "This project does not use a database \u2014 skip this step."}*`}
1882
+
1883
+ ---
1884
+
1885
+ ## ${t("step5Title")}
1886
+
1887
+ \`\`\`bash
1888
+ ${t("step5Cmd")}
1889
+ \`\`\`
1890
+
1891
+ ${t("step5Result")}
1892
+
1893
+ \`\`\`
1894
+ \u2713 Servidor iniciado en http://localhost:3000
1895
+ \u2713 Hot-reload activo
1896
+ \`\`\`
1897
+
1898
+ ${t("step5Open")} ${isEs ? "Deber\xEDas ver [la p\xE1gina principal / el dashboard / la landing]." : "You should see [the main page / the dashboard / the landing]."}
1899
+
1900
+ ---
1901
+
1902
+ ## ${t("step6Title")}
1903
+
1904
+ ${t("step6Test")}
1905
+
1906
+ \`\`\`bash
1907
+ ${t("step6TestCmd")}
1908
+ \`\`\`
1909
+
1910
+ ${isEs ? "Todos deber\xEDan pasar (verde)." : "All should pass (green)."} ${t("step6TestFail")}
1911
+
1912
+ - ${t("step6TestFail1")}
1913
+ - ${t("step6TestFail2")}
1914
+ - ${t("step6TestFail3")}
1915
+
1916
+ ${t("step6Lint")}
1917
+
1918
+ \`\`\`bash
1919
+ ${t("step6LintCmd")}
1920
+ \`\`\`
1921
+
1922
+ ${isEs ? "No deber\xEDa mostrar errores." : "It should show no errors."}
1923
+
1924
+ ---
1925
+
1926
+ ## ${t("nextTitle")}
1927
+
1928
+ - ${t("next1")} [\`environment-setup.md\`](environment-setup.md).
1929
+ - ${t("next2")} [\`first-task.md\`](first-task.md).
1930
+ - ${t("next3")} [\`docs/explanation/architecture.md\`](../explanation/architecture.md).
1931
+ - ${t("next4")} [\`docs/CONTEXT.md\`](../CONTEXT.md).
1932
+ `;
1933
+ return md;
1934
+ }
1935
+
1936
+ // src/generators/api-reference/labels/es.ts
1937
+ var labels9 = {
1938
+ fmType: "reference",
1939
+ fmTags: "api, reference, endpoints, referencia",
1940
+ title: "Referencia de API",
1941
+ intro: "Documentaci\xF3n de referencia de los endpoints del proyecto.",
1942
+ convention: "> [!tip] Convenci\xF3n\n> Si la API crece a m\xE1s de 10 endpoints, convierte este archivo en una carpeta `api/` con un archivo por dominio.",
1943
+ authTitle: "Autenticaci\xF3n",
1944
+ authFlow: "**Flujo**:\n1. Cliente env\xEDa credenciales a `/auth/login`\n2. Server devuelve `{ token, refreshToken }`\n3. Cliente incluye `Authorization: Bearer <token>` en requests siguientes\n4. Si token expira, usar refresh token en `/auth/refresh`",
1945
+ endpointsTitle: "Endpoints",
1946
+ resource: "[Recurso]",
1947
+ getTitle: "`GET /api/[recurso]`",
1948
+ getDesc: "Lista recursos con paginaci\xF3n.",
1949
+ postTitle: "`POST /api/[recurso]`",
1950
+ postDesc: "Crea un nuevo recurso.",
1951
+ errorsTitle: "C\xF3digos de Error",
1952
+ rateLimitTitle: "Rate Limiting",
1953
+ rateStandard: "Standard",
1954
+ ratePremium: "Premium",
1955
+ rateHeaders: "Headers de respuesta:",
1956
+ versioningTitle: "Versionado",
1957
+ versioningDesc: "La API usa versionado en URL: `/api/v1/`, `/api/v2/`.\n\nVersiones anteriores se mantienen durante 6 meses despu\xE9s del release de una nueva versi\xF3n mayor."
1958
+ };
1959
+
1960
+ // src/generators/api-reference/labels/en.ts
1961
+ var labels10 = {
1962
+ fmType: "reference",
1963
+ fmTags: "api, reference, endpoints",
1964
+ title: "API Reference",
1965
+ intro: "Reference documentation for the project's endpoints.",
1966
+ convention: "> [!tip] Convention\n> If the API grows beyond 10 endpoints, convert this file to an `api/` folder with one file per domain.",
1967
+ authTitle: "Authentication",
1968
+ authFlow: "**Flow**:\n1. Client sends credentials to `/auth/login`\n2. Server returns `{ token, refreshToken }`\n3. Client includes `Authorization: Bearer <token>` in subsequent requests\n4. If token expires, use refresh token at `/auth/refresh`",
1969
+ endpointsTitle: "Endpoints",
1970
+ resource: "[Resource]",
1971
+ getTitle: "`GET /api/[resource]`",
1972
+ getDesc: "Lists resources with pagination.",
1973
+ postTitle: "`POST /api/[resource]`",
1974
+ postDesc: "Creates a new resource.",
1975
+ errorsTitle: "Error Codes",
1976
+ rateLimitTitle: "Rate Limiting",
1977
+ rateStandard: "Standard",
1978
+ ratePremium: "Premium",
1979
+ rateHeaders: "Response headers:",
1980
+ versioningTitle: "Versioning",
1981
+ versioningDesc: "The API uses URL versioning: `/api/v1/`, `/api/v2/`.\n\nPrevious versions are maintained for 6 months after a new major version release."
1982
+ };
1983
+
1984
+ // src/generators/api-reference/generator.ts
1985
+ registerLabels("api-reference", "es", labels9);
1986
+ registerLabels("api-reference", "en", labels10);
1987
+ function generate5(options) {
1988
+ const labels31 = loadLabels("api-reference", options.language);
1989
+ const t = (key) => labels31[key] || `[${key}]`;
1990
+ return `---
1991
+ created: "2026-05-07"
1992
+ updated: "${options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0]}"
1993
+ status: active
1994
+ type: ${t("fmType")}
1995
+ tags: [${t("fmTags")}]
1996
+ ---
1997
+
1998
+ # ${t("title")}
1999
+
2000
+ ${t("intro")}
2001
+
2002
+ ${t("convention")}
2003
+
2004
+ ## ${t("authTitle")}
2005
+
2006
+ | M\xE9todo | Descripci\xF3n | Header |
2007
+ |--------|-------------|--------|
2008
+ | Bearer Token | JWT enviado en header | \`Authorization: Bearer <token>\` |
2009
+
2010
+ ${t("authFlow")}
2011
+
2012
+ ## ${t("endpointsTitle")}
2013
+
2014
+ ### ${t("resource")}
2015
+
2016
+ #### ${t("getTitle")}
2017
+
2018
+ ${t("getDesc")}
2019
+
2020
+ **Headers**:
2021
+ | Header | Requerido | Descripci\xF3n |
2022
+ |--------|-----------|-------------|
2023
+ | \`Authorization\` | S\xED | Bearer token |
2024
+
2025
+ **Query Parameters**:
2026
+ | Param | Tipo | Default | Descripci\xF3n |
2027
+ |-------|------|---------|-------------|
2028
+ | \`page\` | number | 1 | P\xE1gina actual |
2029
+ | \`limit\` | number | 20 | Items por p\xE1gina (max 100) |
2030
+ | \`sort\` | string | \`-createdAt\` | Campo de orden (\`-\` para desc) |
2031
+
2032
+ **Response 200**:
2033
+ \`\`\`json
2034
+ {
2035
+ "data": [
2036
+ {
2037
+ "id": "string",
2038
+ "name": "string",
2039
+ "createdAt": "ISO 8601"
2040
+ }
2041
+ ],
2042
+ "meta": {
2043
+ "page": 1,
2044
+ "limit": 20,
2045
+ "total": 100
2046
+ }
2047
+ }
2048
+ \`\`\`
2049
+
2050
+ #### ${t("postTitle")}
2051
+
2052
+ ${t("postDesc")}
2053
+
2054
+ **Body**:
2055
+ \`\`\`json
2056
+ {
2057
+ "name": "string (required, max 200)",
2058
+ "description": "string (optional)"
2059
+ }
2060
+ \`\`\`
2061
+
2062
+ **Response 201**:
2063
+ \`\`\`json
2064
+ {
2065
+ "id": "string",
2066
+ "name": "string",
2067
+ "description": "string",
2068
+ "createdAt": "ISO 8601",
2069
+ "updatedAt": "ISO 8601"
2070
+ }
2071
+ \`\`\`
2072
+
2073
+ ## ${t("errorsTitle")}
2074
+
2075
+ | Status | C\xF3digo | Descripci\xF3n |
2076
+ |--------|--------|-------------|
2077
+ | 400 | \`VALIDATION_ERROR\` | Datos de entrada inv\xE1lidos |
2078
+ | 401 | \`UNAUTHORIZED\` | Token ausente o inv\xE1lido |
2079
+ | 403 | \`FORBIDDEN\` | Sin permisos para el recurso |
2080
+ | 404 | \`NOT_FOUND\` | Recurso no encontrado |
2081
+ | 409 | \`CONFLICT\` | Recurso ya existe |
2082
+ | 422 | \`UNPROCESSABLE\` | Entidad no procesable |
2083
+ | 429 | \`RATE_LIMITED\` | Demasiados requests |
2084
+ | 500 | \`INTERNAL_ERROR\` | Error interno del servidor |
2085
+
2086
+ **Formato de error**:
2087
+ \`\`\`json
2088
+ {
2089
+ "error": {
2090
+ "code": "VALIDATION_ERROR",
2091
+ "message": "Descripci\xF3n legible del error",
2092
+ "details": [
2093
+ { "field": "name", "message": "Name is required" }
2094
+ ]
2095
+ }
2096
+ }
2097
+ \`\`\`
2098
+
2099
+ ## ${t("rateLimitTitle")}
2100
+
2101
+ | Tier | Requests/minuto | Burst |
2102
+ |------|-----------------|-------|
2103
+ | ${t("rateStandard")} | 60 | 10 |
2104
+ | ${t("ratePremium")} | 300 | 50 |
2105
+
2106
+ ${t("rateHeaders")}
2107
+ - \`X-RateLimit-Limit\`: L\xEDmite por ventana
2108
+ - \`X-RateLimit-Remaining\`: Requests restantes
2109
+ - \`X-RateLimit-Reset\`: Timestamp cuando se resetea
2110
+
2111
+ ## ${t("versioningTitle")}
2112
+
2113
+ ${t("versioningDesc")}
2114
+ `;
2115
+ }
2116
+
2117
+ // src/generators/environment-setup/labels/es.ts
2118
+ var labels11 = {
2119
+ fmType: "tutorial",
2120
+ fmTags: "tutorial, environment, setup, herramientas",
2121
+ title: "Configuraci\xF3n del Entorno de Desarrollo",
2122
+ intro: "Gu\xEDa paso a paso para configurar tu entorno de desarrollo. Al terminar, tendr\xE1s todas las herramientas necesarias para trabajar en el proyecto.",
2123
+ time: "**Tiempo estimado**",
2124
+ audience: "**Audiencia**",
2125
+ osTab: "SO",
2126
+ toolTab: "Herramienta",
2127
+ versionTab: "Versi\xF3n",
2128
+ howTab: "Instalaci\xF3n",
2129
+ step1Title: "1. Lenguaje de programaci\xF3n",
2130
+ step1Desc: "El proyecto usa **[LENGUAJE]** [versi\xF3n]. Verificar versi\xF3n:",
2131
+ step1Install: "Si no lo ten\xE9s, instalar desde [enlace oficial].",
2132
+ step2Title: "2. Git",
2133
+ step2Desc: "Git es obligatorio para el control de versiones.",
2134
+ step2Check: "Verificar instalaci\xF3n:",
2135
+ step2Config: "Configurar usuario (solo la primera vez):",
2136
+ step3Title: "3. Package Manager",
2137
+ step3Desc: "El proyecto usa **[PACKAGE_MANAGER]**.",
2138
+ step3Check: "Verificar instalaci\xF3n:",
2139
+ step4Title: "4. Editor de c\xF3digo",
2140
+ step4Desc: "Recomendamos **VS Code** con las siguientes extensiones:",
2141
+ step4Ext1: "**[extensi\xF3n 1]** \u2014 [descripci\xF3n]",
2142
+ step4Ext2: "**[extensi\xF3n 2]** \u2014 [descripci\xF3n]",
2143
+ step4Ext3: "**[extensi\xF3n 3]** \u2014 [descripci\xF3n]",
2144
+ step4Ext4: "**[extensi\xF3n 4]** \u2014 [descripci\xF3n]",
2145
+ step5Title: "5. Docker (opcional)",
2146
+ step5Desc: "Si el proyecto usa Docker para desarrollo local:",
2147
+ step5Check: "Verificar instalaci\xF3n:",
2148
+ step6Title: "6. Base de datos (opcional)",
2149
+ step6Desc: "Si el proyecto usa base de datos local:",
2150
+ step6Install: "**[Herramienta de DB]** \u2014 instalar desde [enlace]",
2151
+ step6Client: "Cliente recomendado: **[cliente de DB]** ([enlace])",
2152
+ verifyTitle: "Verificaci\xF3n final",
2153
+ verifyDesc: "Ejecutar estos comandos para confirmar que todo funciona:",
2154
+ verifyCmd1: "[comando de verificaci\xF3n 1]",
2155
+ verifyCmd2: "[comando de verificaci\xF3n 2]",
2156
+ verifyCmd3: "[comando de verificaci\xF3n 3]",
2157
+ nextTitle: "Siguientes pasos",
2158
+ next1: "Para arrancar el proyecto por primera vez: [`quick-start.md`](quick-start.md)",
2159
+ next2: "Para hacer tu primera contribuci\xF3n (branch \u2192 c\xF3digo \u2192 PR): [`first-task.md`](first-task.md)"
2160
+ };
2161
+
2162
+ // src/generators/environment-setup/labels/en.ts
2163
+ var labels12 = {
2164
+ fmType: "tutorial",
2165
+ fmTags: "tutorial, environment, setup, tools",
2166
+ title: "Development Environment Setup",
2167
+ intro: "Step-by-step guide to configure your development environment. When done, you'll have all the tools needed to work on the project.",
2168
+ time: "**Estimated time**",
2169
+ audience: "**Audience**",
2170
+ osTab: "OS",
2171
+ toolTab: "Tool",
2172
+ versionTab: "Version",
2173
+ howTab: "Installation",
2174
+ step1Title: "1. Programming Language",
2175
+ step1Desc: "The project uses **[LANGUAGE]** [version]. Verify version:",
2176
+ step1Install: "If not installed, install from [official link].",
2177
+ step2Title: "2. Git",
2178
+ step2Desc: "Git is required for version control.",
2179
+ step2Check: "Verify installation:",
2180
+ step2Config: "Configure user (first time only):",
2181
+ step3Title: "3. Package Manager",
2182
+ step3Desc: "The project uses **[PACKAGE_MANAGER]**.",
2183
+ step3Check: "Verify installation:",
2184
+ step4Title: "4. Code Editor",
2185
+ step4Desc: "We recommend **VS Code** with the following extensions:",
2186
+ step4Ext1: "**[extension 1]** \u2014 [description]",
2187
+ step4Ext2: "**[extension 2]** \u2014 [description]",
2188
+ step4Ext3: "**[extension 3]** \u2014 [description]",
2189
+ step4Ext4: "**[extension 4]** \u2014 [description]",
2190
+ step5Title: "5. Docker (optional)",
2191
+ step5Desc: "If the project uses Docker for local development:",
2192
+ step5Check: "Verify installation:",
2193
+ step6Title: "6. Database (optional)",
2194
+ step6Desc: "If the project uses a local database:",
2195
+ step6Install: "**[DB Tool]** \u2014 install from [link]",
2196
+ step6Client: "Recommended client: **[DB client]** ([link])",
2197
+ verifyTitle: "Final Verification",
2198
+ verifyDesc: "Run these commands to confirm everything works:",
2199
+ verifyCmd1: "[verification command 1]",
2200
+ verifyCmd2: "[verification command 2]",
2201
+ verifyCmd3: "[verification command 3]",
2202
+ nextTitle: "Next Steps",
2203
+ next1: "To start the project for the first time: [`quick-start.md`](quick-start.md)",
2204
+ next2: "To make your first contribution (branch \u2192 code \u2192 PR): [`first-task.md`](first-task.md)"
2205
+ };
2206
+
2207
+ // src/generators/environment-setup/generator.ts
2208
+ registerLabels("environment-setup", "es", labels11);
2209
+ registerLabels("environment-setup", "en", labels12);
2210
+ function generate6(options) {
2211
+ const labels31 = loadLabels("environment-setup", options.language);
2212
+ const t = (key) => labels31[key] || `[${key}]`;
2213
+ const today = options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2214
+ return `---
2215
+ created: "${today}"
2216
+ status: active
2217
+ type: ${t("fmType")}
2218
+ tags: [${t("fmTags")}]
2219
+ ---
2220
+
2221
+ # ${t("title")}
2222
+
2223
+ ${t("intro")}
2224
+
2225
+ ${t("time")}: 30-60 minutos.
2226
+ ${t("audience")}: Developers que se incorporan al proyecto.
2227
+
2228
+ ---
2229
+
2230
+ | ${t("osTab")} | ${t("toolTab")} | ${t("versionTab")} | ${t("howTab")} |
2231
+ |-----|-------|--------|-----------|
2232
+ | Windows / Mac / Linux | **[Lenguaje]** | [versi\xF3n] | [enlace oficial] |
2233
+ | Windows / Mac / Linux | **Git** | 2.40+ | [git-scm.com](https://git-scm.com) |
2234
+ | Windows / Mac / Linux | **[Package Manager]** | [versi\xF3n] | Viene con el lenguaje |
2235
+ | Windows / Mac / Linux | **VS Code** | Latest | [code.visualstudio.com](https://code.visualstudio.com) |
2236
+
2237
+ ---
2238
+
2239
+ ## ${t("step1Title")}
2240
+
2241
+ ${t("step1Desc")}
2242
+
2243
+ \`\`\`bash
2244
+ [comando para verificar versi\xF3n \u2014 ej. node --version]
2245
+ \`\`\`
2246
+
2247
+ ${t("step1Install")}
2248
+
2249
+ ---
2250
+
2251
+ ## ${t("step2Title")}
2252
+
2253
+ ${t("step2Desc")}
2254
+
2255
+ ${t("step2Check")}
2256
+
2257
+ \`\`\`bash
2258
+ git --version
2259
+ # Deber\xEDa mostrar: git version 2.40+
2260
+ \`\`\`
2261
+
2262
+ ${t("step2Config")}
2263
+
2264
+ \`\`\`bash
2265
+ git config --global user.name "Tu Nombre"
2266
+ git config --global user.email "tu@email.com"
2267
+ \`\`\`
2268
+
2269
+ ---
2270
+
2271
+ ## ${t("step3Title")}
2272
+
2273
+ ${t("step3Desc")}
2274
+
2275
+ ${t("step3Check")}
2276
+
2277
+ \`\`\`bash
2278
+ [npm --version]
2279
+ # Deber\xEDa mostrar: [versi\xF3n esperada]
2280
+ \`\`\`
2281
+
2282
+ ---
2283
+
2284
+ ## ${t("step4Title")}
2285
+
2286
+ ${t("step4Desc")}
2287
+
2288
+ - ${t("step4Ext1")}
2289
+ - ${t("step4Ext2")}
2290
+ - ${t("step4Ext3")}
2291
+ - ${t("step4Ext4")}
2292
+
2293
+ ---
2294
+
2295
+ ${options.conditionCtx.hasDocker ? `## ${t("step5Title")}
2296
+
2297
+ ${t("step5Desc")}
2298
+
2299
+ ${t("step5Check")}
2300
+
2301
+ \`\`\`bash
2302
+ docker --version
2303
+ docker compose version
2304
+ \`\`\`
2305
+ ` : ""}
2306
+ ---
2307
+
2308
+ ${options.conditionCtx.hasDatabase ? `## ${t("step6Title")}
2309
+
2310
+ ${t("step6Desc")}
2311
+
2312
+ - ${t("step6Install")}
2313
+ - ${t("step6Client")}
2314
+ ` : ""}
2315
+ ---
2316
+
2317
+ ## ${t("verifyTitle")}
2318
+
2319
+ ${t("verifyDesc")}
2320
+
2321
+ \`\`\`bash
2322
+ ${t("verifyCmd1")}
2323
+ ${t("verifyCmd2")}
2324
+ ${t("verifyCmd3")}
2325
+ \`\`\`
2326
+
2327
+ ---
2328
+
2329
+ ## ${t("nextTitle")}
2330
+
2331
+ - ${t("next1")}
2332
+ - ${t("next2")}
2333
+ `;
2334
+ }
2335
+
2336
+ // src/generators/first-task/labels/es.ts
2337
+ var labels13 = {
2338
+ fmType: "tutorial",
2339
+ fmTags: "tutorial, first-task, contribucion",
2340
+ title: "Primera Tarea \u2014 Tu primera contribuci\xF3n",
2341
+ intro: "Este tutorial te gu\xEDa en tu primera contribuci\xF3n: desde elegir una tarea hasta mergear el PR. Al terminar, habr\xE1s completado el flujo completo de trabajo.",
2342
+ time: "**Tiempo estimado**",
2343
+ audience: "**Audiencia**",
2344
+ prereq: "Haber completado [`quick-start.md`](quick-start.md) y [`environment-setup.md`](environment-setup.md).",
2345
+ step1: "1. Elegir una tarea",
2346
+ step1Good: "Buenas primeras tareas: **issues etiquetados**",
2347
+ step2: "2. Crear una branch",
2348
+ step2Desc: "Siempre crear una branch desde `main`:",
2349
+ step3: "3. Implementar",
2350
+ step3Tests: "Asegurate de que los tests pasen:",
2351
+ step3Lint: "Y que el linter est\xE9 limpio:",
2352
+ step4: "4. Commitear los cambios",
2353
+ step4Format: "Usar Conventional Commits en espa\xF1ol:",
2354
+ step5: "5. Crear un Pull Request",
2355
+ step5Desc: "Push de la branch y crear PR en GitHub.",
2356
+ step5Template: "**Template de PR**:",
2357
+ step6: "6. Revisi\xF3n de c\xF3digo",
2358
+ step6Desc: "Un maintainer revisar\xE1 tu PR.",
2359
+ checklist: "**Checklist antes de enviar el PR**:",
2360
+ next: "Felicidades",
2361
+ nextDesc: "Completaste tu primera contribuci\xF3n. Ahora pod\xE9s tomar tareas m\xE1s grandes."
2362
+ };
2363
+
2364
+ // src/generators/first-task/labels/en.ts
2365
+ var labels14 = {
2366
+ fmType: "tutorial",
2367
+ fmTags: "tutorial, first-task, contribution",
2368
+ title: "First Task \u2014 Your First Contribution",
2369
+ intro: "This tutorial guides you through your first contribution: from choosing a task to merging the PR. When done, you'll have completed the full workflow.",
2370
+ time: "**Estimated time**",
2371
+ audience: "**Audience**",
2372
+ prereq: "Completed [`quick-start.md`](quick-start.md) and [`environment-setup.md`](environment-setup.md).",
2373
+ step1: "1. Choose a task",
2374
+ step1Good: "Good first issues: **tagged issues**",
2375
+ step2: "2. Create a branch",
2376
+ step2Desc: "Always create a branch from `main`:",
2377
+ step3: "3. Implement",
2378
+ step3Tests: "Make sure tests pass:",
2379
+ step3Lint: "And the linter is clean:",
2380
+ step4: "4. Commit changes",
2381
+ step4Format: "Use Conventional Commits in English:",
2382
+ step5: "5. Create a Pull Request",
2383
+ step5Desc: "Push the branch and create PR on GitHub.",
2384
+ step5Template: "**PR Template**:",
2385
+ step6: "6. Code Review",
2386
+ step6Desc: "A maintainer will review your PR.",
2387
+ checklist: "**Checklist before submitting PR**:",
2388
+ next: "Congratulations",
2389
+ nextDesc: "You completed your first contribution. Now you can take on larger tasks."
2390
+ };
2391
+
2392
+ // src/generators/first-task/generator.ts
2393
+ registerLabels("first-task", "es", labels13);
2394
+ registerLabels("first-task", "en", labels14);
2395
+ function generate7(options) {
2396
+ const labels31 = loadLabels("first-task", options.language);
2397
+ const t = (key) => labels31[key] || `[${key}]`;
2398
+ const today = options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2399
+ return `---
2400
+ created: "${today}"
2401
+ status: active
2402
+ type: ${t("fmType")}
2403
+ tags: [${t("fmTags")}]
2404
+ ---
2405
+
2406
+ # ${t("title")}
2407
+
2408
+ ${t("intro")}
2409
+
2410
+ ${t("time")}: 1-2 horas.
2411
+ ${t("audience")}: Developers nuevos en el proyecto.
2412
+
2413
+ > **Prerrequisitos**: ${t("prereq")}
2414
+
2415
+ ---
2416
+
2417
+ ## ${t("step1")}
2418
+
2419
+ ${t("step1Good")}:
2420
+ - \`good first issue\` \u2014 tareas introductorias
2421
+ - \`help wanted\` \u2014 tareas que necesitan ayuda
2422
+ - \`bug\` \u2014 bugs confirmados
2423
+
2424
+ Asignate la tarea en GitHub y movela a "In Progress".
2425
+
2426
+ ---
2427
+
2428
+ ## ${t("step2")}
2429
+
2430
+ ${t("step2Desc")}
2431
+
2432
+ \`\`\`bash
2433
+ git checkout main
2434
+ git pull origin main
2435
+ git checkout -b feature/mi-primera-tarea
2436
+ \`\`\`
2437
+
2438
+ ---
2439
+
2440
+ ## ${t("step3")}
2441
+
2442
+ ${t("step3Tests")}
2443
+
2444
+ \`\`\`bash
2445
+ [npm run test]
2446
+ \`\`\`
2447
+
2448
+ ${t("step3Lint")}
2449
+
2450
+ \`\`\`bash
2451
+ [npm run lint]
2452
+ \`\`\`
2453
+
2454
+ ---
2455
+
2456
+ ## ${t("step4")}
2457
+
2458
+ ${t("step4Format")}
2459
+
2460
+ \`\`\`bash
2461
+ git add -A
2462
+ git commit -m "feat(scope): descripci\xF3n corta de lo que hiciste"
2463
+ \`\`\`
2464
+
2465
+ ---
2466
+
2467
+ ## ${t("step5")}
2468
+
2469
+ ${t("step5Desc")}
2470
+
2471
+ \`\`\`bash
2472
+ git push origin feature/mi-primera-tarea
2473
+ \`\`\`
2474
+
2475
+ ${t("step5Template")}
2476
+
2477
+ \`\`\`markdown
2478
+ ## Descripci\xF3n
2479
+ [Qu\xE9 cambia y por qu\xE9]
2480
+
2481
+ ## Tipo de cambio
2482
+ - [ ] Bug fix
2483
+ - [ ] Feature nueva
2484
+ - [ ] Refactor
2485
+ - [ ] Documentaci\xF3n
2486
+
2487
+ ## C\xF3mo probarlo
2488
+ 1. [Paso 1]
2489
+ 2. [Paso 2]
2490
+
2491
+ ## Screenshots (si aplica)
2492
+ \`\`\`
2493
+
2494
+ ---
2495
+
2496
+ ## ${t("step6")}
2497
+
2498
+ ${t("step6Desc")}
2499
+ - Respond\xE9 a los comentarios
2500
+ - Hac\xE9 los cambios solicitados
2501
+ - El PR se mergea cuando recibe approve
2502
+
2503
+ ${t("checklist")}
2504
+ - [ ] Tests pasan
2505
+ - [ ] Linter limpio
2506
+ - [ ] PR description completa
2507
+ - [ ] No hay secrets commiteados
2508
+ - [ ] La branch est\xE1 actualizada con \`main\`
2509
+
2510
+ ---
2511
+
2512
+ ## ${t("next")} \u{1F389}
2513
+
2514
+ ${t("nextDesc")}
2515
+ - Ver el [roadmap](../product/roadmap.md) para features planeadas
2516
+ - Leer la [arquitectura](../explanation/architecture.md) para entender el sistema
2517
+ `;
2518
+ }
2519
+
2520
+ // src/generators/deployment/labels/es.ts
2521
+ var labels15 = {
2522
+ fmType: "guide",
2523
+ fmTags: "guide, deploy, production",
2524
+ title: "Gu\xEDa de Deployment",
2525
+ intro: "Procedimiento para desplegar la aplicaci\xF3n en producci\xF3n.",
2526
+ envTitle: "Entornos",
2527
+ envDev: "Desarrollo",
2528
+ envDevDesc: "Local, hot-reload activo.",
2529
+ envStaging: "Staging",
2530
+ envStagingDesc: "Pre-producci\xF3n, datos de prueba.",
2531
+ envProd: "Producci\xF3n",
2532
+ envProdDesc: "Entorno live, datos reales.",
2533
+ prereq: "Prerrequisitos",
2534
+ prereqItems: "Acceso a [plataforma de deploy]. Variables de entorno configuradas.",
2535
+ step1: "1. Preparar el build",
2536
+ step1Desc: "Ejecutar el build de producci\xF3n:",
2537
+ step2: "2. Verificar tests",
2538
+ step2Desc: "Todos los tests deben pasar antes de deployar:",
2539
+ step3: "3. Deploy",
2540
+ step3Desc: "Ejecutar el comando de deploy:",
2541
+ step4: "4. Verificar health",
2542
+ step4Desc: "Confirmar que la aplicaci\xF3n responde:",
2543
+ rollback: "Rollback",
2544
+ rollbackDesc: "Si algo falla, revertir al \xFAltimo deploy estable:",
2545
+ monitoring: "Monitoreo post-deploy",
2546
+ monitoringDesc: "Verificar m\xE9tricas en [dashboard de monitoreo]."
2547
+ };
2548
+
2549
+ // src/generators/deployment/labels/en.ts
2550
+ var labels16 = {
2551
+ fmType: "guide",
2552
+ fmTags: "guide, deploy, production",
2553
+ title: "Deployment Guide",
2554
+ intro: "Procedure to deploy the application to production.",
2555
+ envTitle: "Environments",
2556
+ envDev: "Development",
2557
+ envDevDesc: "Local, hot-reload active.",
2558
+ envStaging: "Staging",
2559
+ envStagingDesc: "Pre-production, test data.",
2560
+ envProd: "Production",
2561
+ envProdDesc: "Live environment, real data.",
2562
+ prereq: "Prerequisites",
2563
+ prereqItems: "Access to [deploy platform]. Environment variables configured.",
2564
+ step1: "1. Prepare the build",
2565
+ step1Desc: "Run the production build:",
2566
+ step2: "2. Verify tests",
2567
+ step2Desc: "All tests must pass before deploying:",
2568
+ step3: "3. Deploy",
2569
+ step3Desc: "Run the deploy command:",
2570
+ step4: "4. Verify health",
2571
+ step4Desc: "Confirm the application responds:",
2572
+ rollback: "Rollback",
2573
+ rollbackDesc: "If something fails, revert to the last stable deploy:",
2574
+ monitoring: "Post-deploy Monitoring",
2575
+ monitoringDesc: "Check metrics at [monitoring dashboard].",
2576
+ dockerDeploy: "Docker",
2577
+ dockerBuild: "docker build -t app .",
2578
+ dockerRun: "docker compose up -d",
2579
+ ciDesc: "CI/CD pipeline \u2014 el deploy se ejecuta autom\xE1ticamente al mergear a main.",
2580
+ healthCheck: "curl https://[url]/health \u2192 200 OK"
2581
+ };
2582
+
2583
+ // src/generators/deployment/generator.ts
2584
+ registerLabels("deployment", "es", labels15);
2585
+ registerLabels("deployment", "en", labels16);
2586
+ function generate8(options) {
2587
+ const t = (k) => loadLabels("deployment", options.language)[k] || `[${k}]`;
2588
+ const today = options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2589
+ const hasDocker = options.conditionCtx.hasDocker;
2590
+ const hasCI = options.conditionCtx.hasCI;
2591
+ return `---
2592
+ created: "${today}"
2593
+ status: active
2594
+ type: ${t("fmType")}
2595
+ tags: [${t("fmTags")}]
2596
+ ---
2597
+
2598
+ # ${t("title")}
2599
+
2600
+ ${t("intro")}
2601
+
2602
+ ## ${t("envTitle")}
2603
+
2604
+ | Entorno | URL | Rama | Descripci\xF3n |
2605
+ |---------|-----|------|-------------|
2606
+ | ${t("envDev")} | http://localhost:3000 | \u2014 | ${t("envDevDesc")} |
2607
+ | ${t("envStaging")} | [URL de staging] | \`develop\` | ${t("envStagingDesc")} |
2608
+ | ${t("envProd")} | [URL de producci\xF3n] | \`main\` | ${t("envProdDesc")} |
2609
+
2610
+ ## ${t("prereq")}
2611
+
2612
+ - ${t("prereqItems")}
2613
+
2614
+ ## ${t("step1")}
2615
+
2616
+ ${t("step1Desc")}
2617
+
2618
+ \`\`\`bash
2619
+ [comando de build]
2620
+ \`\`\`
2621
+
2622
+ ## ${t("step2")}
2623
+
2624
+ ${t("step2Desc")}
2625
+
2626
+ \`\`\`bash
2627
+ [comando de test]
2628
+ \`\`\`
2629
+ ${hasDocker ? `
2630
+ ## ${t("dockerDeploy")}
2631
+
2632
+ \`\`\`bash
2633
+ ${t("dockerBuild")}
2634
+ ${t("dockerRun")}
2635
+ \`\`\`
2636
+ ` : ""}
2637
+ ## ${t("step3")}
2638
+
2639
+ ${t("step3Desc")}
2640
+ ${hasCI ? `
2641
+ > \u2139\uFE0F ${t("ciDesc")}
2642
+ ` : `
2643
+ \`\`\`bash
2644
+ [comando de deploy manual]
2645
+ \`\`\`
2646
+ `}
2647
+ ## ${t("step4")}
2648
+
2649
+ ${t("step4Desc")}
2650
+
2651
+ \`\`\`bash
2652
+ ${t("healthCheck")}
2653
+ \`\`\`
2654
+
2655
+ ## ${t("rollback")}
2656
+
2657
+ ${t("rollbackDesc")}
2658
+
2659
+ \`\`\`bash
2660
+ [comando de rollback]
2661
+ \`\`\`
2662
+
2663
+ ## ${t("monitoring")}
2664
+
2665
+ ${t("monitoringDesc")}
2666
+ `;
2667
+ }
2668
+
2669
+ // src/generators/troubleshooting/labels/es.ts
2670
+ var labels17 = {
2671
+ fmType: "guide",
2672
+ fmTags: "guide, troubleshooting, debugging",
2673
+ title: "Gu\xEDa de Troubleshooting",
2674
+ intro: "Soluciones a problemas comunes durante el desarrollo.",
2675
+ prob1: "Problema 1",
2676
+ prob1Desc: "[Descripci\xF3n del problema com\xFAn #1]",
2677
+ prob1Fix: "[Soluci\xF3n #1]",
2678
+ prob2: "Problema 2",
2679
+ prob2Desc: "[Descripci\xF3n del problema com\xFAn #2]",
2680
+ prob2Fix: "[Soluci\xF3n #2]",
2681
+ prob3: "Problema 3",
2682
+ prob3Desc: "[Descripci\xF3n del problema com\xFAn #3]",
2683
+ prob3Fix: "[Soluci\xF3n #3]",
2684
+ logs: "C\xF3mo obtener logs",
2685
+ logsDesc: "Para debuggear, aumentar el nivel de logs:",
2686
+ support: "\xBFNo encontraste la soluci\xF3n?",
2687
+ supportDesc: "Crear un issue en GitHub con logs y pasos para reproducir."
2688
+ };
2689
+ var en = {
2690
+ title: "Troubleshooting Guide",
2691
+ intro: "Solutions to common development problems.",
2692
+ prob1: "Problem 1",
2693
+ prob1Desc: "[Description of common problem #1]",
2694
+ prob1Fix: "[Solution #1]",
2695
+ prob2: "Problem 2",
2696
+ prob2Desc: "[Description of common problem #2]",
2697
+ prob2Fix: "[Solution #2]",
2698
+ prob3: "Problem 3",
2699
+ prob3Desc: "[Description of common problem #3]",
2700
+ prob3Fix: "[Solution #3]",
2701
+ logs: "How to get logs",
2702
+ logsDesc: "To debug, increase log level:",
2703
+ support: "Didn't find a solution?",
2704
+ supportDesc: "Create a GitHub issue with logs and reproduction steps.",
2705
+ fmType: "guide",
2706
+ fmTags: "guide, troubleshooting, debugging"
2707
+ };
2708
+
2709
+ // src/generators/troubleshooting/generator.ts
2710
+ registerLabels("troubleshooting", "es", labels17);
2711
+ registerLabels("troubleshooting", "en", { ...labels17, ...en });
2712
+ function generate9(options) {
2713
+ const t = (k) => loadLabels("troubleshooting", options.language)[k] || `[${k}]`;
2714
+ const today = options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2715
+ return `---
2716
+ created: "${today}"
2717
+ status: active
2718
+ type: ${t("fmType")}
2719
+ tags: [${t("fmTags")}]
2720
+ ---
2721
+
2722
+ # ${t("title")}
2723
+
2724
+ ${t("intro")}
2725
+
2726
+ ---
2727
+
2728
+ ## ${t("prob1")}
2729
+
2730
+ **S\xEDntoma**: ${t("prob1Desc")}
2731
+
2732
+ **Soluci\xF3n**: ${t("prob1Fix")}
2733
+
2734
+ ---
2735
+
2736
+ ## ${t("prob2")}
2737
+
2738
+ **S\xEDntoma**: ${t("prob2Desc")}
2739
+
2740
+ **Soluci\xF3n**: ${t("prob2Fix")}
2741
+
2742
+ ---
2743
+
2744
+ ## ${t("prob3")}
2745
+
2746
+ **S\xEDntoma**: ${t("prob3Desc")}
2747
+
2748
+ **Soluci\xF3n**: ${t("prob3Fix")}
2749
+
2750
+ ---
2751
+
2752
+ ## ${t("logs")}
2753
+
2754
+ ${t("logsDesc")}
2755
+
2756
+ \`\`\`bash
2757
+ [comando para ver logs]
2758
+ \`\`\`
2759
+
2760
+ ---
2761
+
2762
+ ## ${t("support")}
2763
+
2764
+ ${t("supportDesc")}
2765
+ `;
2766
+ }
2767
+
2768
+ // src/generators/runbooks/labels/es.ts
2769
+ var labels18 = {
2770
+ fmType: "how-to",
2771
+ fmTags: "runbook, operations, incident",
2772
+ title: "Runbook: [NOMBRE DEL PROCEDIMIENTO]",
2773
+ intro: "Procedimiento operativo para resolver [incidente].",
2774
+ owner: "Owner",
2775
+ severity: "Severidad",
2776
+ time: "Tiempo estimado",
2777
+ prereq: "Prerrequisitos",
2778
+ steps: "Pasos",
2779
+ verification: "Verificaci\xF3n",
2780
+ rollback: "Rollback",
2781
+ notes: "Notas"
2782
+ };
2783
+ var en2 = {
2784
+ title: "Runbook: [PROCEDURE NAME]",
2785
+ intro: "Operational procedure to resolve [incident].",
2786
+ owner: "Owner",
2787
+ severity: "Severity",
2788
+ time: "Estimated time",
2789
+ prereq: "Prerequisites",
2790
+ steps: "Steps",
2791
+ verification: "Verification",
2792
+ rollback: "Rollback",
2793
+ notes: "Notes",
2794
+ fmType: "how-to",
2795
+ fmTags: "runbook, operations, incident"
2796
+ };
2797
+
2798
+ // src/generators/runbooks/generator.ts
2799
+ registerLabels("runbooks", "es", labels18);
2800
+ registerLabels("runbooks", "en", { ...labels18, ...en2 });
2801
+ function generate10(options) {
2802
+ const t = (k) => loadLabels("runbooks", options.language)[k] || `[${k}]`;
2803
+ const today = options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2804
+ return `---
2805
+ created: "${today}"
2806
+ status: active
2807
+ type: ${t("fmType")}
2808
+ tags: [${t("fmTags")}]
2809
+ ---
2810
+
2811
+ # ${t("title")}
2812
+
2813
+ ${t("intro")}
2814
+
2815
+ | Campo | Valor |
2816
+ |-------|-------|
2817
+ | ${t("owner")} | [Equipo responsable] |
2818
+ | ${t("severity")} | [Cr\xEDtica / Alta / Media / Baja] |
2819
+ | ${t("time")} | [X minutos] |
2820
+
2821
+ ## ${t("prereq")}
2822
+ - [Requisito 1]
2823
+ - [Requisito 2]
2824
+
2825
+ ## ${t("steps")}
2826
+ 1. [Paso 1]
2827
+ 2. [Paso 2]
2828
+ 3. [Paso 3]
2829
+
2830
+ ## ${t("verification")}
2831
+ - [C\xF3mo verificar que el procedimiento funcion\xF3]
2832
+
2833
+ ## ${t("rollback")}
2834
+ - [Pasos para revertir si algo falla]
2835
+
2836
+ ## ${t("notes")}
2837
+ - [Notas adicionales]
2838
+ `;
2839
+ }
2840
+
2841
+ // src/generators/configuration/labels/es.ts
2842
+ var labels19 = {
2843
+ fmType: "reference",
2844
+ fmTags: "configuration, reference, env",
2845
+ title: "Referencia de Configuraci\xF3n",
2846
+ intro: "Referencia completa de todas las variables de configuraci\xF3n del proyecto.",
2847
+ required: "Variables obligatorias",
2848
+ optional: "Variables opcionales",
2849
+ envName: "Variable",
2850
+ envDesc: "Descripci\xF3n",
2851
+ envDefault: "Default",
2852
+ envRequired: "Requerida",
2853
+ secrets: "Gesti\xF3n de secretos",
2854
+ secretsDesc: "Nunca commitear valores reales al repositorio.",
2855
+ dotenv: "Archivos .env"
2856
+ };
2857
+ var en3 = {
2858
+ fmType: "reference",
2859
+ fmTags: "configuration, reference, env",
2860
+ title: "Configuration Reference",
2861
+ intro: "Complete reference of all project configuration variables.",
2862
+ required: "Required Variables",
2863
+ optional: "Optional Variables",
2864
+ envName: "Variable",
2865
+ envDesc: "Description",
2866
+ envDefault: "Default",
2867
+ envRequired: "Required",
2868
+ secrets: "Secret Management",
2869
+ secretsDesc: "Never commit real values to the repository.",
2870
+ dotenv: ".env Files"
2871
+ };
2872
+
2873
+ // src/generators/configuration/generator.ts
2874
+ registerLabels("configuration", "es", labels19);
2875
+ registerLabels("configuration", "en", { ...labels19, ...en3 });
2876
+ function generate11(options) {
2877
+ const t = (k) => loadLabels("configuration", options.language)[k] || `[${k}]`;
2878
+ const today = options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2879
+ return `---
2880
+ created: "${today}"
2881
+ status: active
2882
+ type: ${t("fmType")}
2883
+ tags: [${t("fmTags")}]
2884
+ ---
2885
+
2886
+ # ${t("title")}
2887
+
2888
+ ${t("intro")}
2889
+
2890
+ ## ${t("required")}
2891
+
2892
+ | ${t("envName")} | ${t("envDesc")} | ${t("envDefault")} | ${t("envRequired")} |
2893
+ |-------|-----------|--------|--------|
2894
+ | \`APP_ENV\` | Entorno actual | \`development\` | S\xED |
2895
+ | \`APP_PORT\` | Puerto | \`3000\` | No |
2896
+ | \`[VARIABLE_1]\` | [Descripci\xF3n] | \u2014 | S\xED |
2897
+ | \`[VARIABLE_2]\` | [Descripci\xF3n] | [default] | S\xED |
2898
+
2899
+ ## ${t("optional")}
2900
+
2901
+ | ${t("envName")} | ${t("envDesc")} | ${t("envDefault")} | ${t("envRequired")} |
2902
+ |-------|-----------|--------|--------|
2903
+ | \`LOG_LEVEL\` | Nivel de log | \`debug\` | No |
2904
+ | \`[VARIABLE_3]\` | [Descripci\xF3n] | [default] | No |
2905
+
2906
+ ## ${t("secrets")}
2907
+
2908
+ ${t("secretsDesc")}
2909
+
2910
+ - Usar \`.env.example\` como template para documentar qu\xE9 variables existen.
2911
+ - En CI/CD, inyectar secretos v\xEDa [GitHub Secrets / Vault / etc.].
2912
+
2913
+ ## ${t("dotenv")}
2914
+
2915
+ | Archivo | Prop\xF3sito | \xBFCommiteado? |
2916
+ |---------|----------|-------------|
2917
+ | \`.env.example\` | Template documentando todas las variables | \u2705 S\xED |
2918
+ | \`.env\` | Valores locales de desarrollo | \u274C No |
2919
+ | \`.env.production\` | Valores de producci\xF3n | \u274C No |
2920
+ `;
2921
+ }
2922
+
2923
+ // src/generators/infrastructure/labels/es.ts
2924
+ var labels20 = {
2925
+ fmType: "reference",
2926
+ fmTags: "infrastructure, reference, deploy",
2927
+ title: "Infraestructura",
2928
+ intro: "Documentaci\xF3n de la infraestructura del proyecto.",
2929
+ hosting: "Hosting",
2930
+ hostingDesc: "**[Proveedor de hosting]** \u2014 [plan/regi\xF3n]",
2931
+ ci: "CI/CD",
2932
+ ciDesc: "**[Plataforma de CI]** \u2014 [plan]",
2933
+ db: "Base de datos",
2934
+ dbDesc: "**[Motor de base de datos]** \u2014 [versi\xF3n/plan]",
2935
+ cache: "Cache",
2936
+ cacheDesc: "**[Redis / Memcached / etc.]**",
2937
+ storage: "Almacenamiento",
2938
+ storageDesc: "**[S3 / Cloud Storage / etc.]**",
2939
+ monitoring: "Monitoreo",
2940
+ monitoringDesc: "**[Herramienta de monitoreo]**",
2941
+ domains: "Dominios",
2942
+ scaling: "Escalabilidad"
2943
+ };
2944
+ var en4 = {
2945
+ fmType: "reference",
2946
+ fmTags: "infrastructure, reference, deploy",
2947
+ title: "Infrastructure",
2948
+ intro: "Project infrastructure documentation.",
2949
+ hosting: "Hosting",
2950
+ hostingDesc: "**[Hosting provider]** \u2014 [plan/region]",
2951
+ ci: "CI/CD",
2952
+ ciDesc: "**[CI platform]** \u2014 [plan]",
2953
+ db: "Database",
2954
+ dbDesc: "**[Database engine]** \u2014 [version/plan]",
2955
+ cache: "Cache",
2956
+ cacheDesc: "**[Redis / Memcached / etc.]**",
2957
+ storage: "Storage",
2958
+ storageDesc: "**[S3 / Cloud Storage / etc.]**",
2959
+ monitoring: "Monitoring",
2960
+ monitoringDesc: "**[Monitoring tool]**",
2961
+ domains: "Domains",
2962
+ scaling: "Scalability"
2963
+ };
2964
+
2965
+ // src/generators/infrastructure/generator.ts
2966
+ registerLabels("infrastructure", "es", labels20);
2967
+ registerLabels("infrastructure", "en", { ...labels20, ...en4 });
2968
+ function generate12(options) {
2969
+ const t = (k) => loadLabels("infrastructure", options.language)[k] || `[${k}]`;
2970
+ const today = options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2971
+ return `---
2972
+ created: "${today}"
2973
+ status: active
2974
+ type: ${t("fmType")}
2975
+ tags: [${t("fmTags")}]
2976
+ ---
2977
+
2978
+ # ${t("title")}
2979
+
2980
+ ${t("intro")}
2981
+
2982
+ ## ${t("hosting")}
2983
+
2984
+ ${t("hostingDesc")}
2985
+
2986
+ ## ${t("ci")}
2987
+
2988
+ ${t("ciDesc")}
2989
+ ${options.conditionCtx.hasCI ? `
2990
+ - Pipeline configurado en \`.github/workflows/\`
2991
+ - Incluye: lint \u2192 test \u2192 build \u2192 deploy` : ""}
2992
+
2993
+ ## ${t("db")}
2994
+
2995
+ ${t("dbDesc")}
2996
+ ${options.conditionCtx.hasDatabase ? `
2997
+ - Migraciones gestionadas con **[herramienta de migraciones]**
2998
+ - Backups: [frecuencia y ubicaci\xF3n]` : ""}
2999
+
3000
+ ## ${t("cache")}
3001
+
3002
+ ${t("cacheDesc")}
3003
+
3004
+ ## ${t("storage")}
3005
+
3006
+ ${t("storageDesc")}
3007
+
3008
+ ## ${t("monitoring")}
3009
+
3010
+ ${t("monitoringDesc")}
3011
+
3012
+ ## ${t("domains")}
3013
+
3014
+ | Entorno | Dominio |
3015
+ |---------|---------|
3016
+ | Producci\xF3n | [app.dominio.com] |
3017
+ | Staging | [staging.dominio.com] |
3018
+
3019
+ ## ${t("scaling")}
3020
+
3021
+ - [Estrategia de escalado]
3022
+ - [L\xEDmites actuales]
3023
+ `;
3024
+ }
3025
+
3026
+ // src/generators/code-style/labels/es.ts
3027
+ var labels21 = {
3028
+ fmType: "reference",
3029
+ fmTags: "code-style, reference, conventions",
3030
+ title: "Gu\xEDa de Estilo de C\xF3digo",
3031
+ intro: "Convenciones de c\xF3digo del proyecto.",
3032
+ naming: "Nombramiento",
3033
+ namingDesc: "camelCase para variables/funciones, PascalCase para tipos/clases.",
3034
+ formatting: "Formateo",
3035
+ formattingDesc: "Usamos [Prettier / formatter] con la configuraci\xF3n del proyecto.",
3036
+ imports: "Imports",
3037
+ importsDesc: "Orden: built-in \u2192 externos \u2192 internos. Usar imports con nombre.",
3038
+ types: "Tipos",
3039
+ typesDesc: "Usar TypeScript strict. Evitar `any`. Preferir interfaces sobre types.",
3040
+ comments: "Comentarios",
3041
+ commentsDesc: "En espa\xF1ol. Explicar el POR QU\xC9, no el QU\xC9.",
3042
+ errors: "Manejo de errores",
3043
+ errorsDesc: "Usar Result types o excepciones tipadas.",
3044
+ testing: "Testing",
3045
+ testingDesc: "1 archivo de test por m\xF3dulo. Nombre: `[modulo].test.ts`."
3046
+ };
3047
+ var en5 = {
3048
+ fmType: "reference",
3049
+ fmTags: "code-style, reference, conventions",
3050
+ title: "Code Style Guide",
3051
+ intro: "Project code conventions.",
3052
+ naming: "Naming",
3053
+ namingDesc: "camelCase for variables/functions, PascalCase for types/classes.",
3054
+ formatting: "Formatting",
3055
+ formattingDesc: "We use [Prettier / formatter] with project config.",
3056
+ imports: "Imports",
3057
+ importsDesc: "Order: built-in \u2192 external \u2192 internal. Use named imports.",
3058
+ types: "Types",
3059
+ typesDesc: "Use TypeScript strict. Avoid `any`. Prefer interfaces over types.",
3060
+ comments: "Comments",
3061
+ commentsDesc: "In English. Explain the WHY, not the WHAT.",
3062
+ errors: "Error Handling",
3063
+ errorsDesc: "Use Result types or typed exceptions.",
3064
+ testing: "Testing",
3065
+ testingDesc: "1 test file per module. Name: `[module].test.ts`."
3066
+ };
3067
+
3068
+ // src/generators/code-style/generator.ts
3069
+ registerLabels("code-style", "es", labels21);
3070
+ registerLabels("code-style", "en", { ...labels21, ...en5 });
3071
+ function generate13(options) {
3072
+ const t = (k) => loadLabels("code-style", options.language)[k] || `[${k}]`;
3073
+ const today = options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
3074
+ return `---
3075
+ created: "${today}"
3076
+ status: active
3077
+ type: ${t("fmType")}
3078
+ tags: [${t("fmTags")}]
3079
+ ---
3080
+
3081
+ # ${t("title")}
3082
+
3083
+ ${t("intro")}
3084
+
3085
+ ## ${t("naming")}
3086
+
3087
+ ${t("namingDesc")}
3088
+
3089
+ ## ${t("formatting")}
3090
+
3091
+ ${t("formattingDesc")}
3092
+
3093
+ ## ${t("imports")}
3094
+
3095
+ ${t("importsDesc")}
3096
+
3097
+ ## ${t("types")}
3098
+
3099
+ ${t("typesDesc")}
3100
+
3101
+ ## ${t("comments")}
3102
+
3103
+ ${t("commentsDesc")}
3104
+
3105
+ ## ${t("errors")}
3106
+
3107
+ ${t("errorsDesc")}
3108
+
3109
+ ## ${t("testing")}
3110
+
3111
+ ${t("testingDesc")}
3112
+ `;
258
3113
  }
259
- function formatStack(stack) {
260
- const parts = [stack.language];
261
- if (stack.framework) parts.push(stack.framework);
262
- if (stack.packageManager) parts.push(`(${stack.packageManager})`);
263
- return parts.join(" + ");
3114
+
3115
+ // src/generators/architecture/labels/es.ts
3116
+ var labels22 = {
3117
+ fmType: "explanation",
3118
+ fmTags: "architecture, explanation, design",
3119
+ title: "Arquitectura del Sistema",
3120
+ intro: "Explica la arquitectura del proyecto \u2014 no c\xF3mo usarlo, sino por qu\xE9 est\xE1 dise\xF1ado as\xED.",
3121
+ overview: "Visi\xF3n General",
3122
+ components: "Componentes Principales",
3123
+ decisions: "Decisiones Clave",
3124
+ limits: "L\xEDmites del Sistema",
3125
+ deps: "Dependencias Externas"
3126
+ };
3127
+ var en6 = {
3128
+ fmType: "explanation",
3129
+ fmTags: "architecture, explanation, design",
3130
+ title: "System Architecture",
3131
+ intro: "Explains the project architecture \u2014 not how to use it, but why it's designed this way.",
3132
+ overview: "Overview",
3133
+ components: "Main Components",
3134
+ decisions: "Key Decisions",
3135
+ limits: "System Limits",
3136
+ deps: "External Dependencies"
3137
+ };
3138
+
3139
+ // src/generators/architecture/generator.ts
3140
+ registerLabels("architecture", "es", labels22);
3141
+ registerLabels("architecture", "en", { ...labels22, ...en6 });
3142
+ function generate14(options) {
3143
+ const t = (k) => loadLabels("architecture", options.language)[k] || `[${k}]`;
3144
+ const today = options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
3145
+ return `---
3146
+ created: "${today}"
3147
+ status: active
3148
+ type: ${t("fmType")}
3149
+ tags: [${t("fmTags")}]
3150
+ ---
3151
+
3152
+ # ${t("title")}
3153
+
3154
+ ${t("intro")}
3155
+
3156
+ ## ${t("overview")}
3157
+
3158
+ [Descripci\xF3n general del sistema en 2-3 p\xE1rrafos \u2014 qu\xE9 hace, para qui\xE9n, stack principal.]
3159
+
3160
+ \`\`\`mermaid
3161
+ flowchart TD
3162
+ Client["Cliente"] --> API["API"]
3163
+ API --> DB["Base de datos"]
3164
+ API --> Cache["Cache"]
3165
+ \`\`\`
3166
+
3167
+ ## ${t("components")}
3168
+
3169
+ | Componente | Tecnolog\xEDa | Responsabilidad |
3170
+ |-----------|-----------|----------------|
3171
+ | **[Componente 1]** | [Tecnolog\xEDa] | [Qu\xE9 hace] |
3172
+ | **[Componente 2]** | [Tecnolog\xEDa] | [Qu\xE9 hace] |
3173
+ | **[Componente 3]** | [Tecnolog\xEDa] | [Qu\xE9 hace] |
3174
+
3175
+ ## ${t("decisions")}
3176
+
3177
+ | Decisi\xF3n | Raz\xF3n |
3178
+ |----------|-------|
3179
+ | **[Tecnolog\xEDa X]** | [Por qu\xE9 se eligi\xF3] |
3180
+ | **[Patr\xF3n Y]** | [Por qu\xE9 se usa] |
3181
+
3182
+ ## ${t("limits")}
3183
+
3184
+ - No es responsable de [X]
3185
+ - No escala horizontalmente sin [Y]
3186
+ - L\xEDmite de [Z requests/minuto]
3187
+
3188
+ ## ${t("deps")}
3189
+
3190
+ | Dependencia | Versi\xF3n | Prop\xF3sito | Cr\xEDtica |
3191
+ |------------|--------|----------|--------|
3192
+ | **[Dep 1]** | [ver] | [qu\xE9 hace] | S\xED |
3193
+ | **[Dep 2]** | [ver] | [qu\xE9 hace] | No |
3194
+ `;
264
3195
  }
265
3196
 
266
- // src/generator.ts
267
- import path3 from "path";
268
- import { fileURLToPath } from "url";
3197
+ // src/generators/design/labels/es.ts
3198
+ var labels23 = {
3199
+ fmType: "product",
3200
+ fmTags: "design, tokens, theme",
3201
+ title: "Sistema de Dise\xF1o",
3202
+ intro: "Documentaci\xF3n de los tokens y patrones visuales del proyecto.",
3203
+ colors: "Colores",
3204
+ typography: "Tipograf\xEDa",
3205
+ spacing: "Espaciado",
3206
+ elevation: "Elevaci\xF3n",
3207
+ components: "Componentes"
3208
+ };
3209
+ var en7 = {
3210
+ fmType: "product",
3211
+ fmTags: "design, tokens, theme",
3212
+ title: "Design System",
3213
+ intro: "Documentation of the project's visual tokens and patterns.",
3214
+ colors: "Colors",
3215
+ typography: "Typography",
3216
+ spacing: "Spacing",
3217
+ elevation: "Elevation",
3218
+ components: "Components"
3219
+ };
269
3220
 
270
- // src/utils/fs.ts
271
- import fs2 from "fs";
272
- import path2 from "path";
273
- function ensureDir(dirPath) {
274
- if (!fs2.existsSync(dirPath)) {
275
- fs2.mkdirSync(dirPath, { recursive: true });
276
- }
3221
+ // src/generators/design/generator.ts
3222
+ registerLabels("design", "es", labels23);
3223
+ registerLabels("design", "en", { ...labels23, ...en7 });
3224
+ function generate15(options) {
3225
+ const t = (k) => loadLabels("design", options.language)[k] || `[${k}]`;
3226
+ const today = options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
3227
+ return `---
3228
+ created: "${today}"
3229
+ status: active
3230
+ type: ${t("fmType")}
3231
+ tags: [${t("fmTags")}]
3232
+ ---
3233
+
3234
+ # ${t("title")}
3235
+
3236
+ ${t("intro")}
3237
+
3238
+ ## \u{1F3A8} ${t("colors")}
3239
+
3240
+ | Token | Color | Uso |
3241
+ |-------|-------|-----|
3242
+ | \`--color-primary\` | \`#XXXXXX\` | Color principal |
3243
+ | \`--color-secondary\` | \`#XXXXXX\` | Color secundario |
3244
+ | \`--color-background\` | \`#XXXXXX\` | Fondo general |
3245
+ | \`--color-text\` | \`#XXXXXX\` | Texto principal |
3246
+ | \`--color-muted\` | \`#XXXXXX\` | Texto secundario |
3247
+
3248
+ ## \u270F\uFE0F ${t("typography")}
3249
+
3250
+ | Token | Font | Size | Weight |
3251
+ |-------|------|------|--------|
3252
+ | \`--font-family\` | [Font] | \u2014 | \u2014 |
3253
+ | \`--text-xs\` | \u2014 | 0.75rem | \u2014 |
3254
+ | \`--text-base\` | \u2014 | 1rem | \u2014 |
3255
+ | \`--text-lg\` | \u2014 | 1.25rem | \u2014 |
3256
+ | \`--text-xl\` | \u2014 | 1.5rem | 700 |
3257
+
3258
+ ## \u{1F4CF} ${t("spacing")}
3259
+
3260
+ | Token | Value |
3261
+ |-------|-------|
3262
+ | \`--space-1\` | 0.25rem |
3263
+ | \`--space-2\` | 0.5rem |
3264
+ | \`--space-4\` | 1rem |
3265
+ | \`--space-8\` | 2rem |
3266
+
3267
+ ## \u{1F3D4}\uFE0F ${t("elevation")}
3268
+
3269
+ | Token | Shadow |
3270
+ |-------|--------|
3271
+ | \`--shadow-sm\` | \`0 1px 2px rgba(0,0,0,0.05)\` |
3272
+ | \`--shadow-md\` | \`0 4px 6px rgba(0,0,0,0.1)\` |
3273
+ | \`--shadow-lg\` | \`0 10px 15px rgba(0,0,0,0.1)\` |
3274
+
3275
+ ## \u{1F9E9} ${t("components")}
3276
+
3277
+ [Documentar componentes clave del sistema de dise\xF1o aqu\xED.]
3278
+ `;
277
3279
  }
278
- function writeFile(filePath, content) {
279
- ensureDir(path2.dirname(filePath));
280
- fs2.writeFileSync(filePath, content, "utf-8");
3280
+
3281
+ // src/generators/overview/labels/es.ts
3282
+ var labels24 = {
3283
+ fmType: "product",
3284
+ fmTags: "overview, product",
3285
+ title: "Visi\xF3n General",
3286
+ intro: "Resumen ejecutivo del proyecto.",
3287
+ problem: "Problema",
3288
+ solution: "Soluci\xF3n",
3289
+ users: "Usuarios",
3290
+ features: "Features principales"
3291
+ };
3292
+ var en8 = {
3293
+ fmType: "product",
3294
+ fmTags: "overview, product",
3295
+ title: "Overview",
3296
+ intro: "Executive summary of the project.",
3297
+ problem: "Problem",
3298
+ solution: "Solution",
3299
+ users: "Users",
3300
+ features: "Key Features"
3301
+ };
3302
+
3303
+ // src/generators/overview/generator.ts
3304
+ registerLabels("overview", "es", labels24);
3305
+ registerLabels("overview", "en", { ...labels24, ...en8 });
3306
+ function generate16(options) {
3307
+ const t = (k) => loadLabels("overview", options.language)[k] || `[${k}]`;
3308
+ const today = options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
3309
+ return `---
3310
+ created: "${today}"
3311
+ status: active
3312
+ type: ${t("fmType")}
3313
+ tags: [${t("fmTags")}]
3314
+ ---
3315
+
3316
+ # ${t("title")}
3317
+
3318
+ ${t("intro")}
3319
+
3320
+ ## ${t("problem")}
3321
+
3322
+ [Qu\xE9 problema resuelve este proyecto. 2-3 p\xE1rrafos.]
3323
+
3324
+ ## ${t("solution")}
3325
+
3326
+ [C\xF3mo lo resuelve. Incluir diagrama de alto nivel si aplica.]
3327
+
3328
+ ## ${t("users")}
3329
+
3330
+ | Tipo de usuario | Necesidad principal |
3331
+ |----------------|-------------------|
3332
+ | **[Usuario 1]** | [Qu\xE9 necesita] |
3333
+ | **[Usuario 2]** | [Qu\xE9 necesita] |
3334
+
3335
+ ## ${t("features")}
3336
+
3337
+ - **[Feature 1]**: [Descripci\xF3n corta]
3338
+ - **[Feature 2]**: [Descripci\xF3n corta]
3339
+ - **[Feature 3]**: [Descripci\xF3n corta]
3340
+ `;
281
3341
  }
282
- function isDirEmpty(dirPath) {
283
- if (!fs2.existsSync(dirPath)) return true;
284
- const files = fs2.readdirSync(dirPath);
285
- return files.length === 0 || files.length === 1 && files[0] === ".git";
3342
+
3343
+ // src/generators/roadmap/labels/es.ts
3344
+ var labels25 = {
3345
+ fmType: "product",
3346
+ fmTags: "roadmap, planning",
3347
+ title: "Roadmap",
3348
+ intro: "Planificaci\xF3n de features y milestones del proyecto.",
3349
+ now: "Ahora",
3350
+ nowDesc: "En desarrollo activo.",
3351
+ next: "Pr\xF3ximo",
3352
+ nextDesc: "Siguiente en prioridad.",
3353
+ later: "Futuro",
3354
+ laterDesc: "Planeado, sin fecha.",
3355
+ done: "Completado",
3356
+ doneDesc: "Entregado."
3357
+ };
3358
+ var en9 = {
3359
+ fmType: "product",
3360
+ fmTags: "roadmap, planning",
3361
+ title: "Roadmap",
3362
+ intro: "Feature and milestone planning for the project.",
3363
+ now: "Now",
3364
+ nowDesc: "In active development.",
3365
+ next: "Next",
3366
+ nextDesc: "Next in priority.",
3367
+ later: "Later",
3368
+ laterDesc: "Planned, no date.",
3369
+ done: "Done",
3370
+ doneDesc: "Delivered."
3371
+ };
3372
+
3373
+ // src/generators/roadmap/generator.ts
3374
+ registerLabels("roadmap", "es", labels25);
3375
+ registerLabels("roadmap", "en", { ...labels25, ...en9 });
3376
+ function generate17(options) {
3377
+ const t = (k) => loadLabels("roadmap", options.language)[k] || `[${k}]`;
3378
+ return `---
3379
+ created: "${options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0]}"
3380
+ status: active
3381
+ type: ${t("fmType")}
3382
+ tags: [${t("fmTags")}]
3383
+ ---
3384
+
3385
+ # ${t("title")}
3386
+
3387
+ ${t("intro")}
3388
+
3389
+ ## \u{1F504} ${t("now")}
3390
+
3391
+ ${t("nowDesc")}
3392
+
3393
+ - [Feature actual 1]
3394
+ - [Feature actual 2]
3395
+
3396
+ ## \u23E9 ${t("next")}
3397
+
3398
+ ${t("nextDesc")}
3399
+
3400
+ - [Feature planeada 1]
3401
+ - [Feature planeada 2]
3402
+
3403
+ ## \u{1F52E} ${t("later")}
3404
+
3405
+ ${t("laterDesc")}
3406
+
3407
+ - [Idea futura 1]
3408
+ - [Idea futura 2]
3409
+
3410
+ ## \u2705 ${t("done")}
3411
+
3412
+ ${t("doneDesc")}
3413
+
3414
+ - [Feature completada 1]
3415
+ `;
286
3416
  }
287
- function copyTemplateDir(src, dest, replacements) {
288
- ensureDir(dest);
289
- const entries = fs2.readdirSync(src, { withFileTypes: true });
290
- for (const entry of entries) {
291
- const srcPath = path2.join(src, entry.name);
292
- const destPath = path2.join(dest, entry.name);
293
- if (entry.isDirectory()) {
294
- copyTemplateDir(srcPath, destPath, replacements);
295
- } else {
296
- let content = fs2.readFileSync(srcPath, "utf-8");
297
- if (isTextFile(entry.name)) {
298
- for (const [placeholder, value] of Object.entries(replacements)) {
299
- content = content.replaceAll(placeholder, value);
300
- }
301
- }
302
- writeFile(destPath, content);
303
- }
304
- }
3417
+
3418
+ // src/generators/operations/labels/es.ts
3419
+ var labels26 = {
3420
+ fmType: "operations",
3421
+ fmTags: "operations, monitoring, incidents",
3422
+ title: "Operaciones",
3423
+ intro: "Documentaci\xF3n operativa del proyecto.",
3424
+ monitoring: "Monitoreo",
3425
+ alerts: "Alertas",
3426
+ incidents: "Incidentes",
3427
+ backups: "Backups"
3428
+ };
3429
+ var en10 = {
3430
+ fmType: "operations",
3431
+ fmTags: "operations, monitoring, incidents",
3432
+ title: "Operations",
3433
+ intro: "Project operations documentation.",
3434
+ monitoring: "Monitoring",
3435
+ alerts: "Alerts",
3436
+ incidents: "Incidents",
3437
+ backups: "Backups"
3438
+ };
3439
+
3440
+ // src/generators/operations/generator.ts
3441
+ registerLabels("operations", "es", labels26);
3442
+ registerLabels("operations", "en", { ...labels26, ...en10 });
3443
+ function generate18(options) {
3444
+ const t = (k) => loadLabels("operations", options.language)[k] || `[${k}]`;
3445
+ return `---
3446
+ created: "${options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0]}"
3447
+ status: active
3448
+ type: ${t("fmType")}
3449
+ tags: [${t("fmTags")}]
3450
+ ---
3451
+
3452
+ # ${t("title")}
3453
+
3454
+ ${t("intro")}
3455
+
3456
+ ## \u{1F4CA} ${t("monitoring")}
3457
+
3458
+ - [Dashboard de monitoreo]: [URL]
3459
+ - M\xE9tricas clave: [latencia, error rate, throughput]
3460
+ - Logs: [herramienta de logs]
3461
+
3462
+ ## \u{1F6A8} ${t("alerts")}
3463
+
3464
+ | Alerta | Severidad | Canal | Responsable |
3465
+ |--------|----------|-------|------------|
3466
+ | [Alerta 1] | Cr\xEDtica | PagerDuty | [Equipo] |
3467
+ | [Alerta 2] | Alta | Slack | [Equipo] |
3468
+
3469
+ ## \u{1F525} ${t("incidents")}
3470
+
3471
+ Procedimiento de respuesta a incidentes:
3472
+ 1. [Detectar y reconocer]
3473
+ 2. [Escalar si es necesario]
3474
+ 3. [Mitigar]
3475
+ 4. [Resolver]
3476
+ 5. [Post-mortem]
3477
+
3478
+ Ver runbooks en [\`docs/guides/runbooks/\`](../guides/runbooks/).
3479
+
3480
+ ## \u{1F4BE} ${t("backups")}
3481
+
3482
+ | Dato | Frecuencia | Retenci\xF3n | Ubicaci\xF3n |
3483
+ |------|----------|----------|----------|
3484
+ | Base de datos | [Diaria] | [30 d\xEDas] | [S3] |
3485
+ | Archivos | [Diaria] | [30 d\xEDas] | [S3] |
3486
+ `;
3487
+ }
3488
+
3489
+ // src/generators/project-readme/labels/es.ts
3490
+ var labels27 = {
3491
+ title: "# {{PROJECT_NAME}}",
3492
+ intro: "[Descripci\xF3n corta del proyecto en una o dos frases.]",
3493
+ quick: "\u{1F680} Quick Start",
3494
+ quickDesc: "[Instrucciones m\xEDnimas para arrancar en local.]",
3495
+ docs: "\u{1F4DA} Documentaci\xF3n",
3496
+ docsDesc: "Documentaci\xF3n completa en la carpeta [`docs/`](docs/).",
3497
+ stack: "\u{1F6E0}\uFE0F Stack",
3498
+ license: "\u{1F4C4} Licencia"
3499
+ };
3500
+ var en11 = {
3501
+ title: "# {{PROJECT_NAME}}",
3502
+ intro: "[Short project description in one or two sentences.]",
3503
+ quick: "\u{1F680} Quick Start",
3504
+ quickDesc: "[Minimum instructions to get started locally.]",
3505
+ docs: "\u{1F4DA} Documentation",
3506
+ docsDesc: "Full documentation in the [`docs/`](docs/) folder.",
3507
+ stack: "\u{1F6E0}\uFE0F Stack",
3508
+ license: "\u{1F4C4} License"
3509
+ };
3510
+
3511
+ // src/generators/project-readme/generator.ts
3512
+ registerLabels("project-readme", "es", labels27);
3513
+ registerLabels("project-readme", "en", { ...labels27, ...en11 });
3514
+ function generate19(options) {
3515
+ const t = (k) => loadLabels("project-readme", options.language)[k] || `[${k}]`;
3516
+ const stack = options.stack ? `${options.stack.language}${options.stack.framework ? " + " + options.stack.framework : ""}` : "[TECNOLOG\xCDA]";
3517
+ return `# {{PROJECT_NAME}}
3518
+
3519
+ ${t("intro")}
3520
+
3521
+ ## ${t("quick")}
3522
+
3523
+ \`\`\`bash
3524
+ git clone [URL]
3525
+ cd {{PROJECT_NAME}}
3526
+ [comando de instalaci\xF3n]
3527
+ [comando de dev]
3528
+ \`\`\`
3529
+
3530
+ ${t("quickDesc")}
3531
+
3532
+ ## ${t("docs")}
3533
+
3534
+ ${t("docsDesc")}
3535
+
3536
+ ## ${t("stack")}
3537
+
3538
+ - **Lenguaje**: ${stack}
3539
+ - **Package Manager**: ${options.stack?.packageManager || "[package manager]"}
3540
+
3541
+ ## ${t("license")}
3542
+
3543
+ [LICENSE]
3544
+ `;
3545
+ }
3546
+
3547
+ // src/generators/docs-readme/labels/es.ts
3548
+ var labels28 = {
3549
+ title: "\u{1F4DA} Documentaci\xF3n de {{PROJECT_NAME}}",
3550
+ intro: "Bienvenido a la documentaci\xF3n de {{PROJECT_NAME}}.",
3551
+ structure: "Estructura",
3552
+ tutorials: "\u{1F4D6} Tutoriales",
3553
+ guides: "\u{1F4DD} Gu\xEDas",
3554
+ reference: "\u{1F4CB} Referencia",
3555
+ explanation: "\u{1F4A1} Explicaci\xF3n",
3556
+ product: "\u{1F680} Producto",
3557
+ ops: "\u2699\uFE0F Operaciones"
3558
+ };
3559
+ var en12 = {
3560
+ title: "\u{1F4DA} {{PROJECT_NAME}} Documentation",
3561
+ intro: "Welcome to the {{PROJECT_NAME}} documentation.",
3562
+ structure: "Structure",
3563
+ tutorials: "\u{1F4D6} Tutorials",
3564
+ guides: "\u{1F4DD} Guides",
3565
+ reference: "\u{1F4CB} Reference",
3566
+ explanation: "\u{1F4A1} Explanation",
3567
+ product: "\u{1F680} Product",
3568
+ ops: "\u2699\uFE0F Operations"
3569
+ };
3570
+
3571
+ // src/generators/docs-readme/generator.ts
3572
+ registerLabels("docs-readme", "es", labels28);
3573
+ registerLabels("docs-readme", "en", { ...labels28, ...en12 });
3574
+ function generate20(options) {
3575
+ const t = (k) => loadLabels("docs-readme", options.language)[k] || `[${k}]`;
3576
+ return `# ${t("title")}
3577
+
3578
+ ${t("intro")}
3579
+
3580
+ ## ${t("structure")}
3581
+
3582
+ | Directorio | Tipo | Contenido |
3583
+ |-----------|------|----------|
3584
+ | \`tutorials/\` | ${t("tutorials")} | Aprender haciendo |
3585
+ | \`guides/\` | ${t("guides")} | C\xF3mo resolver tareas |
3586
+ | \`reference/\` | ${t("reference")} | Info t\xE9cnica detallada |
3587
+ | \`explanation/\` | ${t("explanation")} | Razonamiento y decisiones |
3588
+ | \`product/\` | ${t("product")} | Roadmap y visi\xF3n |
3589
+ | \`operations/\` | ${t("ops")} | Runbooks y monitoreo |
3590
+ `;
3591
+ }
3592
+
3593
+ // src/generators/adr-template/labels/es.ts
3594
+ var labels29 = {
3595
+ fmType: "adr-template",
3596
+ fmTags: "adr, template, decisions",
3597
+ title: "ADR-0000: [T\xEDtulo descriptivo de la decisi\xF3n]",
3598
+ statuses: "Propuesto \u2192 Aceptado \u2192 Deprecado \u2192 Reemplazado",
3599
+ context: "Contexto",
3600
+ decision: "Decisi\xF3n",
3601
+ consequences: "Consecuencias",
3602
+ alternatives: "Alternativas",
3603
+ pos: "Positivas",
3604
+ neg: "Negativas",
3605
+ migration: "Migraci\xF3n",
3606
+ rollback: "Rollback"
3607
+ };
3608
+ var en13 = {
3609
+ fmType: "adr-template",
3610
+ fmTags: "adr, template, decisions",
3611
+ title: "ADR-0000: [Descriptive title of the decision]",
3612
+ statuses: "Proposed \u2192 Accepted \u2192 Deprecated \u2192 Superseded",
3613
+ context: "Context",
3614
+ decision: "Decision",
3615
+ consequences: "Consequences",
3616
+ alternatives: "Alternatives",
3617
+ pos: "Positive",
3618
+ neg: "Negative",
3619
+ migration: "Migration",
3620
+ rollback: "Rollback"
3621
+ };
3622
+
3623
+ // src/generators/adr-template/generator.ts
3624
+ registerLabels("adr-template", "es", labels29);
3625
+ registerLabels("adr-template", "en", { ...labels29, ...en13 });
3626
+ function generate21(options) {
3627
+ const t = (k) => loadLabels("adr-template", options.language)[k] || `[${k}]`;
3628
+ const today = options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
3629
+ return `---
3630
+ created: "${today}"
3631
+ status: proposed
3632
+ deciders: ["[nombre]"]
3633
+ tags: [${t("fmTags")}]
3634
+ ---
3635
+
3636
+ # ${t("title")}
3637
+
3638
+ **Estado**: ${t("statuses")}
3639
+
3640
+ ## ${t("context")}
3641
+
3642
+ [Describe el problema, las fuerzas en juego, y las restricciones. \xBFQu\xE9 nos llev\xF3 a tomar esta decisi\xF3n?]
3643
+
3644
+ ## ${t("decision")}
3645
+
3646
+ [Describe la decisi\xF3n en una o dos frases. S\xE9 espec\xEDfico.]
3647
+
3648
+ ## ${t("consequences")}
3649
+
3650
+ ### ${t("pos")}
3651
+ - [Consecuencia positiva 1]
3652
+ - [Consecuencia positiva 2]
3653
+
3654
+ ### ${t("neg")}
3655
+ - [Consecuencia negativa 1]
3656
+ - [Trade-off aceptado]
3657
+
3658
+ ### ${t("migration")}
3659
+ [Si la decisi\xF3n requiere migraci\xF3n, describir los pasos.]
3660
+
3661
+ ### ${t("rollback")}
3662
+ [Si la decisi\xF3n se revierte, \xBFc\xF3mo se vuelve atr\xE1s?]
3663
+
3664
+ ## ${t("alternatives")}
3665
+
3666
+ | Alternativa | Rechazada porque... |
3667
+ |------------|-------------------|
3668
+ | **[Alt 1]** | [Raz\xF3n] |
3669
+ | **[Alt 2]** | [Raz\xF3n] |
3670
+ `;
305
3671
  }
306
- function isTextFile(filename) {
307
- const textExtensions = [".md", ".yml", ".yaml", ".json", ".txt", ".editorconfig"];
308
- return textExtensions.some((ext) => filename.endsWith(ext)) || filename.startsWith(".");
3672
+
3673
+ // src/generators/agent-flow/labels/es.ts
3674
+ var labels30 = {
3675
+ fmType: "explanation",
3676
+ fmTags: "agent-flow, agents, protocol",
3677
+ title: "Flujo de Agentes",
3678
+ intro: "Diagrama y explicaci\xF3n del flujo de trabajo de agentes de IA en este proyecto.",
3679
+ subdel: "Subdelegaci\xF3n",
3680
+ subdelDesc: "El orquestador delega a agentes especializados.",
3681
+ qg: "Quality Gate",
3682
+ qgDesc: "@reviewer verifica antes de completar.",
3683
+ main: "Mantenimiento",
3684
+ mainDesc: "El skill doc-maintain sincroniza cambios."
3685
+ };
3686
+ var en14 = {
3687
+ fmType: "explanation",
3688
+ fmTags: "agent-flow, agents, protocol",
3689
+ title: "Agent Flow",
3690
+ intro: "Diagram and explanation of the AI agent workflow in this project.",
3691
+ subdel: "Sub-delegation",
3692
+ subdelDesc: "The orchestrator delegates to specialized agents.",
3693
+ qg: "Quality Gate",
3694
+ qgDesc: "@reviewer verifies before completing.",
3695
+ main: "Maintenance",
3696
+ mainDesc: "The doc-maintain skill syncs changes."
3697
+ };
3698
+
3699
+ // src/generators/agent-flow/generator.ts
3700
+ registerLabels("agent-flow", "es", labels30);
3701
+ registerLabels("agent-flow", "en", { ...labels30, ...en14 });
3702
+ function generate22(options) {
3703
+ const t = (k) => loadLabels("agent-flow", options.language)[k] || `[${k}]`;
3704
+ return `---
3705
+ created: "${options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0]}"
3706
+ status: active
3707
+ type: ${t("fmType")}
3708
+ tags: [${t("fmTags")}]
3709
+ ---
3710
+
3711
+ # ${t("title")}
3712
+
3713
+ ${t("intro")}
3714
+
3715
+ \`\`\`mermaid
3716
+ sequenceDiagram
3717
+ participant U as Developer
3718
+ participant O as Orchestrator
3719
+ participant A as Agent
3720
+ participant R as @reviewer
3721
+
3722
+ U->>O: Task
3723
+ O->>A: ${t("subdel")}
3724
+ A->>A: Implement
3725
+ A->>R: Request review
3726
+ R-->>A: \u2705 / \u274C
3727
+ A->>O: Done
3728
+ O->>U: Complete
3729
+ \`\`\`
3730
+
3731
+ ## ${t("subdel")}
3732
+
3733
+ ${t("subdelDesc")}
3734
+
3735
+ ## ${t("qg")}
3736
+
3737
+ ${t("qgDesc")}
3738
+
3739
+ ## ${t("main")}
3740
+
3741
+ ${t("mainDesc")}
3742
+ `;
309
3743
  }
310
3744
 
311
3745
  // src/generator.ts
312
- var __dirname = path3.dirname(fileURLToPath(import.meta.url));
313
- async function generate(options) {
314
- const { projectName, targetDir, stack, modules, language } = options;
315
- const createdFiles = [];
3746
+ var __dirname = path6.dirname(fileURLToPath(import.meta.url));
3747
+ var GENERATED_FILES = /* @__PURE__ */ new Set([
3748
+ // Base
3749
+ "AGENTS.md",
3750
+ "AGENTS.en.md",
3751
+ "CHANGELOG.md",
3752
+ "CHANGELOG.en.md",
3753
+ "docs/CONTEXT.md",
3754
+ "docs/CONTEXT.en.md",
3755
+ "README.md",
3756
+ "docs/README.md",
3757
+ "docs/adr/TEMPLATE.md",
3758
+ // Tutorials
3759
+ "docs/tutorials/quick-start.md",
3760
+ "docs/tutorials/quick-start.en.md",
3761
+ "docs/tutorials/environment-setup.md",
3762
+ "docs/tutorials/first-task.md",
3763
+ // Guides
3764
+ "docs/guides/deployment.md",
3765
+ "docs/guides/troubleshooting.md",
3766
+ "docs/guides/runbooks/TEMPLATE.md",
3767
+ // Reference
3768
+ "docs/reference/api.md",
3769
+ "docs/reference/api.en.md",
3770
+ "docs/reference/configuration.md",
3771
+ "docs/reference/infrastructure.md",
3772
+ "docs/reference/code-style.md",
3773
+ // Explanation
3774
+ "docs/explanation/architecture.md",
3775
+ "docs/explanation/agent-flow.md",
3776
+ // Product
3777
+ "docs/product/overview.md",
3778
+ "docs/roadmap.md",
3779
+ // Operations
3780
+ "docs/operations/README.md",
3781
+ // Design
3782
+ "docs/DESIGN.md"
3783
+ ]);
3784
+ async function generate23(options) {
3785
+ const { projectName, targetDir, modules } = options;
3786
+ const replacements = buildReplacements(projectName, options.stack);
3787
+ const conditionCtx = buildConditionContext(options.stack, targetDir);
3788
+ const templatesDir = resolveTemplatesDir();
3789
+ const plannedFiles = [];
3790
+ const baseDir = path6.join(templatesDir, "base");
3791
+ if (fs6.existsSync(baseDir)) {
3792
+ collectFiles(baseDir, targetDir, replacements, "base", plannedFiles);
3793
+ }
3794
+ for (const moduleName of modules) {
3795
+ const moduleDir = path6.join(templatesDir, "modules", moduleName);
3796
+ if (fs6.existsSync(moduleDir)) {
3797
+ collectFiles(moduleDir, targetDir, replacements, moduleName, plannedFiles);
3798
+ }
3799
+ }
3800
+ const sharedDir = path6.join(templatesDir, "shared");
3801
+ if (fs6.existsSync(sharedDir)) {
3802
+ collectFiles(sharedDir, targetDir, replacements, "shared", plannedFiles);
3803
+ }
3804
+ const genOpts = {
3805
+ projectName,
3806
+ stack: options.stack,
3807
+ language: options.language,
3808
+ conditionCtx
3809
+ };
3810
+ plannedFiles.push({
3811
+ relativePath: "AGENTS.md",
3812
+ sourcePath: "",
3813
+ content: generate(genOpts),
3814
+ replacements: {},
3815
+ module: "base"
3816
+ });
3817
+ plannedFiles.push({
3818
+ relativePath: "docs/CONTEXT.md",
3819
+ sourcePath: "",
3820
+ content: generate2(genOpts),
3821
+ replacements: {},
3822
+ module: "base"
3823
+ });
3824
+ plannedFiles.push({
3825
+ relativePath: "CHANGELOG.md",
3826
+ sourcePath: "",
3827
+ content: generate3(genOpts),
3828
+ replacements: {},
3829
+ module: "base"
3830
+ });
3831
+ if (modules.includes("reference")) {
3832
+ plannedFiles.push({ relativePath: "docs/reference/api.md", sourcePath: "", content: generate5(genOpts), replacements: {}, module: "reference" });
3833
+ plannedFiles.push({
3834
+ relativePath: "docs/reference/configuration.md",
3835
+ sourcePath: "",
3836
+ content: generate11(genOpts),
3837
+ replacements: {},
3838
+ module: "reference"
3839
+ });
3840
+ plannedFiles.push({
3841
+ relativePath: "docs/reference/infrastructure.md",
3842
+ sourcePath: "",
3843
+ content: generate12(genOpts),
3844
+ replacements: {},
3845
+ module: "reference"
3846
+ });
3847
+ plannedFiles.push({
3848
+ relativePath: "docs/reference/code-style.md",
3849
+ sourcePath: "",
3850
+ content: generate13(genOpts),
3851
+ replacements: {},
3852
+ module: "reference"
3853
+ });
3854
+ }
3855
+ if (modules.includes("tutorials")) {
3856
+ plannedFiles.push({
3857
+ relativePath: "docs/tutorials/quick-start.md",
3858
+ sourcePath: "",
3859
+ content: generate4(genOpts),
3860
+ replacements: {},
3861
+ module: "tutorials"
3862
+ });
3863
+ plannedFiles.push({
3864
+ relativePath: "docs/tutorials/environment-setup.md",
3865
+ sourcePath: "",
3866
+ content: generate6(genOpts),
3867
+ replacements: {},
3868
+ module: "tutorials"
3869
+ });
3870
+ plannedFiles.push({
3871
+ relativePath: "docs/tutorials/first-task.md",
3872
+ sourcePath: "",
3873
+ content: generate7(genOpts),
3874
+ replacements: {},
3875
+ module: "tutorials"
3876
+ });
3877
+ }
3878
+ if (modules.includes("guides")) {
3879
+ plannedFiles.push({ relativePath: "docs/guides/deployment.md", sourcePath: "", content: generate8(genOpts), replacements: {}, module: "guides" });
3880
+ plannedFiles.push({
3881
+ relativePath: "docs/guides/troubleshooting.md",
3882
+ sourcePath: "",
3883
+ content: generate9(genOpts),
3884
+ replacements: {},
3885
+ module: "guides"
3886
+ });
3887
+ plannedFiles.push({
3888
+ relativePath: "docs/guides/runbooks/TEMPLATE.md",
3889
+ sourcePath: "",
3890
+ content: generate10(genOpts),
3891
+ replacements: {},
3892
+ module: "guides"
3893
+ });
3894
+ }
3895
+ if (modules.includes("explanation")) {
3896
+ plannedFiles.push({
3897
+ relativePath: "docs/explanation/architecture.md",
3898
+ sourcePath: "",
3899
+ content: generate14(genOpts),
3900
+ replacements: {},
3901
+ module: "explanation"
3902
+ });
3903
+ plannedFiles.push({
3904
+ relativePath: "docs/explanation/agent-flow.md",
3905
+ sourcePath: "",
3906
+ content: generate22(genOpts),
3907
+ replacements: {},
3908
+ module: "explanation"
3909
+ });
3910
+ }
3911
+ if (modules.includes("product")) {
3912
+ plannedFiles.push({ relativePath: "docs/product/overview.md", sourcePath: "", content: generate16(genOpts), replacements: {}, module: "product" });
3913
+ plannedFiles.push({ relativePath: "docs/roadmap.md", sourcePath: "", content: generate17(genOpts), replacements: {}, module: "product" });
3914
+ }
3915
+ if (modules.includes("operations")) {
3916
+ plannedFiles.push({ relativePath: "docs/operations/README.md", sourcePath: "", content: generate18(genOpts), replacements: {}, module: "operations" });
3917
+ }
3918
+ if (modules.includes("design")) {
3919
+ plannedFiles.push({ relativePath: "docs/DESIGN.md", sourcePath: "", content: generate15(genOpts), replacements: {}, module: "design" });
3920
+ }
3921
+ plannedFiles.push({ relativePath: "README.md", sourcePath: "", content: generate19(genOpts), replacements: {}, module: "base" });
3922
+ plannedFiles.push({ relativePath: "docs/README.md", sourcePath: "", content: generate20(genOpts), replacements: {}, module: "base" });
3923
+ plannedFiles.push({ relativePath: "docs/adr/TEMPLATE.md", sourcePath: "", content: generate21(genOpts), replacements: {}, module: "base" });
3924
+ const createdFiles = await processConflicts(plannedFiles, {
3925
+ targetDir,
3926
+ force: options.force,
3927
+ dryRun: options.dryRun,
3928
+ conditionCtx
3929
+ });
3930
+ if (options.initGit && !options.dryRun) {
3931
+ await initGit(targetDir);
3932
+ }
3933
+ return createdFiles;
3934
+ }
3935
+ function buildReplacements(projectName, stack) {
316
3936
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
317
- const replacements = {
3937
+ return {
318
3938
  "{{PROJECT_NAME}}": projectName,
319
3939
  "{{TECH_STACK}}": stack ? formatStackForTemplate(stack) : "[TECNOLOG\xCDA PRINCIPAL]",
320
3940
  "{{DEV_COMMAND}}": stack?.devCommand || "[comando de dev]",
@@ -325,49 +3945,34 @@ async function generate(options) {
325
3945
  "{{FRAMEWORK}}": stack?.framework || "[framework]",
326
3946
  "{{PACKAGE_MANAGER}}": stack?.packageManager || "[package manager]",
327
3947
  "{{DATE}}": today,
328
- // Mantener los placeholders originales para compatibilidad
329
3948
  "[NOMBRE DEL PROYECTO]": projectName
330
3949
  };
331
- const templatesDir = await resolveTemplatesDir();
332
- const baseDir = path3.join(templatesDir, "base");
333
- copyTemplateDir(baseDir, targetDir, replacements);
334
- createdFiles.push(...await listGeneratedFiles(baseDir, targetDir));
335
- for (const moduleName of modules) {
336
- const moduleDir = path3.join(templatesDir, "modules", moduleName);
337
- copyTemplateDir(moduleDir, targetDir, replacements);
338
- createdFiles.push(...await listGeneratedFiles(moduleDir, targetDir));
339
- }
340
- const sharedDir = path3.join(templatesDir, "shared");
341
- copyTemplateDir(sharedDir, targetDir, replacements);
342
- createdFiles.push(...await listGeneratedFiles(sharedDir, targetDir));
343
- if (options.initGit) {
344
- await initGit(targetDir);
345
- }
346
- return createdFiles;
347
- }
348
- async function resolveTemplatesDir() {
349
- const prodPath = path3.resolve(__dirname, "..", "templates");
350
- const devPath = path3.resolve(__dirname, "..", "..", "templates");
351
- const { existsSync } = await import("fs");
352
- if (existsSync(prodPath)) return prodPath;
353
- if (existsSync(devPath)) return devPath;
354
- throw new Error("No se encontr\xF3 el directorio de templates. \xBFSe instal\xF3 correctamente el paquete?");
355
3950
  }
356
- async function listGeneratedFiles(templateDir, targetDir) {
357
- const { readdirSync } = await import("fs");
358
- const files = [];
359
- function walk(dir, base) {
360
- for (const entry of readdirSync(dir, { withFileTypes: true })) {
361
- const rel = path3.join(base, entry.name);
362
- if (entry.isDirectory()) {
363
- walk(path3.join(dir, entry.name), rel);
364
- } else {
365
- files.push(rel);
366
- }
3951
+ function collectFiles(templateDir, targetDir, replacements, module, output, prefix = "") {
3952
+ const entries = fs6.readdirSync(templateDir, { withFileTypes: true });
3953
+ for (const entry of entries) {
3954
+ const srcPath = path6.join(templateDir, entry.name);
3955
+ if (entry.isDirectory()) {
3956
+ collectFiles(srcPath, targetDir, replacements, module, output, path6.join(prefix, entry.name));
3957
+ } else {
3958
+ const relativePath = path6.join(prefix, entry.name).replace(/\\/g, "/");
3959
+ if (GENERATED_FILES.has(relativePath)) continue;
3960
+ if (GENERATED_FILES.has(relativePath.replace(/\.en\.md$/, ".md"))) continue;
3961
+ output.push({
3962
+ relativePath,
3963
+ sourcePath: path6.resolve(srcPath),
3964
+ replacements,
3965
+ module
3966
+ });
367
3967
  }
368
3968
  }
369
- walk(templateDir, "");
370
- return files;
3969
+ }
3970
+ function resolveTemplatesDir() {
3971
+ const prodPath = path6.resolve(__dirname, "..", "templates");
3972
+ const devPath = path6.resolve(__dirname, "..", "..", "templates");
3973
+ if (fs6.existsSync(prodPath)) return prodPath;
3974
+ if (fs6.existsSync(devPath)) return devPath;
3975
+ throw new Error("No se encontr\xF3 el directorio de templates. \xBFSe instal\xF3 correctamente el paquete?");
371
3976
  }
372
3977
  async function initGit(dir) {
373
3978
  const { execSync } = await import("child_process");
@@ -554,43 +4159,45 @@ function generateAgentsGuide() {
554
4159
  }
555
4160
 
556
4161
  // src/cli.ts
557
- var __dirname2 = path4.dirname(url.fileURLToPath(import.meta.url));
558
- var pkg = JSON.parse(fs3.readFileSync(path4.join(__dirname2, "..", "package.json"), "utf-8"));
4162
+ var __dirname2 = path7.dirname(url.fileURLToPath(import.meta.url));
4163
+ var pkg = JSON.parse(fs7.readFileSync(path7.join(__dirname2, "..", "package.json"), "utf-8"));
559
4164
  function showHelp() {
560
4165
  console.log(`
561
- ${pc2.bold(brand.title("@damenor/agent-docs"))} ${pc2.dim(`v${pkg.version}`)}
4166
+ ${pc4.bold(brand.title("@damenor/agent-docs"))} ${pc4.dim(`v${pkg.version}`)}
562
4167
 
563
- ${pc2.bold("USAGE")}
564
- ${pc2.cyan("npx @damenor/agent-docs")} ${pc2.dim("# Interactive wizard (default)")}
565
- ${pc2.cyan("npx @damenor/agent-docs --help")} ${pc2.dim("# Show this help")}
566
- ${pc2.cyan("npx @damenor/agent-docs --version")} ${pc2.dim("# Show version")}
4168
+ ${pc4.bold("USAGE")}
4169
+ ${pc4.cyan("npx @damenor/agent-docs")} ${pc4.dim("# Interactive wizard (default)")}
4170
+ ${pc4.cyan("npx @damenor/agent-docs --help")} ${pc4.dim("# Show this help")}
4171
+ ${pc4.cyan("npx @damenor/agent-docs --version")} ${pc4.dim("# Show version")}
567
4172
 
568
- ${pc2.bold("WHAT IT DOES")}
4173
+ ${pc4.bold("WHAT IT DOES")}
569
4174
  Generates a professional documentation structure for your project:
570
4175
  Di\xE1taxis (Tutorials/Guides/Reference/Explanation) + AGENTS.md + ADRs + AI agent skills.
571
4176
 
572
- ${pc2.bold("WIZARD STEPS")}
573
- 1. ${pc2.bold("Project name")} \u2014 How your project is called
574
- 2. ${pc2.bold("Target directory")} \u2014 Where to generate docs (default: ./)
575
- 3. ${pc2.bold("Stack detection")} \u2014 Auto-detect or configure manually
576
- 4. ${pc2.bold("Language")} \u2014 Espa\xF1ol or English
577
- 5. ${pc2.bold("Modules")} \u2014 Pick from 9 available modules
578
- 6. ${pc2.bold("Git init")} \u2014 Initialize git repo with first commit
579
- 7. ${pc2.bold("Generate")} \u2014 Confirm and create all files
4177
+ ${pc4.bold("WIZARD STEPS")}
4178
+ 1. ${pc4.bold("Project name")} \u2014 How your project is called
4179
+ 2. ${pc4.bold("Target directory")} \u2014 Where to generate docs (default: ./)
4180
+ 3. ${pc4.bold("Stack detection")} \u2014 Auto-detect or configure manually
4181
+ 4. ${pc4.bold("Language")} \u2014 Espa\xF1ol or English
4182
+ 5. ${pc4.bold("Modules")} \u2014 Pick from 9 available modules
4183
+ 6. ${pc4.bold("Git init")} \u2014 Initialize git repo with first commit
4184
+ 7. ${pc4.bold("Generate")} \u2014 Confirm and create all files
580
4185
 
581
- ${pc2.bold("MODULES")}
582
- ${DOC_MODULES.map((m) => ` ${pc2.cyan(m.value.padEnd(12))} ${m.label} \u2014 ${m.hint ?? ""}`).join("\n")}
4186
+ ${pc4.bold("MODULES")}
4187
+ ${DOC_MODULES.map((m) => ` ${pc4.cyan(m.value.padEnd(12))} ${m.label} \u2014 ${m.hint ?? ""}`).join("\n")}
583
4188
 
584
- ${pc2.bold("STACK DETECTION")}
4189
+ ${pc4.bold("STACK DETECTION")}
585
4190
  Reads package.json, pyproject.toml, go.mod, Cargo.toml, pom.xml, build.gradle.
586
4191
  Supports Node.js, Python, Go, Rust, Java/Kotlin + 10+ frameworks.
587
4192
 
588
- ${pc2.bold("OPTIONS")}
589
- ${pc2.cyan("-h, --help")} Show this help
590
- ${pc2.cyan("-v, --version")} Show version
591
- ${pc2.cyan("--agents-guide")} Output guide for AI agents (what to fill, what to delete, priorities)
4193
+ ${pc4.bold("OPTIONS")}
4194
+ ${pc4.cyan("-h, --help")} Show this help
4195
+ ${pc4.cyan("-v, --version")} Show version
4196
+ ${pc4.cyan("--agents-guide")} Output guide for AI agents (what to fill, what to delete, priorities)
4197
+ ${pc4.cyan("--force")} Overwrite existing files without prompting
4198
+ ${pc4.cyan("--dry-run")} Preview what would be generated without writing
592
4199
 
593
- ${pc2.dim("Made with \u2764\uFE0F by damenordev")}
4200
+ ${pc4.dim("Made with \u2764\uFE0F by damenordev")}
594
4201
  `);
595
4202
  }
596
4203
  function showVersion() {
@@ -598,6 +4205,8 @@ function showVersion() {
598
4205
  }
599
4206
  async function cli() {
600
4207
  const args = process.argv.slice(2);
4208
+ const isForce = args.includes("--force");
4209
+ const isDryRun = args.includes("--dry-run");
601
4210
  if (args.includes("--help") || args.includes("-h")) {
602
4211
  showHelp();
603
4212
  return;
@@ -611,11 +4220,15 @@ async function cli() {
611
4220
  process.exit(0);
612
4221
  }
613
4222
  console.clear();
614
- p.intro(
615
- `${icons.docs} ${brand.title("@damenor/agent-docs")} ${pc2.dim(`v${pkg.version}`)}
616
- ${pc2.dim("Documentaci\xF3n profesional para proyectos con agentes AI")}`
4223
+ if (isDryRun) {
4224
+ console.log(`${pc4.blue("\u2139")} ${pc4.dim("Dry run mode \u2014 no files will be written")}
4225
+ `);
4226
+ }
4227
+ p2.intro(
4228
+ `${icons.docs} ${brand.title("@damenor/agent-docs")} ${pc4.dim(`v${pkg.version}`)}
4229
+ ${pc4.dim("Documentaci\xF3n profesional para proyectos con agentes AI")}`
617
4230
  );
618
- const projectName = await p.text({
4231
+ const projectName = await p2.text({
619
4232
  message: `${icons.sparkle} Nombre del proyecto`,
620
4233
  placeholder: "mi-proyecto",
621
4234
  validate: (value) => {
@@ -625,11 +4238,11 @@ async function cli() {
625
4238
  }
626
4239
  }
627
4240
  });
628
- if (p.isCancel(projectName)) {
629
- p.cancel("Operaci\xF3n cancelada.");
4241
+ if (p2.isCancel(projectName)) {
4242
+ p2.cancel("Operaci\xF3n cancelada.");
630
4243
  process.exit(0);
631
4244
  }
632
- const targetDir = await p.text({
4245
+ const targetDir = await p2.text({
633
4246
  message: `${icons.folder} Directorio de destino`,
634
4247
  placeholder: "./",
635
4248
  initialValue: "./",
@@ -637,22 +4250,22 @@ async function cli() {
637
4250
  if (!value.trim()) return "El directorio es obligatorio.";
638
4251
  }
639
4252
  });
640
- if (p.isCancel(targetDir)) {
641
- p.cancel("Operaci\xF3n cancelada.");
4253
+ if (p2.isCancel(targetDir)) {
4254
+ p2.cancel("Operaci\xF3n cancelada.");
642
4255
  process.exit(0);
643
4256
  }
644
- const resolvedDir = path4.resolve(targetDir.trim());
4257
+ const resolvedDir = path7.resolve(targetDir.trim());
645
4258
  if (!isDirEmpty(resolvedDir)) {
646
- const overwrite = await p.confirm({
4259
+ const overwrite = await p2.confirm({
647
4260
  message: `${icons.warning} El directorio no est\xE1 vac\xEDo. \xBFContinuar? (puede sobrescribir archivos)`,
648
4261
  initialValue: false
649
4262
  });
650
- if (p.isCancel(overwrite) || !overwrite) {
651
- p.cancel("Operaci\xF3n cancelada.");
4263
+ if (p2.isCancel(overwrite) || !overwrite) {
4264
+ p2.cancel("Operaci\xF3n cancelada.");
652
4265
  process.exit(0);
653
4266
  }
654
4267
  }
655
- const stackOption = await p.select({
4268
+ const stackOption = await p2.select({
656
4269
  message: `${icons.search} Stack tecnol\xF3gico`,
657
4270
  options: [
658
4271
  { value: "auto", label: "Auto-detectar", hint: "recomendado \u2014 analiza el proyecto" },
@@ -660,13 +4273,13 @@ async function cli() {
660
4273
  { value: "skip", label: "Omitir", hint: "rellenar despu\xE9s" }
661
4274
  ]
662
4275
  });
663
- if (p.isCancel(stackOption)) {
664
- p.cancel("Operaci\xF3n cancelada.");
4276
+ if (p2.isCancel(stackOption)) {
4277
+ p2.cancel("Operaci\xF3n cancelada.");
665
4278
  process.exit(0);
666
4279
  }
667
4280
  let stack = null;
668
4281
  if (stackOption === "auto") {
669
- const s2 = p.spinner();
4282
+ const s2 = p2.spinner();
670
4283
  s2.start("Analizando proyecto...");
671
4284
  await new Promise((r) => setTimeout(r, 800));
672
4285
  stack = detectStack(resolvedDir);
@@ -676,9 +4289,9 @@ async function cli() {
676
4289
  s2.stop(`${icons.warning} No se detect\xF3 stack \u2014 los placeholders se rellenar\xE1n despu\xE9s`);
677
4290
  }
678
4291
  } else if (stackOption === "manual") {
679
- const manualStack = await p.group(
4292
+ const manualStack = await p2.group(
680
4293
  {
681
- language: () => p.select({
4294
+ language: () => p2.select({
682
4295
  message: "Lenguaje principal",
683
4296
  options: [
684
4297
  { value: "TypeScript", label: "TypeScript" },
@@ -690,14 +4303,14 @@ async function cli() {
690
4303
  { value: "Other", label: "Otro" }
691
4304
  ]
692
4305
  }),
693
- framework: () => p.text({
4306
+ framework: () => p2.text({
694
4307
  message: "Framework (opcional)",
695
4308
  placeholder: "Next.js 14, Django 5, etc."
696
4309
  })
697
4310
  },
698
4311
  {
699
4312
  onCancel: () => {
700
- p.cancel("Operaci\xF3n cancelada.");
4313
+ p2.cancel("Operaci\xF3n cancelada.");
701
4314
  process.exit(0);
702
4315
  }
703
4316
  }
@@ -707,7 +4320,7 @@ async function cli() {
707
4320
  framework: manualStack.framework?.trim() || void 0
708
4321
  };
709
4322
  }
710
- const language = await p.select({
4323
+ const language = await p2.select({
711
4324
  message: `${icons.docs} Idioma de la documentaci\xF3n`,
712
4325
  options: LANGUAGES.map((lang) => ({
713
4326
  value: lang.value,
@@ -715,24 +4328,24 @@ async function cli() {
715
4328
  hint: lang.hint
716
4329
  }))
717
4330
  });
718
- if (p.isCancel(language)) {
719
- p.cancel("Operaci\xF3n cancelada.");
4331
+ if (p2.isCancel(language)) {
4332
+ p2.cancel("Operaci\xF3n cancelada.");
720
4333
  process.exit(0);
721
4334
  }
722
- const allModules = await p.confirm({
4335
+ const allModules = await p2.confirm({
723
4336
  message: `${icons.package} \xBFIncluir todos los m\xF3dulos?`,
724
4337
  initialValue: true
725
4338
  });
726
- if (p.isCancel(allModules)) {
727
- p.cancel("Operaci\xF3n cancelada.");
4339
+ if (p2.isCancel(allModules)) {
4340
+ p2.cancel("Operaci\xF3n cancelada.");
728
4341
  process.exit(0);
729
4342
  }
730
4343
  let selectedModules;
731
4344
  if (allModules) {
732
4345
  selectedModules = DOC_MODULES.map((mod) => mod.value);
733
4346
  } else {
734
- const picked = await p.multiselect({
735
- message: `${icons.package} M\xF3dulos a incluir ${pc2.dim("(espacio para seleccionar, enter para confirmar)")}`,
4347
+ const picked = await p2.multiselect({
4348
+ message: `${icons.package} M\xF3dulos a incluir ${pc4.dim("(espacio para seleccionar, enter para confirmar)")}`,
736
4349
  options: DOC_MODULES.map((mod) => ({
737
4350
  value: mod.value,
738
4351
  label: mod.label,
@@ -740,71 +4353,75 @@ async function cli() {
740
4353
  })),
741
4354
  required: false
742
4355
  });
743
- if (p.isCancel(picked)) {
744
- p.cancel("Operaci\xF3n cancelada.");
4356
+ if (p2.isCancel(picked)) {
4357
+ p2.cancel("Operaci\xF3n cancelada.");
745
4358
  process.exit(0);
746
4359
  }
747
4360
  selectedModules = picked;
748
4361
  }
749
- const initGit2 = await p.confirm({
4362
+ const initGit2 = await p2.confirm({
750
4363
  message: `${icons.gear} \xBFInicializar repositorio git?`,
751
4364
  initialValue: true
752
4365
  });
753
- if (p.isCancel(initGit2)) {
754
- p.cancel("Operaci\xF3n cancelada.");
4366
+ if (p2.isCancel(initGit2)) {
4367
+ p2.cancel("Operaci\xF3n cancelada.");
755
4368
  process.exit(0);
756
4369
  }
757
- const modulesLabel = selectedModules.length > 0 ? selectedModules.join(", ") : pc2.dim("ninguno (solo archivos base)");
758
- p.note(
4370
+ const modulesLabel = selectedModules.length > 0 ? selectedModules.join(", ") : pc4.dim("ninguno (solo archivos base)");
4371
+ p2.note(
759
4372
  [
760
4373
  `${brand.label("Proyecto")}: ${projectName}`,
761
4374
  `${brand.label("Directorio")}: ${brand.path(resolvedDir)}`,
762
- `${brand.label("Stack")}: ${stack ? formatStack(stack) : pc2.dim("no detectado")}`,
4375
+ `${brand.label("Stack")}: ${stack ? formatStack(stack) : pc4.dim("no detectado")}`,
763
4376
  `${brand.label("Idioma")}: ${language === "es" ? "Espa\xF1ol" : "English"}`,
764
4377
  `${brand.label("M\xF3dulos")}: ${modulesLabel}`,
765
4378
  `${brand.label("Git")}: ${initGit2 ? "S\xED" : "No"}`
766
4379
  ].join("\n"),
767
4380
  `${icons.chart} Resumen`
768
4381
  );
769
- const confirmed = await p.confirm({
4382
+ const confirmed = await p2.confirm({
770
4383
  message: "\xBFGenerar documentaci\xF3n?",
771
4384
  initialValue: true
772
4385
  });
773
- if (p.isCancel(confirmed) || !confirmed) {
774
- p.cancel("Operaci\xF3n cancelada.");
4386
+ if (p2.isCancel(confirmed) || !confirmed) {
4387
+ p2.cancel("Operaci\xF3n cancelada.");
775
4388
  process.exit(0);
776
4389
  }
777
- const s = p.spinner();
778
- s.start("Creando estructura de documentaci\xF3n...");
779
- await new Promise((r) => setTimeout(r, 400));
780
- s.message("Generando archivos base (AGENTS.md, CONTEXT.md, ADR...)");
781
- await new Promise((r) => setTimeout(r, 500));
782
- if (selectedModules.length > 0) {
783
- s.message(`A\xF1adiendo m\xF3dulos: ${selectedModules.join(", ")}`);
4390
+ const s = p2.spinner();
4391
+ if (!isDryRun) {
4392
+ s.start("Creando estructura de documentaci\xF3n...");
784
4393
  await new Promise((r) => setTimeout(r, 400));
4394
+ s.message("Generando archivos base (AGENTS.md, CONTEXT.md, ADR...)");
4395
+ await new Promise((r) => setTimeout(r, 500));
4396
+ if (selectedModules.length > 0) {
4397
+ s.message(`A\xF1adiendo m\xF3dulos: ${selectedModules.join(", ")}`);
4398
+ await new Promise((r) => setTimeout(r, 400));
4399
+ }
785
4400
  }
786
- const createdFiles = await generate({
4401
+ const createdFiles = await generate23({
787
4402
  projectName: projectName.trim(),
788
4403
  targetDir: resolvedDir,
789
4404
  stack,
790
4405
  modules: selectedModules,
791
4406
  language,
792
- initGit: initGit2
4407
+ initGit: initGit2,
4408
+ force: isForce,
4409
+ dryRun: isDryRun
793
4410
  });
794
4411
  if (initGit2) {
795
4412
  s.message("Inicializando repositorio git...");
796
4413
  await new Promise((r) => setTimeout(r, 300));
797
4414
  }
798
- s.stop(`${icons.check} ${brand.success(`${createdFiles.length} archivos generados`)}`);
4415
+ if (!isDryRun) {
4416
+ s.stop(`${icons.check} ${brand.success(`${createdFiles.length} archivos generados`)}`);
4417
+ }
799
4418
  const nextSteps = [
800
- `${pc2.bold("1.")} Rellenar ${brand.path("docs/CONTEXT.md")} con los t\xE9rminos del dominio`,
801
- `${pc2.bold("2.")} Revisar ${brand.path("AGENTS.md")} y ajustar stack/comandos`,
802
- `${pc2.bold("3.")} Ejecutar ${pc2.cyan("npx @damenor/agent-docs --help")} para m\xE1s opciones`
4419
+ `${pc4.bold("1.")} Rellenar ${brand.path("docs/CONTEXT.md")} con los t\xE9rminos del dominio`,
4420
+ `${pc4.bold("2.")} Revisar ${brand.path("AGENTS.md")} y ajustar stack/comandos`,
4421
+ `${pc4.bold("3.")} Ejecutar ${pc4.cyan("npx @damenor/agent-docs --help")} para m\xE1s opciones`
803
4422
  ];
804
- p.note(nextSteps.join("\n"), `${icons.rocket} Pr\xF3ximos pasos`);
805
- p.outro(
806
- `${icons.sparkle} ${brand.title("\xA1Documentaci\xF3n lista!")} ${pc2.dim("\u2014 github.com/damenordev/doc-projects")}`
807
- );
4423
+ p2.note(nextSteps.join("\n"), `${icons.rocket} Pr\xF3ximos pasos`);
4424
+ p2.outro(`${icons.sparkle} ${brand.title("\xA1Documentaci\xF3n lista!")} ${pc4.dim("\u2014 github.com/damenordev/doc-projects")}`);
808
4425
  }
809
4426
 
810
4427
  // src/index.ts