agent-rules-init 0.1.3 → 0.2.1

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.
@@ -0,0 +1,74 @@
1
+ const FRAMEWORKS = [
2
+ ["gin-gonic/gin", "gin"],
3
+ ["labstack/echo", "echo"],
4
+ ["gofiber/fiber", "fiber"],
5
+ ["go-chi/chi", "chi"],
6
+ ];
7
+ // The `module` line of go.mod is the project's own import path, not a dependency —
8
+ // searching the whole file would false-positive on a framework whose own repo module
9
+ // path happens to match a known framework name (e.g. gofiber/fiber's own go.mod
10
+ // declares `module github.com/gofiber/fiber/v3`). Scope the search to `require` entries.
11
+ function extractGoRequireSection(goMod) {
12
+ const sections = [];
13
+ for (const m of goMod.matchAll(/require\s*\(([\s\S]*?)\)/g))
14
+ sections.push(m[1]);
15
+ for (const m of goMod.matchAll(/^require\s+(?!\()(.+)$/gm))
16
+ sections.push(m[1]);
17
+ return sections.length > 0 ? sections.join("\n") : goMod;
18
+ }
19
+ function detect(signals) {
20
+ const source = signals.goMod;
21
+ if (!source)
22
+ return null;
23
+ const lower = extractGoRequireSection(source).toLowerCase();
24
+ let framework = { value: "none", confidence: "low" };
25
+ for (const [needle, label] of FRAMEWORKS) {
26
+ if (lower.includes(needle)) {
27
+ framework = { value: label, confidence: "high" };
28
+ break;
29
+ }
30
+ }
31
+ return {
32
+ packId: "go",
33
+ language: "Go",
34
+ framework,
35
+ testRunner: { value: "go test", confidence: "high" },
36
+ packageManager: { value: "go modules", confidence: "high" },
37
+ };
38
+ }
39
+ function rules(detection) {
40
+ const framework = detection.framework?.value ?? "none";
41
+ return {
42
+ summary: `Proyecto Go${framework !== "none" ? ` con ${framework}` : ""} (go modules).`,
43
+ conventions: [
44
+ "Sigue el formato estándar de `gofmt`; no introduzcas estilos alternativos.",
45
+ "Ejecuta los tests con `go test ./...` antes de terminar una tarea.",
46
+ "Maneja los errores explícitamente (`if err != nil`); no los ignores en silencio.",
47
+ ],
48
+ architectureNotes: [
49
+ "Mantén los paquetes con una responsabilidad clara; evita paquetes `util` genéricos.",
50
+ "Declara toda dependencia nueva vía `go get` y mantén `go.mod`/`go.sum` sincronizados.",
51
+ ],
52
+ };
53
+ }
54
+ function promptTemplates(detection) {
55
+ const framework = detection.framework?.value ?? "el framework del proyecto";
56
+ return [
57
+ {
58
+ id: "review",
59
+ title: "Code Review (Go)",
60
+ body: `Revisa el diff actual buscando bugs, manejo de errores omitido y desviaciones de las convenciones de ${framework}. Señala solo problemas concretos con línea de archivo.`,
61
+ },
62
+ {
63
+ id: "refactor",
64
+ title: "Refactor (Go)",
65
+ body: `Propón refactors que reduzcan duplicación y mejoren la legibilidad sin cambiar comportamiento observable.`,
66
+ },
67
+ {
68
+ id: "testing",
69
+ title: "Testing (Go)",
70
+ body: `Escribe tests con \`go test\` para el código señalado. Cubre el camino feliz y al menos un caso límite.`,
71
+ },
72
+ ];
73
+ }
74
+ export const goPack = { id: "go", detect, rules, promptTemplates };
@@ -0,0 +1,2 @@
1
+ import type { Pack } from "../core/types.js";
2
+ export declare const javaPack: Pack;
@@ -0,0 +1,59 @@
1
+ function detect(signals) {
2
+ const source = signals.pomXml ?? signals.buildGradle;
3
+ if (!source)
4
+ return null;
5
+ // A Gradle build that applies the Kotlin plugin is a Kotlin project, not Java —
6
+ // defer entirely to the Kotlin pack instead of also reporting a spurious Java match.
7
+ // Modern Gradle projects often declare plugins via version catalogs
8
+ // (`alias(libs.plugins.kotlin.android)`) rather than the literal `kotlin("jvm")` or
9
+ // `org.jetbrains.kotlin` plugin id, so a plain word-boundary check on "kotlin" is
10
+ // more robust than trying to match every DSL style.
11
+ if (/\bkotlin\b/i.test(source))
12
+ return null;
13
+ const framework = /spring/i.test(source)
14
+ ? { value: "spring", confidence: "high" }
15
+ : { value: "none", confidence: "low" };
16
+ const packageManager = signals.pomXml
17
+ ? { value: "maven", confidence: "high" }
18
+ : { value: "gradle", confidence: "high" };
19
+ const testRunner = /junit/i.test(source)
20
+ ? { value: "junit", confidence: "high" }
21
+ : { value: "unknown", confidence: "low" };
22
+ return { packId: "java", language: "Java", framework, packageManager, testRunner };
23
+ }
24
+ function rules(detection) {
25
+ const framework = detection.framework?.value ?? "none";
26
+ return {
27
+ summary: `Proyecto Java${framework !== "none" ? ` con ${framework}` : ""} (${detection.packageManager?.value}).`,
28
+ conventions: [
29
+ "Sigue las convenciones de nombrado estándar de Java (PascalCase para clases, camelCase para métodos).",
30
+ `Ejecuta los tests con ${detection.packageManager?.value === "maven" ? "mvn test" : "gradle test"} antes de terminar una tarea.`,
31
+ "No añadas dependencias nuevas sin declararlas en el gestor de build existente.",
32
+ ],
33
+ architectureNotes: [
34
+ "Respeta la separación en capas (controller/service/repository) si el proyecto ya la usa.",
35
+ "Prefiere inyección de dependencias sobre instanciación manual cuando el framework ya la ofrezca.",
36
+ ],
37
+ };
38
+ }
39
+ function promptTemplates(detection) {
40
+ const framework = detection.framework?.value ?? "el framework del proyecto";
41
+ return [
42
+ {
43
+ id: "review",
44
+ title: "Code Review (Java)",
45
+ body: `Revisa el diff actual buscando bugs, null-safety y desviaciones de las convenciones de ${framework}. Señala solo problemas concretos con línea de archivo.`,
46
+ },
47
+ {
48
+ id: "refactor",
49
+ title: "Refactor (Java)",
50
+ body: `Propón refactors que reduzcan duplicación y mejoren la legibilidad sin cambiar comportamiento observable.`,
51
+ },
52
+ {
53
+ id: "testing",
54
+ title: "Testing (Java)",
55
+ body: `Escribe tests con ${detection.testRunner?.value ?? "el test runner del proyecto"} para el código señalado. Cubre el camino feliz y al menos un caso límite.`,
56
+ },
57
+ ];
58
+ }
59
+ export const javaPack = { id: "java", detect, rules, promptTemplates };
@@ -0,0 +1,2 @@
1
+ import type { Pack } from "../core/types.js";
2
+ export declare const jsTsPack: Pack;
@@ -0,0 +1,101 @@
1
+ const FRAMEWORKS = {
2
+ next: "next",
3
+ "@nestjs/core": "nestjs",
4
+ react: "react",
5
+ vue: "vue",
6
+ "@angular/core": "angular",
7
+ svelte: "svelte",
8
+ fastify: "fastify",
9
+ koa: "koa",
10
+ express: "express",
11
+ };
12
+ const TEST_RUNNERS = {
13
+ vitest: "vitest",
14
+ jest: "jest",
15
+ mocha: "mocha",
16
+ };
17
+ const LINTERS = {
18
+ eslint: "eslint",
19
+ biome: "biome",
20
+ };
21
+ function detectFromDeps(deps, table) {
22
+ for (const [depName, label] of Object.entries(table)) {
23
+ if (deps[depName])
24
+ return { value: label, confidence: "high" };
25
+ }
26
+ return undefined;
27
+ }
28
+ function detect(signals) {
29
+ if (!signals.packageJson)
30
+ return null;
31
+ const allDeps = { ...signals.packageJson.dependencies, ...signals.packageJson.devDependencies };
32
+ const framework = detectFromDeps(allDeps, FRAMEWORKS) ?? {
33
+ value: "none",
34
+ confidence: "low",
35
+ };
36
+ const testRunner = detectFromDeps(allDeps, TEST_RUNNERS) ?? {
37
+ value: "unknown",
38
+ confidence: "low",
39
+ };
40
+ const linter = detectFromDeps(allDeps, LINTERS) ?? { value: "unknown", confidence: "low" };
41
+ const packageManager = signals.hasFile("pnpm-lock.yaml")
42
+ ? { value: "pnpm", confidence: "high" }
43
+ : signals.hasFile("yarn.lock")
44
+ ? { value: "yarn", confidence: "high" }
45
+ : signals.hasFile("package-lock.json")
46
+ ? { value: "npm", confidence: "high" }
47
+ : { value: "npm", confidence: "low" };
48
+ const usesTypeScript = Boolean(allDeps.typescript) || signals.hasFile("tsconfig.json");
49
+ const moduleFormat = signals.packageJson.moduleType;
50
+ return {
51
+ packId: "js-ts",
52
+ language: usesTypeScript ? "TypeScript" : "JavaScript",
53
+ framework,
54
+ testRunner,
55
+ linter,
56
+ packageManager,
57
+ usesTypeScript,
58
+ moduleFormat,
59
+ };
60
+ }
61
+ function rules(detection) {
62
+ const framework = detection.framework?.value ?? "none";
63
+ const testRunner = detection.testRunner?.value ?? "unknown";
64
+ const conventions = [];
65
+ if (detection.usesTypeScript) {
66
+ conventions.push("Usa TypeScript estricto; evita `any` salvo justificación explícita.");
67
+ }
68
+ conventions.push(`Ejecuta los tests con ${testRunner === "unknown" ? "el test runner del proyecto" : testRunner} antes de dar por terminada una tarea.`);
69
+ conventions.push(detection.moduleFormat === "module"
70
+ ? "Sigue el estilo de módulos ES existente (import/export), no mezcles con require()."
71
+ : "Sigue el estilo CommonJS existente (require()/module.exports), no mezcles con import/export.");
72
+ return {
73
+ summary: `Proyecto ${detection.usesTypeScript ? "TypeScript" : "JavaScript"}${framework !== "none" ? ` con ${framework}` : ""}.`,
74
+ conventions,
75
+ architectureNotes: [
76
+ "Mantén los componentes/módulos pequeños y con una responsabilidad clara.",
77
+ "Coloca los tests junto al código que prueban o en un directorio `test/` espejo, según lo que ya use el repo.",
78
+ ],
79
+ };
80
+ }
81
+ function promptTemplates(detection) {
82
+ const framework = detection.framework?.value ?? "el framework del proyecto";
83
+ return [
84
+ {
85
+ id: "review",
86
+ title: "Code Review (JS/TS)",
87
+ body: `Revisa el diff actual buscando bugs de tipado, condiciones de carrera en async/await, y desviaciones de las convenciones de ${framework}. Señala solo problemas concretos con línea de archivo.`,
88
+ },
89
+ {
90
+ id: "refactor",
91
+ title: "Refactor (JS/TS)",
92
+ body: `Propón refactors que reduzcan duplicación y mejoren la legibilidad sin cambiar comportamiento observable. Respeta los tipos existentes.`,
93
+ },
94
+ {
95
+ id: "testing",
96
+ title: "Testing (JS/TS)",
97
+ body: `Escribe tests para el código señalado usando el test runner detectado (${detection.testRunner?.value ?? "el del proyecto"}). Cubre el camino feliz y al menos un caso límite.`,
98
+ },
99
+ ];
100
+ }
101
+ export const jsTsPack = { id: "js-ts", detect, rules, promptTemplates };
@@ -0,0 +1,2 @@
1
+ import type { Pack } from "../core/types.js";
2
+ export declare const kotlinPack: Pack;
@@ -0,0 +1,65 @@
1
+ function detect(signals) {
2
+ const source = signals.buildGradle;
3
+ if (!source)
4
+ return null;
5
+ // Modern Gradle projects often declare the Kotlin plugin via a version catalog alias
6
+ // (`alias(libs.plugins.kotlin.android)`) rather than the literal `kotlin("jvm")` or
7
+ // `org.jetbrains.kotlin` plugin id, so a plain word-boundary check is more robust.
8
+ if (!/\bkotlin\b/i.test(source))
9
+ return null;
10
+ const framework = /ktor/i.test(source)
11
+ ? { value: "ktor", confidence: "high" }
12
+ : /com\.android\.application|com\.android\.library/i.test(source)
13
+ ? { value: "android", confidence: "high" }
14
+ : /spring/i.test(source)
15
+ ? { value: "spring", confidence: "high" }
16
+ : { value: "none", confidence: "low" };
17
+ const testRunner = /kotlin\.test|kotest/i.test(source)
18
+ ? { value: "kotest", confidence: "high" }
19
+ : /junit/i.test(source)
20
+ ? { value: "junit", confidence: "high" }
21
+ : { value: "unknown", confidence: "low" };
22
+ return {
23
+ packId: "kotlin",
24
+ language: "Kotlin",
25
+ framework,
26
+ testRunner,
27
+ packageManager: { value: "gradle", confidence: "high" },
28
+ };
29
+ }
30
+ function rules(detection) {
31
+ const framework = detection.framework?.value ?? "none";
32
+ return {
33
+ summary: `Proyecto Kotlin${framework !== "none" ? ` con ${framework}` : ""} (gradle).`,
34
+ conventions: [
35
+ "Sigue las convenciones de estilo oficiales de Kotlin (kotlinlang.org/docs/coding-conventions.html).",
36
+ "Ejecuta los tests con `gradle test` antes de terminar una tarea.",
37
+ "Prefiere tipos no-nulos y `val` sobre `var` salvo que la mutabilidad sea necesaria.",
38
+ ],
39
+ architectureNotes: [
40
+ "Respeta la separación en capas (controller/service/repository) si el proyecto ya la usa.",
41
+ "Prefiere inyección de dependencias sobre instanciación manual cuando el framework ya la ofrezca.",
42
+ ],
43
+ };
44
+ }
45
+ function promptTemplates(detection) {
46
+ const framework = detection.framework?.value ?? "el framework del proyecto";
47
+ return [
48
+ {
49
+ id: "review",
50
+ title: "Code Review (Kotlin)",
51
+ body: `Revisa el diff actual buscando bugs, uso innecesario de \`!!\` y desviaciones de las convenciones de ${framework}. Señala solo problemas concretos con línea de archivo.`,
52
+ },
53
+ {
54
+ id: "refactor",
55
+ title: "Refactor (Kotlin)",
56
+ body: `Propón refactors que reduzcan duplicación y mejoren la legibilidad sin cambiar comportamiento observable.`,
57
+ },
58
+ {
59
+ id: "testing",
60
+ title: "Testing (Kotlin)",
61
+ body: `Escribe tests con ${detection.testRunner?.value !== "unknown" ? detection.testRunner?.value : "el test runner del proyecto"} para el código señalado. Cubre el camino feliz y al menos un caso límite.`,
62
+ },
63
+ ];
64
+ }
65
+ export const kotlinPack = { id: "kotlin", detect, rules, promptTemplates };
@@ -0,0 +1,2 @@
1
+ import type { Pack } from "../core/types.js";
2
+ export declare const phpPack: Pack;
@@ -0,0 +1,63 @@
1
+ const FRAMEWORKS = {
2
+ "laravel/framework": "laravel",
3
+ "symfony/symfony": "symfony",
4
+ "codeigniter4/framework": "codeigniter",
5
+ };
6
+ function detect(signals) {
7
+ if (!signals.composerJson)
8
+ return null;
9
+ const allDeps = { ...signals.composerJson.require, ...signals.composerJson.requireDev };
10
+ let framework = { value: "none", confidence: "low" };
11
+ for (const [dep, label] of Object.entries(FRAMEWORKS)) {
12
+ if (allDeps[dep]) {
13
+ framework = { value: label, confidence: "high" };
14
+ break;
15
+ }
16
+ }
17
+ const testRunner = allDeps["phpunit/phpunit"]
18
+ ? { value: "phpunit", confidence: "high" }
19
+ : { value: "unknown", confidence: "low" };
20
+ return {
21
+ packId: "php",
22
+ language: "PHP",
23
+ framework,
24
+ testRunner,
25
+ packageManager: { value: "composer", confidence: "high" },
26
+ };
27
+ }
28
+ function rules(detection) {
29
+ const framework = detection.framework?.value ?? "none";
30
+ return {
31
+ summary: `Proyecto PHP${framework !== "none" ? ` con ${framework}` : ""} (composer).`,
32
+ conventions: [
33
+ "Sigue PSR-12 para el estilo de código.",
34
+ `Ejecuta los tests con ${detection.testRunner?.value === "phpunit" ? "vendor/bin/phpunit" : "el test runner del proyecto"} antes de terminar una tarea.`,
35
+ "Declara toda dependencia nueva en composer.json, nunca la instales sin registrarla.",
36
+ ],
37
+ architectureNotes: [
38
+ "Respeta la estructura MVC del framework si el proyecto ya la sigue.",
39
+ "Evita lógica de negocio en los controladores cuando el proyecto ya use capas de servicio.",
40
+ ],
41
+ };
42
+ }
43
+ function promptTemplates(detection) {
44
+ const framework = detection.framework?.value ?? "el framework del proyecto";
45
+ return [
46
+ {
47
+ id: "review",
48
+ title: "Code Review (PHP)",
49
+ body: `Revisa el diff actual buscando bugs y desviaciones de las convenciones de ${framework}. Señala solo problemas concretos con línea de archivo.`,
50
+ },
51
+ {
52
+ id: "refactor",
53
+ title: "Refactor (PHP)",
54
+ body: `Propón refactors que reduzcan duplicación y mejoren la legibilidad sin cambiar comportamiento observable.`,
55
+ },
56
+ {
57
+ id: "testing",
58
+ title: "Testing (PHP)",
59
+ body: `Escribe tests con ${detection.testRunner?.value === "phpunit" ? "PHPUnit" : "el test runner del proyecto"} para el código señalado. Cubre el camino feliz y al menos un caso límite.`,
60
+ },
61
+ ];
62
+ }
63
+ export const phpPack = { id: "php", detect, rules, promptTemplates };
@@ -0,0 +1,2 @@
1
+ import type { Pack } from "../core/types.js";
2
+ export declare const pythonPack: Pack;
@@ -0,0 +1,88 @@
1
+ const FRAMEWORKS = [
2
+ ["fastapi", "fastapi"],
3
+ ["django", "django"],
4
+ ["flask", "flask"],
5
+ ];
6
+ const TEST_RUNNERS = [
7
+ ["pytest", "pytest"],
8
+ ["unittest", "unittest"],
9
+ ];
10
+ function findIn(haystack, table) {
11
+ const lower = haystack.toLowerCase();
12
+ for (const [needle, label] of table) {
13
+ if (lower.includes(needle))
14
+ return { value: label, confidence: "high" };
15
+ }
16
+ return undefined;
17
+ }
18
+ // Searching the whole pyproject.toml text (project name, URLs, script entry points, etc.)
19
+ // produces false positives — e.g. Flask's own pyproject.toml has `name = "flask"`, which
20
+ // isn't a dependency at all. Scope the search to the actual dependency declarations.
21
+ function extractPyprojectDependencySections(pyproject) {
22
+ const sections = [];
23
+ const mainDeps = pyproject.match(/(?:^|\n)dependencies\s*=\s*\[([\s\S]*?)\]/);
24
+ if (mainDeps)
25
+ sections.push(mainDeps[1]);
26
+ const optionalDeps = pyproject.match(/\[project\.optional-dependencies\]([\s\S]*?)(?:\n\[|$)/);
27
+ if (optionalDeps)
28
+ sections.push(optionalDeps[1]);
29
+ const dependencyGroups = pyproject.match(/\[dependency-groups\]([\s\S]*?)(?:\n\[|$)/);
30
+ if (dependencyGroups)
31
+ sections.push(dependencyGroups[1]);
32
+ const poetryDepsBlocks = pyproject.match(/\[tool\.poetry(?:\.group\.\w+)?\.dependencies\]([\s\S]*?)(?:\n\[|$)/g);
33
+ if (poetryDepsBlocks)
34
+ sections.push(...poetryDepsBlocks);
35
+ return sections.length > 0 ? sections.join("\n") : pyproject;
36
+ }
37
+ function detect(signals) {
38
+ const source = signals.pyprojectToml ?? signals.requirementsTxt ?? signals.environmentYml;
39
+ if (!source)
40
+ return null;
41
+ const searchText = signals.pyprojectToml ? extractPyprojectDependencySections(signals.pyprojectToml) : source;
42
+ const framework = findIn(searchText, FRAMEWORKS) ?? { value: "none", confidence: "low" };
43
+ const testRunner = findIn(searchText, TEST_RUNNERS) ?? { value: "unknown", confidence: "low" };
44
+ const packageManager = signals.environmentYml
45
+ ? { value: "conda", confidence: "high" }
46
+ : signals.hasFile("poetry.lock")
47
+ ? { value: "poetry", confidence: "high" }
48
+ : signals.pyprojectToml
49
+ ? { value: "pip (pyproject.toml)", confidence: "low" }
50
+ : { value: "pip", confidence: "low" };
51
+ return { packId: "python", language: "Python", framework, testRunner, packageManager };
52
+ }
53
+ function rules(detection) {
54
+ const framework = detection.framework?.value ?? "none";
55
+ return {
56
+ summary: `Proyecto Python${framework !== "none" ? ` con ${framework}` : ""}.`,
57
+ conventions: [
58
+ "Sigue PEP 8; usa type hints en funciones públicas.",
59
+ `Ejecuta los tests con ${detection.testRunner?.value ?? "el test runner del proyecto"} antes de terminar una tarea.`,
60
+ "No introduzcas dependencias nuevas sin añadirlas al manifiesto de dependencias existente.",
61
+ ],
62
+ architectureNotes: [
63
+ "Mantén la lógica de negocio separada de la capa de framework cuando el proyecto ya siga ese patrón.",
64
+ "Usa entornos virtuales; no instales paquetes globalmente.",
65
+ ],
66
+ };
67
+ }
68
+ function promptTemplates(detection) {
69
+ const framework = detection.framework?.value ?? "el framework del proyecto";
70
+ return [
71
+ {
72
+ id: "review",
73
+ title: "Code Review (Python)",
74
+ body: `Revisa el diff actual buscando bugs, manejo de excepciones incorrecto y desviaciones de las convenciones de ${framework}. Señala solo problemas concretos con línea de archivo.`,
75
+ },
76
+ {
77
+ id: "refactor",
78
+ title: "Refactor (Python)",
79
+ body: `Propón refactors que reduzcan duplicación y mejoren la legibilidad sin cambiar comportamiento observable. Respeta los type hints existentes.`,
80
+ },
81
+ {
82
+ id: "testing",
83
+ title: "Testing (Python)",
84
+ body: `Escribe tests para el código señalado usando ${detection.testRunner?.value ?? "el test runner del proyecto"}. Cubre el camino feliz y al menos un caso límite.`,
85
+ },
86
+ ];
87
+ }
88
+ export const pythonPack = { id: "python", detect, rules, promptTemplates };
@@ -0,0 +1,2 @@
1
+ import type { Pack } from "../core/types.js";
2
+ export declare const rPack: Pack;
@@ -0,0 +1,60 @@
1
+ const FRAMEWORKS = [
2
+ ["shiny", "shiny"],
3
+ ["plumber", "plumber"],
4
+ ];
5
+ function detect(signals) {
6
+ const source = signals.rDescription ?? signals.renvLock;
7
+ if (!source)
8
+ return null;
9
+ const lower = source.toLowerCase();
10
+ let framework = { value: "none", confidence: "low" };
11
+ for (const [needle, label] of FRAMEWORKS) {
12
+ if (lower.includes(needle)) {
13
+ framework = { value: label, confidence: "high" };
14
+ break;
15
+ }
16
+ }
17
+ const testRunner = lower.includes("testthat")
18
+ ? { value: "testthat", confidence: "high" }
19
+ : { value: "unknown", confidence: "low" };
20
+ const packageManager = signals.renvLock
21
+ ? { value: "renv", confidence: "high" }
22
+ : { value: "CRAN", confidence: "low" };
23
+ return { packId: "r", language: "R", framework, testRunner, packageManager };
24
+ }
25
+ function rules(detection) {
26
+ const framework = detection.framework?.value ?? "none";
27
+ return {
28
+ summary: `Proyecto R${framework !== "none" ? ` con ${framework}` : ""} (${detection.packageManager?.value}).`,
29
+ conventions: [
30
+ "Sigue la guía de estilo tidyverse (style.tidyverse.org) salvo que el proyecto ya use otra.",
31
+ `Ejecuta los tests con ${detection.testRunner?.value === "testthat" ? "testthat::test_dir(\"tests\")" : "el test runner del proyecto"} antes de terminar una tarea.`,
32
+ "Declara toda dependencia nueva en DESCRIPTION y actualiza renv.lock si el proyecto usa renv.",
33
+ ],
34
+ architectureNotes: [
35
+ "Mantén las funciones puras y con una responsabilidad clara; evita modificar el entorno global.",
36
+ "Separa el análisis/scripts de la lógica reutilizable empaquetada en funciones.",
37
+ ],
38
+ };
39
+ }
40
+ function promptTemplates(detection) {
41
+ const framework = detection.framework?.value ?? "el framework del proyecto";
42
+ return [
43
+ {
44
+ id: "review",
45
+ title: "Code Review (R)",
46
+ body: `Revisa el diff actual buscando bugs y desviaciones de las convenciones de ${framework}. Señala solo problemas concretos con línea de archivo.`,
47
+ },
48
+ {
49
+ id: "refactor",
50
+ title: "Refactor (R)",
51
+ body: `Propón refactors que reduzcan duplicación y mejoren la legibilidad sin cambiar comportamiento observable.`,
52
+ },
53
+ {
54
+ id: "testing",
55
+ title: "Testing (R)",
56
+ body: `Escribe tests con ${detection.testRunner?.value !== "unknown" ? detection.testRunner?.value : "el test runner del proyecto"} para el código señalado. Cubre el camino feliz y al menos un caso límite.`,
57
+ },
58
+ ];
59
+ }
60
+ export const rPack = { id: "r", detect, rules, promptTemplates };
@@ -0,0 +1,2 @@
1
+ import type { Pack } from "../core/types.js";
2
+ export declare const rubyPack: Pack;
@@ -0,0 +1,59 @@
1
+ function detect(signals) {
2
+ const source = signals.gemfile;
3
+ if (!source)
4
+ return null;
5
+ const lower = source.toLowerCase();
6
+ const framework = /gem\s+['"]rails['"]/.test(lower)
7
+ ? { value: "rails", confidence: "high" }
8
+ : /gem\s+['"]sinatra['"]/.test(lower)
9
+ ? { value: "sinatra", confidence: "high" }
10
+ : { value: "none", confidence: "low" };
11
+ const testRunner = /gem\s+['"]rspec/.test(lower)
12
+ ? { value: "rspec", confidence: "high" }
13
+ : /gem\s+['"]minitest['"]/.test(lower)
14
+ ? { value: "minitest", confidence: "high" }
15
+ : { value: "unknown", confidence: "low" };
16
+ return {
17
+ packId: "ruby",
18
+ language: "Ruby",
19
+ framework,
20
+ testRunner,
21
+ packageManager: { value: "bundler", confidence: "high" },
22
+ };
23
+ }
24
+ function rules(detection) {
25
+ const framework = detection.framework?.value ?? "none";
26
+ return {
27
+ summary: `Proyecto Ruby${framework !== "none" ? ` con ${framework}` : ""} (bundler).`,
28
+ conventions: [
29
+ "Sigue la guía de estilo Ruby estándar (snake_case para métodos/variables, CamelCase para clases).",
30
+ `Ejecuta los tests con ${detection.testRunner?.value === "rspec" ? "bundle exec rspec" : detection.testRunner?.value === "minitest" ? "bundle exec rake test" : "el test runner del proyecto"} antes de terminar una tarea.`,
31
+ "Declara toda dependencia nueva en el Gemfile, nunca instales una gema sin registrarla.",
32
+ ],
33
+ architectureNotes: [
34
+ "Respeta la estructura MVC del framework si el proyecto ya la sigue.",
35
+ "Evita lógica de negocio en los controladores cuando el proyecto ya use capas de servicio.",
36
+ ],
37
+ };
38
+ }
39
+ function promptTemplates(detection) {
40
+ const framework = detection.framework?.value ?? "el framework del proyecto";
41
+ return [
42
+ {
43
+ id: "review",
44
+ title: "Code Review (Ruby)",
45
+ body: `Revisa el diff actual buscando bugs y desviaciones de las convenciones de ${framework}. Señala solo problemas concretos con línea de archivo.`,
46
+ },
47
+ {
48
+ id: "refactor",
49
+ title: "Refactor (Ruby)",
50
+ body: `Propón refactors que reduzcan duplicación y mejoren la legibilidad sin cambiar comportamiento observable.`,
51
+ },
52
+ {
53
+ id: "testing",
54
+ title: "Testing (Ruby)",
55
+ body: `Escribe tests con ${detection.testRunner?.value !== "unknown" ? detection.testRunner?.value : "el test runner del proyecto"} para el código señalado. Cubre el camino feliz y al menos un caso límite.`,
56
+ },
57
+ ];
58
+ }
59
+ export const rubyPack = { id: "ruby", detect, rules, promptTemplates };
@@ -0,0 +1,2 @@
1
+ import type { Pack } from "../core/types.js";
2
+ export declare const rustPack: Pack;