@cristiancorreau/forge 2.2.0 → 2.4.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.
Files changed (44) hide show
  1. package/README.md +52 -109
  2. package/assets/core/hooks/pre-bash-check.js +144 -0
  3. package/assets/core/hooks/pre-edit-check.js +166 -0
  4. package/dist/cli.js +1 -1
  5. package/dist/commands/audit.d.ts.map +1 -1
  6. package/dist/commands/audit.js +27 -7
  7. package/dist/commands/audit.js.map +1 -1
  8. package/dist/commands/doctor.d.ts.map +1 -1
  9. package/dist/commands/doctor.js +54 -19
  10. package/dist/commands/doctor.js.map +1 -1
  11. package/dist/commands/generate.d.ts.map +1 -1
  12. package/dist/commands/generate.js +88 -37
  13. package/dist/commands/generate.js.map +1 -1
  14. package/dist/commands/init.d.ts.map +1 -1
  15. package/dist/commands/init.js +43 -5
  16. package/dist/commands/init.js.map +1 -1
  17. package/dist/lib/detect.d.ts +13 -0
  18. package/dist/lib/detect.d.ts.map +1 -0
  19. package/dist/lib/detect.js +85 -0
  20. package/dist/lib/detect.js.map +1 -0
  21. package/dist/lib/generators/claude-code.d.ts.map +1 -1
  22. package/dist/lib/generators/claude-code.js +7 -1
  23. package/dist/lib/generators/claude-code.js.map +1 -1
  24. package/dist/lib/lock.d.ts +15 -0
  25. package/dist/lib/lock.d.ts.map +1 -0
  26. package/dist/lib/lock.js +48 -0
  27. package/dist/lib/lock.js.map +1 -0
  28. package/dist/lib/wizard.d.ts +3 -2
  29. package/dist/lib/wizard.d.ts.map +1 -1
  30. package/dist/lib/wizard.js +211 -142
  31. package/dist/lib/wizard.js.map +1 -1
  32. package/dist/ui/box.d.ts +2 -0
  33. package/dist/ui/box.d.ts.map +1 -0
  34. package/dist/ui/box.js +15 -0
  35. package/dist/ui/box.js.map +1 -0
  36. package/dist/ui/colors.d.ts +15 -0
  37. package/dist/ui/colors.d.ts.map +1 -0
  38. package/dist/ui/colors.js +19 -0
  39. package/dist/ui/colors.js.map +1 -0
  40. package/dist/ui/spinner.d.ts +9 -0
  41. package/dist/ui/spinner.d.ts.map +1 -0
  42. package/dist/ui/spinner.js +46 -0
  43. package/dist/ui/spinner.js.map +1 -0
  44. package/package.json +2 -1
package/README.md CHANGED
@@ -1,156 +1,99 @@
1
1
  # forge
2
2
 
3
3
  [![tests](https://github.com/cristiancorreau/forge/actions/workflows/tests.yml/badge.svg)](https://github.com/cristiancorreau/forge/actions/workflows/tests.yml)
4
- [![version](https://img.shields.io/badge/version-0.5.0-blue)](CHANGELOG.md)
4
+ [![npm](https://img.shields.io/npm/v/@cristiancorreau/forge)](https://www.npmjs.com/package/@cristiancorreau/forge)
5
5
  [![license](https://img.shields.io/badge/license-Apache%202.0-green)](LICENSE)
6
6
 
7
- Framework de desarrollo agéntico para equipos de software. Un `project.yaml` genera la configuración correcta de agentes, skills y reglas para cualquier runtime de IA.
7
+ **Configura cualquier proyecto para trabajar con agentes IA en un comando.**
8
8
 
9
- > Los agentes sin harness derivan. Forge es el harness: reglas persistentes, memoria del proyecto, y delegación estructurada desde el primer commit.
9
+ Wizard interactivo que detecta tu stack, instala agentes especializados, genera guardrails y mantiene un manifest con SHA-256 para auditar cada cambio.
10
10
 
11
11
  ---
12
12
 
13
- ## Por qué Forge
14
-
15
- - **Los agentes olvidan.** Sin memoria y reglas persistentes, cada sesión empieza desde cero. Forge mantiene el contexto entre sesiones.
16
- - **El contexto se pierde entre archivos.** Un CLAUDE.md plano no sabe qué agente ejecuta qué tarea. Forge separa responsabilidades con agentes especializados por tier.
17
- - **Cada runtime tiene su formato.** Claude Code, OpenCode, Kiro y Codex CLI esperan archivos distintos. Forge los genera todos desde una sola fuente de verdad.
18
- - **La calidad baja con el tiempo.** Sin auditoría, los agentes se desactualizan silenciosamente. Forge detecta gaps y ofrece correcciones.
19
-
20
- ---
21
-
22
- ## Diferencias con otras herramientas
23
-
24
- | Herramienta | Qué hace | Alcance | Runtimes | Hooks | Equipos |
25
- |-------------|----------|---------|----------|-------|---------|
26
- | **Forge** | Framework completo: agentes, skills, reglas, auditoría | Proyecto + team | Claude Code, OpenCode, Kiro, Codex CLI | Sí (pre-commit) | Sí (tiers) |
27
- | `cc-sdd` | Plantillas SDD para Claude Code | Proyecto individual | Claude Code | No | No |
28
- | `Bridle` | Guardrails para prompts | Prompt-level | Agnóstico | No | No |
29
- | `wshobson/agents` | Colección de agent files | Proyecto individual | Claude Code | No | No |
30
- | CLAUDE.md manual | Instrucciones en texto plano | Sesión | Claude Code | No | No |
31
-
32
- **Lo que Forge NO es:** no es un modelo de IA, no es un servicio en la nube, no es una plataforma de deployment, no ejecuta agentes por sí solo. Es una capa de configuración y estructura que vive en tu repositorio.
33
-
34
- ---
35
-
36
- ## Quick start (5 minutos)
37
-
38
- **Requisitos:** Python 3.9+, git, Claude Code (u otro runtime soportado).
13
+ ## Quick start
39
14
 
40
15
  ```bash
41
- # 1. Agregar forge al proyecto como submodule
42
- git submodule add https://github.com/cristiancorreau/forge .agentic
43
- pip3 install -r .agentic/requirements.txt
16
+ npx @cristiancorreau/forge init
44
17
  ```
45
18
 
46
- ```bash
47
- # 2. Copiar y completar project.yaml
48
- cp .agentic/templates/project.yaml.tpl project.yaml
49
- ```
50
-
51
- Editar `project.yaml` con los datos del proyecto:
52
-
53
- ```yaml
54
- project:
55
- name: "Mi SaaS"
56
- mode: "standard" # startup | standard | enterprise
19
+ Sin instalación global. Sin Python. Solo Node.js.
57
20
 
58
- stack:
59
- backend: "hono"
60
- frontend: "nextjs"
21
+ ---
61
22
 
62
- agents:
63
- active: [orchestrator, test-engineer, docs-writer]
64
- profiles: [hono-drizzle, nextjs-admin]
23
+ ## Cómo funciona
65
24
 
66
- skills:
67
- active: [new-feature, security-audit, db-migrate]
68
- ```
25
+ El wizard detecta y configura el proyecto en cinco pasos:
69
26
 
70
- ```bash
71
- # 3. Inicializar agentes
72
- python3 .agentic/scripts/forge-init.py --tool claude-code
73
- ```
74
-
75
- ```bash
76
- # 4. Abrir Claude Code y ejecutar
77
- /session-start
78
- ```
79
-
80
- Después del paso 4 verás: agentes instalados en `.claude/agents/`, un `CLAUDE.md` generado con el roster del proyecto, y slash commands disponibles en Claude Code.
27
+ 1. **Detecta el stack** — lee `package.json`, lockfiles y `Dockerfile` para identificar framework, lenguaje y dependencias.
28
+ 2. **Selecciona agentes** — muestra un selector de flechas con los agentes disponibles para tu stack (TypeScript, Python, Ruby, Go, PHP).
29
+ 3. **Instala configuración** — escribe `.claude/agents/`, `CLAUDE.md`, `settings.json` y `architecture.rules` en el repositorio.
30
+ 4. **Instala hooks** — genera hooks de guardrail en JavaScript puro; sin dependencias de Python ni binarios externos.
31
+ 5. **Crea el manifest** — `forge/.forge/manifest.json` con SHA-256 de cada archivo gestionado para rastrear derivaciones futuras.
81
32
 
82
33
  ---
83
34
 
84
- ## Arquitectura — cinco capas
85
-
86
- | Capa | Qué hace |
87
- |------|----------|
88
- | **Memory** | `project.yaml` como fuente de verdad; wiki de proyecto persistente entre sesiones |
89
- | **Knowledge** | Agentes especializados (Tier 1/2/3) con scope declarado y reglas no-negociables |
90
- | **Guardrail** | Compliance by design, hook de pre-commit, auditoría con `forge-audit.py` |
91
- | **Delegation** | Orquestador que descompone tareas y delega a agentes especializados |
92
- | **Distribution** | Un solo `project.yaml` genera configs para todos los runtimes soportados |
35
+ ## Comandos
93
36
 
94
- Documentación completa: [`docs/guide.md`](docs/guide.md)
37
+ | Comando | Qué hace |
38
+ |---------|----------|
39
+ | `forge init` | Wizard completo: detecta stack, instala agentes, hooks y genera configuración |
40
+ | `forge audit` | Verifica el estado del proyecto contra el manifest; detecta archivos modificados o faltantes |
41
+ | `forge generate` | Regenera configuración desde el estado actual del proyecto sin ejecutar el wizard completo |
42
+ | `forge validate` | Valida que los archivos generados cumplan el esquema esperado |
43
+ | `forge doctor` | Health-check del entorno: Node.js, git, runtime de IA activo, permisos |
95
44
 
96
45
  ---
97
46
 
98
47
  ## Runtimes soportados
99
48
 
100
- | Runtime | Soporte | Cómo instalar |
101
- |---------|---------|---------------|
102
- | **Claude Code** | Completo (agentes, CLAUDE.md, settings, slash commands) | `--tool claude-code` |
103
- | **OpenCode** | Serial (AGENTS.md) | `--tool opencode` |
104
- | **Codex CLI** | Serial (AGENTS.md enriquecido) | `--tool codex` |
105
- | **Kiro** | Serial (steering files) | `--tool kiro` |
106
- | **Todos** | Genera los cuatro | `--tool all` |
107
-
108
- "Soporte completo" significa integración con hooks, settings.json y slash commands. "Serial" significa generación del archivo de instrucciones sin integración profunda con el runtime.
49
+ | Runtime | Soporte |
50
+ |---------|---------|
51
+ | **Claude Code** | Completo agentes, `CLAUDE.md`, `settings.json`, hooks |
52
+ | **OpenCode** | `AGENTS.md` generado |
53
+ | **Codex CLI** | `AGENTS.md` enriquecido para contexto de proyecto |
54
+ | **Kiro** | Steering files |
109
55
 
110
56
  ---
111
57
 
112
- ## Perfiles de stack disponibles
113
-
114
- 15 perfiles listos para usar, declarados en `agents.profiles` del `project.yaml`:
58
+ ## Stacks soportados
115
59
 
116
- `hono-drizzle` · `nextjs-admin` · `astro` · `expo` · `playwright-crawler`
117
- `fastapi` · `express` · `rails` · `nestjs` · `django`
118
- `vuenuxt` · `go-gin` · `sveltekit` · `laravel` · `wordpress`
60
+ | Lenguaje | Frameworks |
61
+ |----------|------------|
62
+ | TypeScript | Hono, Next.js, NestJS, Astro |
63
+ | Python | FastAPI, Django |
64
+ | Ruby | Rails |
65
+ | Go | Gin |
66
+ | PHP | Laravel |
119
67
 
120
- Cada profile instala uno o más agentes especializados en ese stack. Ver [`profiles/`](profiles/) para el detalle de cada uno.
121
-
122
- Para stacks no cubiertos:
123
-
124
- ```bash
125
- python3 .agentic/scripts/forge-scaffold-profile.py --name <stack> --engineer <agente>
126
- ```
68
+ Cada stack instala agentes especializados con reglas de arquitectura, convenciones de código y patrones específicos del framework.
127
69
 
128
70
  ---
129
71
 
130
- ## Contribuir
72
+ ## Sin Python requerido
131
73
 
132
- **Fork + PR.** Para cambios grandes, abre un issue primero.
74
+ Toda la CLI corre en Node.js. Los hooks de guardrail son JavaScript puro.
133
75
 
134
- **Agregar un profile:**
76
+ No hay `pip install`, no hay `requirements.txt`, no hay dependencias de sistema fuera de Node.js 18+.
135
77
 
136
- ```bash
137
- python3 .agentic/scripts/forge-scaffold-profile.py --name <stack> --engineer <agente>
138
- ```
78
+ ---
139
79
 
140
- El agente debe seguir el estándar en [`docs/agent-standard.md`](docs/agent-standard.md). Agregar el nombre al `CATALOG` en `scripts/aitmpl-search.py` y a los parametrize en `tests/test_profiles.py`.
80
+ ## Comparativa
141
81
 
142
- **Agregar un skill:** Crear `core/skills/<nombre>/SKILL.md` con la estructura estándar. Ver skills existentes como referencia.
82
+ | Herramienta | Agentes especializados | Hooks de guardrail | Manifest con SHA-256 | Multi-runtime |
83
+ |-------------|------------------------|-------------------|----------------------|---------------|
84
+ | **forge** | Sí | Sí | Sí | Claude Code, OpenCode, Codex, Kiro |
85
+ | `cc-sdd` | No — plantillas SDD | No | No | Claude Code |
86
+ | `autoskills` | No — skills genéricos | No | No | Claude Code |
143
87
 
144
- **Reportar fricción:** Abre un issue con el formato: _qué intentabas hacer → qué pasó → qué esperabas_. Los friction logs son bienvenidos como issues o PRs directamente en `docs/`.
88
+ ---
145
89
 
146
- **Tests antes de cada PR:**
90
+ ## Documentación
147
91
 
148
- ```bash
149
- python3 -m pytest tests/ -q # debe pasar al 100%
150
- ```
92
+ - [Guía completa](docs/guide.md)
93
+ - [Runtimes](docs/runtimes/)
151
94
 
152
95
  ---
153
96
 
154
97
  ## Licencia
155
98
 
156
- Apache 2.0 — [Cristian Correa](https://github.com/cristiancorreau), 2026.
99
+ Apache 2.0 — Copyright [Cristian Correa](https://github.com/cristiancorreau), 2026.
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * forge — PreToolUse hook: pre-bash-check.js
4
+ * Blocks destructive commands in production context. Zero Python dependency.
5
+ *
6
+ * Context: on 2026-04-28, --force-reset was accidentally executed against
7
+ * production DB, deleting 225 users and 35 forms. This hook prevents recurrence.
8
+ */
9
+ 'use strict';
10
+
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+
14
+ const DEBUG = !['', '0', 'false', 'False'].includes(process.env.DEBUG || '');
15
+ const dbg = msg => DEBUG && process.stdout.write(`[forge-hook-debug] ${msg}\n`);
16
+
17
+ // ---------------------------------------------------------------------------
18
+ // Load project.yaml (minimal YAML parser for flat key: value)
19
+ // ---------------------------------------------------------------------------
20
+ function loadProjectYaml() {
21
+ try {
22
+ let dir = process.cwd();
23
+ for (let i = 0; i < 6; i++) {
24
+ const candidate = path.join(dir, 'project.yaml');
25
+ if (fs.existsSync(candidate)) {
26
+ const text = fs.readFileSync(candidate, 'utf8');
27
+ return parseYamlMinimal(text);
28
+ }
29
+ const parent = path.dirname(dir);
30
+ if (parent === dir) break;
31
+ dir = parent;
32
+ }
33
+ } catch (e) { dbg(`project.yaml load error: ${e}`); }
34
+ return {};
35
+ }
36
+
37
+ function parseYamlMinimal(text) {
38
+ // Minimal parser: handles nested sections and key: value pairs
39
+ const result = {};
40
+ let currentSection = null;
41
+ let currentSubSection = null;
42
+ for (const rawLine of text.split('\n')) {
43
+ const line = rawLine.trimEnd();
44
+ if (!line || line.trim().startsWith('#')) continue;
45
+ const indent = line.length - line.trimStart().length;
46
+ const trimmed = line.trimStart();
47
+ const colonIdx = trimmed.indexOf(':');
48
+ if (colonIdx === -1) continue;
49
+ const key = trimmed.slice(0, colonIdx).trim();
50
+ const val = trimmed.slice(colonIdx + 1).trim();
51
+ if (indent === 0) { currentSection = key; currentSubSection = null; if (val) result[key] = val; else result[key] = {}; }
52
+ else if (indent === 2 && currentSection) { currentSubSection = key; if (!result[currentSection] || typeof result[currentSection] !== 'object') result[currentSection] = {}; if (val) result[currentSection][key] = val; else result[currentSection][key] = {}; }
53
+ else if (indent === 4 && currentSection && currentSubSection) { if (!result[currentSection][currentSubSection] || typeof result[currentSection][currentSubSection] !== 'object') result[currentSection][currentSubSection] = {}; if (val) result[currentSection][currentSubSection][key] = val; }
54
+ }
55
+ return result;
56
+ }
57
+
58
+ // ---------------------------------------------------------------------------
59
+ // Dangerous patterns
60
+ // ---------------------------------------------------------------------------
61
+ const DANGEROUS = [
62
+ [/--force-reset/, '--force-reset'],
63
+ [/prisma\s+migrate\s+reset/i, 'prisma migrate reset'],
64
+ [/DROP\s+TABLE/i, 'DROP TABLE'],
65
+ [/TRUNCATE\s+/i, 'TRUNCATE'],
66
+ [/DELETE\s+FROM\s+\w+\s*;/i, 'DELETE FROM sin WHERE'],
67
+ [/DROP\s+DATABASE/i, 'DROP DATABASE'],
68
+ [/dropdb\s+/, 'dropdb'],
69
+ [/rm\s+-rf\s+\//, 'rm -rf /'],
70
+ [/git\s+push\s+--force(?!\s+--with-lease)/, 'git push --force sin --with-lease'],
71
+ ];
72
+
73
+ function matchDangerous(command) {
74
+ for (const [re, label] of DANGEROUS) {
75
+ if (re.test(command)) return label;
76
+ }
77
+ return null;
78
+ }
79
+
80
+ function matchForbidden(command, project) {
81
+ try {
82
+ const forbidden = (project.rules || {}).forbidden_in_production;
83
+ if (!Array.isArray(forbidden)) return null;
84
+ for (const pattern of forbidden) {
85
+ if (new RegExp(pattern).test(command)) return pattern;
86
+ }
87
+ } catch (e) { dbg(`forbidden_in_production error: ${e}`); }
88
+ return null;
89
+ }
90
+
91
+ function isProductionContext(command, project) {
92
+ const deploy = project.deploy || {};
93
+ const prodUrl = deploy.production_url || '';
94
+ const projectId = deploy.project_id || '';
95
+ if (prodUrl && command.includes(prodUrl)) { dbg(`prod context: URL match`); return true; }
96
+ if (projectId && command.includes(projectId)) { dbg(`prod context: project_id match`); return true; }
97
+ for (const key of Object.keys(process.env)) {
98
+ if (/^(PROD_|PRODUCTION_|PROD$|PRODUCTION$)/i.test(key) && process.env[key]) { dbg(`prod context: env ${key}`); return true; }
99
+ }
100
+ return false;
101
+ }
102
+
103
+ // ---------------------------------------------------------------------------
104
+ // Main
105
+ // ---------------------------------------------------------------------------
106
+ let raw = '';
107
+ process.stdin.setEncoding('utf8');
108
+ process.stdin.on('data', chunk => { raw += chunk; });
109
+ process.stdin.on('end', () => {
110
+ if (!raw.trim()) { dbg('empty stdin'); process.exit(0); }
111
+ let data;
112
+ try { data = JSON.parse(raw); } catch (e) { dbg(`parse error: ${e}`); process.exit(0); }
113
+
114
+ const toolName = data.tool_name || '';
115
+ if (toolName !== 'Bash') process.exit(0);
116
+
117
+ const command = (data.tool_input || {}).command || '';
118
+ if (!command) process.exit(0);
119
+ dbg(`command: ${command.slice(0, 200)}`);
120
+
121
+ const project = loadProjectYaml();
122
+ const label = matchDangerous(command) || matchForbidden(command, project);
123
+ if (!label) process.exit(0);
124
+
125
+ const snippet = command.slice(0, 120) + (command.length > 120 ? '...' : '');
126
+ const inProd = isProductionContext(command, project);
127
+
128
+ if (inProd) {
129
+ process.stdout.write(
130
+ `forge: BLOQUEADO — comando destructivo detectado en contexto de producción.\n\n` +
131
+ ` Comando: ${snippet}\n Patrón: ${label}\n\n` +
132
+ ` Ejecutá esto MANUALMENTE con plena consciencia de que afecta producción.\n\n` +
133
+ ` Lección del 2026-04-28: --force-reset borró 225 usuarios en producción.\n`
134
+ );
135
+ process.exit(2);
136
+ } else {
137
+ process.stdout.write(
138
+ `forge: ADVERTENCIA — comando potencialmente destructivo.\n\n` +
139
+ ` Comando: ${snippet}\n Patrón: ${label}\n\n` +
140
+ ` Si apunta a producción, cancelá y ejecutá manualmente.\n`
141
+ );
142
+ process.exit(0);
143
+ }
144
+ });
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * forge — PreToolUse hook: pre-edit-check.js
4
+ * Branch guard, debug detection, hardcoded secret detection. Zero Python dependency.
5
+ */
6
+ 'use strict';
7
+
8
+ const { execSync } = require('child_process');
9
+ const path = require('path');
10
+
11
+ const DEBUG = !['', '0', 'false', 'False'].includes(process.env.DEBUG || '');
12
+ const dbg = msg => DEBUG && process.stdout.write(`[forge-hook-debug] ${msg}\n`);
13
+
14
+ // ---------------------------------------------------------------------------
15
+ // File classification
16
+ // ---------------------------------------------------------------------------
17
+ const CODE_EXTS = new Set(['.py','.ts','.js','.tsx','.jsx','.php','.rb','.go','.rs','.java','.cs','.cpp','.c','.sh']);
18
+ const NON_CODE_EXTS = new Set(['.md','.yaml','.yml','.json','.toml','.txt','.lock']);
19
+ const ROOT_PROTECTED = new Set(['README.md','CLAUDE.md','CHANGELOG.md','AGENTS.md']);
20
+ const PROTECTED_DIRS = ['docs/', '.claude/'];
21
+
22
+ function isCodeFile(filePath) {
23
+ const ext = path.extname(filePath).toLowerCase();
24
+ if (CODE_EXTS.has(ext)) return true;
25
+ if (NON_CODE_EXTS.has(ext)) return false;
26
+ return false;
27
+ }
28
+
29
+ function isExemptFromBranchGuard(filePath) {
30
+ const norm = filePath.replace(/\\/g, '/');
31
+ for (const d of PROTECTED_DIRS) {
32
+ if (norm.startsWith(d) || norm.includes(`/${d.replace(/\/$/, '')}`)) return true;
33
+ }
34
+ const base = path.basename(norm);
35
+ if (ROOT_PROTECTED.has(base)) return true;
36
+ return false;
37
+ }
38
+
39
+ // ---------------------------------------------------------------------------
40
+ // Branch guard
41
+ // ---------------------------------------------------------------------------
42
+ function getCurrentBranch() {
43
+ try {
44
+ return execSync('git branch --show-current', { encoding: 'utf8', timeout: 3000 }).trim();
45
+ } catch { return ''; }
46
+ }
47
+
48
+ // ---------------------------------------------------------------------------
49
+ // Debug detection patterns per language
50
+ // ---------------------------------------------------------------------------
51
+ const DEBUG_PATTERNS = [
52
+ { re: /\bconsole\.(log|debug|warn|error|trace)\s*\(/, lang: 'TypeScript/JavaScript' },
53
+ { re: /\bprint\s*\(/, lang: 'Python' },
54
+ { re: /\bdd\s*\(/, lang: 'PHP (dd)' },
55
+ { re: /\bvar_dump\s*\(/, lang: 'PHP (var_dump)' },
56
+ { re: /\bdump\s*\(/, lang: 'PHP (dump)' },
57
+ { re: /\bdebugger\b/, lang: 'JavaScript debugger' },
58
+ { re: /\bbinding\.pry\b/, lang: 'Ruby (binding.pry)' },
59
+ { re: /\bbyebug\b/, lang: 'Ruby (byebug)' },
60
+ { re: /\bp\s+\w+/, lang: 'Ruby (p)' },
61
+ ];
62
+
63
+ function detectDebugStatements(content) {
64
+ const found = [];
65
+ const lines = content.split('\n');
66
+ lines.forEach((line, idx) => {
67
+ for (const { re, lang } of DEBUG_PATTERNS) {
68
+ if (re.test(line)) {
69
+ found.push({ line: idx + 1, snippet: line.trim().slice(0, 80), lang });
70
+ break;
71
+ }
72
+ }
73
+ });
74
+ return found;
75
+ }
76
+
77
+ // ---------------------------------------------------------------------------
78
+ // Secret detection
79
+ // ---------------------------------------------------------------------------
80
+ const SECRET_PATTERNS = [
81
+ { re: /(?:password|passwd|pwd)\s*=\s*['"][^'"]{4,}['"]/i, label: 'password hardcodeado' },
82
+ { re: /(?:api_?key|apikey)\s*=\s*['"][^'"]{8,}['"]/i, label: 'API key hardcodeada' },
83
+ { re: /(?:secret|token)\s*=\s*['"][^'"]{8,}['"]/i, label: 'secret/token hardcodeado' },
84
+ { re: /sk-[a-zA-Z0-9]{20,}/, label: 'OpenAI API key' },
85
+ { re: /ghp_[a-zA-Z0-9]{30,}/, label: 'GitHub Personal Access Token' },
86
+ { re: /eyJ[a-zA-Z0-9_-]{20,}\.[a-zA-Z0-9_-]{20,}/, label: 'JWT token' },
87
+ ];
88
+
89
+ function detectSecrets(content) {
90
+ const found = [];
91
+ const lines = content.split('\n');
92
+ lines.forEach((line, idx) => {
93
+ for (const { re, label } of SECRET_PATTERNS) {
94
+ if (re.test(line)) {
95
+ found.push({ line: idx + 1, label, snippet: line.trim().slice(0, 60) + '...' });
96
+ break;
97
+ }
98
+ }
99
+ });
100
+ return found;
101
+ }
102
+
103
+ // ---------------------------------------------------------------------------
104
+ // Main
105
+ // ---------------------------------------------------------------------------
106
+ let raw = '';
107
+ process.stdin.setEncoding('utf8');
108
+ process.stdin.on('data', chunk => { raw += chunk; });
109
+ process.stdin.on('end', () => {
110
+ if (!raw.trim()) { process.exit(0); }
111
+ let data;
112
+ try { data = JSON.parse(raw); } catch { process.exit(0); }
113
+
114
+ const toolName = data.tool_name || '';
115
+ if (!['Write', 'Edit', 'MultiEdit'].includes(toolName)) process.exit(0);
116
+
117
+ const toolInput = data.tool_input || {};
118
+ const filePath = toolInput.file_path || toolInput.path || '';
119
+ if (!filePath) process.exit(0);
120
+
121
+ dbg(`file: ${filePath}`);
122
+
123
+ const warnings = [];
124
+
125
+ // 1. Branch guard
126
+ if (!isExemptFromBranchGuard(filePath) && isCodeFile(filePath)) {
127
+ const branch = getCurrentBranch();
128
+ dbg(`branch: ${branch}`);
129
+ if (branch === 'main' || branch === 'master') {
130
+ process.stdout.write(
131
+ `forge: BLOQUEADO — editando código directamente en ${branch}.\n\n` +
132
+ ` Archivo: ${filePath}\n\n` +
133
+ ` Creá una rama antes de editar código:\n` +
134
+ ` git checkout -b feat/descripcion\n\n` +
135
+ ` Ramas de documentación (.md, .yaml, .json) están permitidas en ${branch}.\n`
136
+ );
137
+ process.exit(2);
138
+ }
139
+ }
140
+
141
+ // 2. Debug and secret detection on new content
142
+ const newContent = toolInput.new_string || toolInput.content || '';
143
+ if (newContent && isCodeFile(filePath)) {
144
+ const debugHits = detectDebugStatements(newContent);
145
+ const secretHits = detectSecrets(newContent);
146
+
147
+ if (debugHits.length > 0) {
148
+ const items = debugHits.map(h => ` línea ${h.line}: ${h.snippet} (${h.lang})`).join('\n');
149
+ warnings.push(`Debug statements detectados:\n${items}`);
150
+ }
151
+ if (secretHits.length > 0) {
152
+ const items = secretHits.map(h => ` línea ${h.line}: ${h.label} — ${h.snippet}`).join('\n');
153
+ warnings.push(`Posibles secrets hardcodeados:\n${items}\n Usar variables de entorno en su lugar.`);
154
+ }
155
+ }
156
+
157
+ if (warnings.length > 0) {
158
+ process.stdout.write(
159
+ `forge: ADVERTENCIA — revisá antes de continuar:\n\n` +
160
+ warnings.map(w => ` • ${w}`).join('\n\n') + '\n'
161
+ );
162
+ // Don't block — just warn
163
+ }
164
+
165
+ process.exit(0);
166
+ });
package/dist/cli.js CHANGED
@@ -4,7 +4,7 @@ import { audit } from './commands/audit.js';
4
4
  import { generate } from './commands/generate.js';
5
5
  import { validate } from './commands/validate.js';
6
6
  import { doctor } from './commands/doctor.js';
7
- const VERSION = '2.2.0';
7
+ const VERSION = '2.4.1';
8
8
  const HELP = `forge v${VERSION} — Agentic development framework
9
9
 
10
10
  Usage: forge <command> [options]
@@ -1 +1 @@
1
- {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/commands/audit.ts"],"names":[],"mappings":"AAgEA,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAuH3D"}
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/commands/audit.ts"],"names":[],"mappings":"AAmEA,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAyI3D"}
@@ -1,6 +1,9 @@
1
1
  import { existsSync, readFileSync, readdirSync } from 'fs';
2
2
  import { join } from 'path';
3
3
  import { findProjectYaml, loadProjectYaml } from '../lib/yaml.js';
4
+ import { bold, dim, green, red, yellow, cyan, gray, icons } from '../ui/colors.js';
5
+ import { box } from '../ui/box.js';
6
+ import { loadManifest, checkOutdated } from '../lib/lock.js';
4
7
  const HELP = `Usage: forge audit [options]
5
8
 
6
9
  Audit a project against the forge standard. Checks installed agents,
@@ -140,6 +143,20 @@ export async function audit(args) {
140
143
  if (!hasClaudeDir && !hasAgentsMd && !hasKiro) {
141
144
  issues.push({ level: 'warn', check: 'runtime', message: 'No se detectó ningún runtime — ejecutar forge init' });
142
145
  }
146
+ // Manifest check
147
+ const manifest = loadManifest(root);
148
+ if (manifest) {
149
+ const outdated = checkOutdated(root, manifest);
150
+ if (outdated.length === 0) {
151
+ issues.push({ level: 'ok', check: 'manifest', message: `forge v${manifest.forgeVersion} — todos los archivos al día` });
152
+ }
153
+ else {
154
+ issues.push({ level: 'warn', check: 'manifest', message: `${outdated.length} archivo(s) modificados desde forge init` });
155
+ }
156
+ }
157
+ else {
158
+ issues.push({ level: 'info', check: 'manifest', message: 'Sin .forge/manifest.json — ejecutar forge init para generarlo' });
159
+ }
143
160
  // Summary
144
161
  const errors = issues.filter(i => i.level === 'error').length;
145
162
  const warnings = issues.filter(i => i.level === 'warn').length;
@@ -151,15 +168,18 @@ export async function audit(args) {
151
168
  }, null, 2));
152
169
  }
153
170
  else {
154
- console.log('forge audit\n');
171
+ console.log(cyan(bold('forge audit')) + '\n');
155
172
  for (const issue of issues) {
156
- const icons = { ok: '', warn: '!', error: '✗', info: 'i' };
157
- const icon = icons[issue.level] ?? '·';
158
- console.log(` [${icon}] ${issue.check.padEnd(20)} ${issue.message}`);
173
+ const levelIcon = icons[issue.level] ?? gray('·');
174
+ console.log(` [${levelIcon}] ${bold(issue.check.padEnd(20))} ${dim(issue.message)}`);
159
175
  }
160
- console.log(`\n Resumen: ${ok} OK · ${warnings} warnings · ${errors} errores`);
161
- if (errors === 0 && warnings === 0)
162
- console.log(' El proyecto cumple con el estándar forge.');
176
+ const summaryLine = `Resumen: ${green(String(ok) + ' OK')} · ${yellow(String(warnings) + ' warn')} · ${red(String(errors) + ' ✗')}`;
177
+ const boxTitle = errors === 0 && warnings === 0
178
+ ? green('Todo en orden')
179
+ : errors > 0
180
+ ? red('Se encontraron errores')
181
+ : yellow('Advertencias encontradas');
182
+ console.log('\n' + box(boxTitle, [summaryLine]));
163
183
  }
164
184
  return errors > 0 ? 1 : 0;
165
185
  }
@@ -1 +1 @@
1
- {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/commands/audit.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/commands/audit.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAKA,wBAAsB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA8D7D"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAOA,wBAAsB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAqG7D"}