pigmalion-setup 0.1.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.
package/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # pigmalion-setup
2
+
3
+ Utilidad NPX para inicializar un proyecto copiando `AGENTS.md`, `CODEX.md` y `SETUP.md`, y arrancar Codex usando `SETUP.md` como base del flujo.
4
+
5
+ ## Uso
6
+
7
+ ```bash
8
+ npx pigmalion-setup
9
+ ```
10
+
11
+ Requiere que el comando `codex` este disponible en `PATH`.
12
+
13
+ ## Comportamiento
14
+
15
+ - Copia `AGENTS.md`, `CODEX.md`, `SETUP.md` en el directorio actual si no existen.
16
+ - Ejecuta `codex` y le pasa el contenido de `SETUP.md` para iniciar la conversación.
17
+ - Codex define documentación base y `ROADMAP.md` según el flujo de `SETUP.md`.
18
+
19
+
20
+ # Desarrollo local
21
+
22
+ Para probar la herramienta localmente sin publicarla, puedes usar `npm link`:
23
+
24
+ ```
25
+ npm link
26
+ ```
27
+
28
+ Esto hará que el comando `pigmalion-setup` esté disponible globalmente en tu sistema, apuntando a tu versión local del proyecto. Luego puedes ejecutar `npx pigmalion-setup` para probarlo.
29
+
30
+
package/bin/cli.js ADDED
@@ -0,0 +1,430 @@
1
+ #!/usr/bin/env node
2
+ import fs from "node:fs";
3
+ import fsPromises from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { spawn, spawnSync } from "node:child_process";
7
+ import readline from "node:readline/promises";
8
+
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = path.dirname(__filename);
11
+
12
+ const TEMPLATE_DIR = path.join(__dirname, "..", "templates");
13
+ const TARGET_DIR = process.cwd();
14
+
15
+ const INITIAL_FILES = ["SETUP.md"];
16
+ const POST_FILES = ["AGENTS.md", "CODEX.md"];
17
+
18
+ function log(msg) {
19
+ process.stdout.write(`${msg}\n`);
20
+ }
21
+
22
+ function normalizePath(p) {
23
+ if (process.platform !== "win32") return p;
24
+ if (!p) return p;
25
+ const msysMatch = p.match(/^\/([a-zA-Z])\/(.*)/);
26
+ if (msysMatch) {
27
+ const drive = msysMatch[1].toUpperCase();
28
+ const rest = msysMatch[2].replace(/\//g, "\\");
29
+ return `${drive}:\\${rest}`;
30
+ }
31
+ return p;
32
+ }
33
+
34
+ function detectShell() {
35
+ const env = process.env;
36
+ const shell = (env.SHELL || "").toLowerCase();
37
+ if (shell.includes("bash")) return "bash";
38
+ const psModulePath = (env.PSModulePath || "").toLowerCase();
39
+ if (psModulePath.includes("powershell") || env.PSExecutionPolicyPreference) {
40
+ return "powershell";
41
+ }
42
+ const comspec = (env.COMSPEC || "").toLowerCase();
43
+ if (comspec.includes("cmd.exe")) return "cmd";
44
+ return "unknown";
45
+ }
46
+
47
+ function ensureWindowsExecutable(codexCmd) {
48
+ if (process.platform !== "win32") return codexCmd;
49
+ if (!codexCmd) return codexCmd;
50
+ const ext = path.extname(codexCmd);
51
+ if (ext) return codexCmd;
52
+ const candidates = [
53
+ `${codexCmd}.cmd`,
54
+ `${codexCmd}.ps1`,
55
+ `${codexCmd}.exe`,
56
+ codexCmd
57
+ ];
58
+ for (const candidate of candidates) {
59
+ if (fs.existsSync(candidate)) return candidate;
60
+ }
61
+ return codexCmd;
62
+ }
63
+
64
+ function canRunCodex(codexCmd) {
65
+ if (!codexCmd) return false;
66
+ const ext = path.extname(codexCmd).toLowerCase();
67
+ const useShell =
68
+ process.platform === "win32" && (!ext || ext === ".cmd" || ext === ".ps1");
69
+ const result = spawnSync(codexCmd, ["--version"], {
70
+ stdio: "ignore",
71
+ env: process.env,
72
+ shell: useShell
73
+ });
74
+ if (result.error && result.error.code === "ENOENT") return false;
75
+ if (result.error) return false;
76
+ return true;
77
+ }
78
+
79
+ async function fileExists(p) {
80
+ try {
81
+ await fsPromises.access(p);
82
+ return true;
83
+ } catch {
84
+ return false;
85
+ }
86
+ }
87
+
88
+ async function confirmOverwrite(name) {
89
+ if (!process.stdin.isTTY) {
90
+ return true; // Asumir sí en modo no interactivo
91
+ }
92
+ const rl = readline.createInterface({
93
+ input: process.stdin,
94
+ output: process.stdout
95
+ });
96
+ try {
97
+ const answer = await rl.question(
98
+ `- ${name} ya existe. ¿Sobrescribir? (s/N): `
99
+ );
100
+ const normalized = answer.trim().toLowerCase();
101
+ return normalized === "s" || normalized === "si" || normalized === "y";
102
+ } finally {
103
+ rl.close();
104
+ }
105
+ }
106
+
107
+ async function waitForEnter() {
108
+ if (!process.stdin.isTTY) {
109
+ log("Modo no interactivo detectado. Continuando...");
110
+ return;
111
+ }
112
+ const rl = readline.createInterface({
113
+ input: process.stdin,
114
+ output: process.stdout
115
+ });
116
+ try {
117
+ await rl.question("Presiona Enter para continuar...");
118
+ } finally {
119
+ rl.close();
120
+ }
121
+ }
122
+
123
+ async function copyTemplates(files, { allowOverwrite } = { allowOverwrite: false }) {
124
+ for (const name of files) {
125
+ const src = path.join(TEMPLATE_DIR, name);
126
+ const dest = path.join(TARGET_DIR, name);
127
+ if (await fileExists(dest)) {
128
+ if (!allowOverwrite) {
129
+ log(`- ${name} ya existe, se omite`);
130
+ continue;
131
+ }
132
+ const shouldOverwrite = await confirmOverwrite(name);
133
+ if (!shouldOverwrite) {
134
+ log(`- ${name} ya existe, se omite`);
135
+ continue;
136
+ }
137
+ }
138
+ await fsPromises.copyFile(src, dest);
139
+ log(`- ${name} instalado`);
140
+ }
141
+ }
142
+
143
+ function resolveCodexJsFromCmd(codexCmd) {
144
+ if (!codexCmd.toLowerCase().endsWith(".cmd")) return null;
145
+ const binDir = path.dirname(codexCmd);
146
+ const candidate = path.join(
147
+ binDir,
148
+ "node_modules",
149
+ "@openai",
150
+ "codex",
151
+ "bin",
152
+ "codex.js",
153
+ );
154
+ if (fs.existsSync(candidate)) return candidate;
155
+ return null;
156
+ }
157
+
158
+ function buildCodexProcess(codexCmd, prompt) {
159
+ const codexJs = resolveCodexJsFromCmd(codexCmd);
160
+ if (codexJs) {
161
+ return {
162
+ cmd: process.execPath,
163
+ args: [codexJs],
164
+ options: { shell: false },
165
+ };
166
+ }
167
+ const ext = path.extname(codexCmd).toLowerCase();
168
+ const useShell =
169
+ process.platform === "win32" && (ext === ".cmd" || ext === ".ps1");
170
+ return { cmd: codexCmd, args: [], options: { shell: useShell } };
171
+ }
172
+
173
+ async function runCodex(codexCmd) {
174
+ const setupPath = path.join(TARGET_DIR, "SETUP.md");
175
+
176
+ log("");
177
+ log("Setup detectado. Para continuar con Codex:");
178
+ log(`Ejecuta: ${codexCmd}`);
179
+ log("");
180
+ log("Y pega el siguiente prompt:");
181
+ log("");
182
+ const prompt = [
183
+ `Lee y sigue estrictamente SETUP.md en: ${setupPath}`,
184
+ "Inicia el flujo base con el usuario para definir vision general, documentacion y ROADMAP.",
185
+ "No toques codigo todavia. Solo documentacion, roadmap y arquitectura.",
186
+ "Comienza ahora."
187
+ ].join("\n");
188
+ log(prompt);
189
+ log("");
190
+ }
191
+
192
+ function findCodexInBinDir(binDir) {
193
+ if (!binDir) return null;
194
+ const normalized = normalizePath(binDir);
195
+ const candidates = [
196
+ path.join(normalized, "codex"),
197
+ path.join(normalized, "codex.cmd"),
198
+ path.join(normalized, "codex.ps1"),
199
+ path.join(normalized, "codex.exe")
200
+ ];
201
+ for (const candidate of candidates) {
202
+ try {
203
+ fs.accessSync(candidate);
204
+ return candidate;
205
+ } catch {
206
+ // continue
207
+ }
208
+ }
209
+ return null;
210
+ }
211
+
212
+ function findCodexFromNpmGlobal() {
213
+ const npmPrefix = spawnSync("npm", ["prefix", "-g"], {
214
+ encoding: "utf8",
215
+ stdio: ["ignore", "pipe", "ignore"],
216
+ env: process.env
217
+ });
218
+ if (npmPrefix.status !== 0 || !npmPrefix.stdout) {
219
+ return null;
220
+ }
221
+ const prefix = npmPrefix.stdout.trim();
222
+ const direct = findCodexInBinDir(prefix);
223
+ if (direct) return direct;
224
+ return findCodexInBinDir(path.join(prefix, "bin"));
225
+ }
226
+
227
+ function findCodexFromNpmPrefix() {
228
+ const npmPrefix = spawnSync("npm", ["prefix", "-g"], {
229
+ encoding: "utf8",
230
+ stdio: ["ignore", "pipe", "ignore"],
231
+ env: process.env
232
+ });
233
+ if (npmPrefix.status === 0 && npmPrefix.stdout) {
234
+ const prefix = npmPrefix.stdout.trim();
235
+ const found = findCodexInBinDir(prefix);
236
+ if (found) return found;
237
+ const foundBin = findCodexInBinDir(path.join(prefix, "bin"));
238
+ if (foundBin) return foundBin;
239
+ }
240
+
241
+ const npmConfigPrefix = spawnSync("npm", ["config", "get", "prefix"], {
242
+ encoding: "utf8",
243
+ stdio: ["ignore", "pipe", "ignore"],
244
+ env: process.env
245
+ });
246
+ if (npmConfigPrefix.status === 0 && npmConfigPrefix.stdout) {
247
+ const prefix = npmConfigPrefix.stdout.trim();
248
+ const found = findCodexInBinDir(prefix);
249
+ if (found) return found;
250
+ const foundBin = findCodexInBinDir(path.join(prefix, "bin"));
251
+ if (foundBin) return foundBin;
252
+ }
253
+
254
+ return null;
255
+ }
256
+
257
+ function findCodexFromLocalNodeModules() {
258
+ const localBin = path.join(TARGET_DIR, "node_modules", ".bin");
259
+ return findCodexInBinDir(localBin);
260
+ }
261
+
262
+ function findCodexFromWhere() {
263
+ const whereResult = spawnSync("where", ["codex"], {
264
+ encoding: "utf8",
265
+ stdio: ["ignore", "pipe", "ignore"],
266
+ env: process.env
267
+ });
268
+ if (whereResult.status !== 0 || !whereResult.stdout) {
269
+ return null;
270
+ }
271
+ const lines = whereResult.stdout
272
+ .split(/\r?\n/)
273
+ .map((l) => l.trim())
274
+ .filter(Boolean);
275
+ if (lines.length === 0) return null;
276
+ return lines[0];
277
+ }
278
+
279
+ function findCodexFromWhich() {
280
+ const whichResult = spawnSync("which", ["codex"], {
281
+ encoding: "utf8",
282
+ stdio: ["ignore", "pipe", "ignore"],
283
+ env: process.env
284
+ });
285
+ if (whichResult.status !== 0 || !whichResult.stdout) {
286
+ return null;
287
+ }
288
+ const lines = whichResult.stdout
289
+ .split(/\r?\n/)
290
+ .map((l) => l.trim())
291
+ .filter(Boolean);
292
+ if (lines.length === 0) return null;
293
+ const first = normalizePath(lines[0]);
294
+ const hasExt = path.extname(first).length > 0;
295
+ if (hasExt && fs.existsSync(first)) return first;
296
+ const candidates = [
297
+ `${first}.cmd`,
298
+ `${first}.ps1`,
299
+ `${first}.exe`,
300
+ first
301
+ ];
302
+ for (const candidate of candidates) {
303
+ if (fs.existsSync(candidate)) return candidate;
304
+ }
305
+ return null;
306
+ }
307
+
308
+ function findCodexFromShell() {
309
+ const shell = detectShell();
310
+ if (shell === "bash") return findCodexFromWhich();
311
+ if (shell === "powershell" || shell === "cmd") return findCodexFromWhere();
312
+ return null;
313
+ }
314
+
315
+ function findCodexFromPnpmGlobal() {
316
+ const pnpmBin = spawnSync("pnpm", ["bin", "-g"], {
317
+ encoding: "utf8",
318
+ stdio: ["ignore", "pipe", "ignore"],
319
+ env: process.env
320
+ });
321
+ if (pnpmBin.status !== 0 || !pnpmBin.stdout) {
322
+ return null;
323
+ }
324
+ return findCodexInBinDir(pnpmBin.stdout.trim());
325
+ }
326
+
327
+ function findCodexFromYarnGlobal() {
328
+ const yarnBin = spawnSync("yarn", ["global", "bin"], {
329
+ encoding: "utf8",
330
+ stdio: ["ignore", "pipe", "ignore"],
331
+ env: process.env
332
+ });
333
+ if (yarnBin.status !== 0 || !yarnBin.stdout) {
334
+ return null;
335
+ }
336
+ return findCodexInBinDir(yarnBin.stdout.trim());
337
+ }
338
+
339
+ function findCodexFromKnownPaths() {
340
+ const bins = [];
341
+ if (process.env.npm_config_prefix) {
342
+ bins.push(process.env.npm_config_prefix);
343
+ bins.push(path.join(process.env.npm_config_prefix, "bin"));
344
+ }
345
+ if (process.env.npm_prefix) {
346
+ bins.push(process.env.npm_prefix);
347
+ bins.push(path.join(process.env.npm_prefix, "bin"));
348
+ }
349
+ if (process.env.npm_config_global_prefix) {
350
+ bins.push(process.env.npm_config_global_prefix);
351
+ bins.push(path.join(process.env.npm_config_global_prefix, "bin"));
352
+ }
353
+ if (process.env.APPDATA) {
354
+ bins.push(path.join(process.env.APPDATA, "npm"));
355
+ bins.push(path.join(process.env.APPDATA, "Yarn", "bin"));
356
+ }
357
+ if (process.env.LOCALAPPDATA) {
358
+ bins.push(path.join(process.env.LOCALAPPDATA, "Yarn", "bin"));
359
+ bins.push(path.join(process.env.LOCALAPPDATA, "npm"));
360
+ }
361
+ if (process.env.PNPM_HOME) {
362
+ bins.push(process.env.PNPM_HOME);
363
+ }
364
+ if (process.env.YARN_GLOBAL_FOLDER) {
365
+ bins.push(process.env.YARN_GLOBAL_FOLDER);
366
+ bins.push(path.join(process.env.YARN_GLOBAL_FOLDER, "bin"));
367
+ }
368
+
369
+ for (const binDir of bins) {
370
+ const found = findCodexInBinDir(binDir);
371
+ if (found) return found;
372
+ }
373
+ return null;
374
+ }
375
+
376
+ function checkCodexAvailable() {
377
+ const candidates = [
378
+ findCodexFromShell(),
379
+ findCodexFromLocalNodeModules(),
380
+ findCodexFromNpmGlobal(),
381
+ findCodexFromNpmPrefix(),
382
+ findCodexFromPnpmGlobal(),
383
+ findCodexFromYarnGlobal(),
384
+ findCodexFromWhere(),
385
+ findCodexFromWhich(),
386
+ findCodexFromKnownPaths()
387
+ ];
388
+ for (const candidate of candidates) {
389
+ const resolved = ensureWindowsExecutable(candidate);
390
+ if (canRunCodex(resolved)) return resolved;
391
+ }
392
+
393
+ const result = spawnSync("codex", ["--version"], {
394
+ stdio: "ignore",
395
+ env: process.env,
396
+ shell: process.platform === "win32"
397
+ });
398
+ if (!result.error && result.status === 0) {
399
+ return "codex";
400
+ }
401
+ if (result.error && result.error.code !== "ENOENT") {
402
+ return null;
403
+ }
404
+
405
+ log("");
406
+ log("No se encontro el comando 'codex' en PATH ni en npm/pnpm/yarn global.");
407
+ log("Instalacion recomendada:");
408
+ log("- Instala el CLI de Codex con el metodo oficial segun tu entorno.");
409
+ log("- Verifica que el comando `codex` quede disponible en PATH.");
410
+ log("- Luego vuelve a ejecutar `npx pigmalion-setup`.");
411
+ return null;
412
+ }
413
+
414
+ async function main() {
415
+ log("Pigmalion Setup- Init");
416
+ await copyTemplates(INITIAL_FILES);
417
+ const codexCmd = checkCodexAvailable();
418
+ if (!codexCmd) {
419
+ return;
420
+ }
421
+ await runCodex(codexCmd);
422
+ await copyTemplates(POST_FILES, { allowOverwrite: true });
423
+ log("");
424
+ log("Listo. Puedes revisar SETUP.md y los docs generados por Codex.");
425
+ }
426
+
427
+ main().catch((err) => {
428
+ console.error(err);
429
+ process.exit(1);
430
+ });
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "pigmalion-setup",
3
+ "version": "0.1.0",
4
+ "description": "NPX utility to initialize projects with Pigmalion Manager setup flow.",
5
+ "type": "module",
6
+ "bin": {
7
+ "pigmalion-setup": "bin/cli.js"
8
+ },
9
+ "engines": {
10
+ "node": ">=18"
11
+ },
12
+ "files": [
13
+ "bin",
14
+ "templates"
15
+ ],
16
+ "license": "MIT"
17
+ }
@@ -0,0 +1,299 @@
1
+ # 🤖 AGENTS.md - Workflow Automatizado IA
2
+
3
+ ## 🎯 PRINCIPIO FUNDAMENTAL
4
+ **Actúa primero, pregunta después solo si es crítico**
5
+ Objetivo: Maximizar velocidad sin sacrificar calidad
6
+
7
+ ---
8
+
9
+ ## 🚀 AUTONOMÍA MÁXIMA
10
+
11
+ ### Reglas de Decisión
12
+ ```
13
+ SI duda <5s → Implementa mejor práctica estándar
14
+ SI impacto >1h trabajo → 1 pregunta concreta máximo
15
+ SI breaking change → Avisa + propón migración
16
+ ```
17
+
18
+ ### Comunicación Prohibida
19
+ ❌ "¿Quieres que...?"
20
+ ❌ "¿Prefieres A o B?"
21
+ ❌ "¿Dónde pongo...?"
22
+
23
+ ### Comunicación Correcta
24
+ ✅ "Implementado X. Tests 92%. Review: /diff"
25
+ ✅ "Breaking: API v2. Migración: /docs/MIGRATION.md"
26
+ ✅ "Hotfix deployed. Rollback: `git revert abc123`"
27
+
28
+ ---
29
+
30
+ ## ESTRUCTURA
31
+ (Según proyecto)
32
+ backend/ (3001) | frontend/ (3002) | .github/
33
+
34
+
35
+ # 🧠 STACK INTELIGENTE (AUTO-SELECCIÓN)
36
+
37
+ ## HEURÍSTICAS DECISIÓN STACK (Evalúa + elige mejor)
38
+
39
+ PROYECTO GRANDE (>10 modelos/usuarios/cruzado): Laravel 11 + Inertia + Vue 3 + MySQL (puerto 3000)
40
+ SIMPLE (<1 semana/MVP): Node Express + React Vite (3001/3002)
41
+ REALTIME (chat/socket): Node Socket.io + React (3001/3002)
42
+ ML/DATA (análisis): Python + FastAPI + Streamlit (8000/3002)
43
+ MÓVIL/PWA: Laravel API + React Native
44
+
45
+ ---
46
+
47
+ ## 📁 EJEMPLO DE ESTRUCTURA PROYECTO
48
+
49
+ Por defecto, se sigue una estructura modular por capas o pipelines, evitando mezclar responsabilidades.
50
+
51
+ ```
52
+ proyecto/
53
+ ├── backend/ # API + lógica negocio
54
+ ├── frontend/ # UI + cliente
55
+ ├── shared/ # types, utils, schemas compartidos
56
+ ├── tests/ # tests unitarios e integración
57
+ ├── docs/ # Documentación técnica
58
+ │ ├── API.md
59
+ │ ├── ARCHITECTURE.md
60
+ │ └── DECISIONS.md # ADRs importantes
61
+ ├── .github/
62
+ │ ├── workflows/ # CI/CD
63
+ ├── docker-compose.yml
64
+ ├── AGENTS.md # ← ESTE archivo
65
+ ├── ROADMAP.md # Plan de trabajo
66
+ ├── README.md # Documentación general
67
+ └── package.json # Scripts raíz
68
+ ```
69
+
70
+ ### Scripts NPM Raíz (Requeridos)
71
+ ```json
72
+ {
73
+ "scripts": {
74
+ "dev": "concurrently 'npm:dev:*'",
75
+ "dev:backend": "cd backend && npm run dev",
76
+ "dev:frontend": "cd frontend && npm run dev",
77
+ "install:all": "npm i && cd backend && npm i && cd ../frontend && npm i",
78
+ "lint": "prettier --check . && eslint .",
79
+ "format": "prettier --write .",
80
+ "test": "npm run test --workspaces",
81
+ "test:ci": "npm run test:ci --workspaces",
82
+ "build": "npm run build --workspaces"
83
+ }
84
+ }
85
+ ```
86
+
87
+ ---
88
+
89
+ ## 🔄 WORKFLOW GIT
90
+
91
+ ### Branching Strategy
92
+ ```bash
93
+ # Nomenclatura obligatoria
94
+ codex-{tipo}-{descripción-corta}-{timestamp}
95
+
96
+ # Ejemplos
97
+ codex-feat-auth-api-20260215-1430
98
+ codex-fix-login-bug-20260215-1445
99
+ codex-docs-api-spec-20260215-1500
100
+ ```
101
+
102
+ ### Tipos Válidos
103
+ - `feat`: Nueva funcionalidad
104
+ - `fix`: Corrección bug
105
+ - `refactor`: Refactorización sin cambio comportamiento
106
+ - `docs`: Solo documentación
107
+ - `test`: Añadir/mejorar tests
108
+ - `chore`: Tareas mantenimiento (deps, config)
109
+
110
+ ### Flujo Automático
111
+
112
+ ```bash
113
+ 1. /diff # Muestra cambios + impacto
114
+ 2. /test # Ejecuta tests + coverage
115
+ 3. /merge # Merge si tests >85% + CI pass
116
+ ```
117
+
118
+ ### Commits
119
+ ```bash
120
+ # Formato: tipo(scope): descripción
121
+ feat(auth): add JWT refresh token endpoint
122
+ fix(ui): resolve mobile menu overflow
123
+ docs(api): update rate limit documentation
124
+ ```
125
+
126
+ ---
127
+
128
+ # 🔄 ISSUE WORKFLOW (GitHub Issues nativo - OBLIGATORIO)
129
+
130
+ ## PROCESO AUTOMÁTICO
131
+
132
+ GitHub Issues → Label: 🔴 bug 🤖 codex | 🟢 feature 🤖 codex
133
+ codex /issues → Lista disponibles kanban
134
+ codex /next-bug → codex-bug-#12 (auto-branch)
135
+ Implementa → /test → coverage >85% → /pr → /close #12
136
+
137
+
138
+ ## COMANDOS AGENTES
139
+ codex /issues # Lista + kanban status
140
+ codex /next-bug # Toma siguiente 🔴 bug
141
+ codex /next-feature # Toma siguiente 🟢 feature
142
+ codex /assign #15 # Asigna agent a issue
143
+ codex /close #12 # Merge + close auto
144
+ codex /kanban # Status visual ToDo/InProgress/Done
145
+
146
+ ## BRANCH CONVENCIÓN
147
+ 🔴 bug → codex-bug-#12-login-crash
148
+ 🟢 feature → codex-feature-#15-google-oauth
149
+ 🔵 docs → codex-docs-#18-api-readme
150
+
151
+ ## PRIORIDADES
152
+ bug > feature > refactor > docs
153
+ GitHub Project: "Codex Kanban" (4 columnas)
154
+ Labels auto: 'crash→bug', 'añade→feature', 'docs→docs'
155
+
156
+ ---
157
+
158
+ ## 📚 DOCUMENTACIÓN OBLIGATORIA
159
+
160
+ Mantener ROADMAP.md siempre activo y actualizado: referencia principal para agentes y consulta humana.
161
+
162
+ ### README.md (Raíz)
163
+ ```markdown
164
+ # Proyecto XYZ
165
+
166
+ ## Quick Start
167
+ npm run install:all
168
+ npm run dev # → backend:3001 + frontend:3002
169
+
170
+ ## Architecture
171
+ Ver [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)
172
+
173
+ ## Roadmap (Fases y entregables)
174
+ Ver [ROADMAP.md](ROADMAP.md)
175
+ ```
176
+
177
+ ### backend/README.md
178
+ ```markdown
179
+ # Backend API
180
+
181
+ ## Endpoints
182
+ GET /api/users # Lista usuarios
183
+ POST /api/users # Crear usuario
184
+ ...
185
+
186
+ ## Examples
187
+ curl -X POST http://localhost:3001/api/users \
188
+ -H "Content-Type: application/json" \
189
+ -d '{"name":"John"}'
190
+ ```
191
+
192
+ ### frontend/README.md
193
+ ```markdown
194
+ # Frontend
195
+
196
+ ## Development
197
+ npm run dev # → http://localhost:3002
198
+
199
+ ## Build
200
+ npm run build # → dist/
201
+ ```
202
+
203
+ ### Inline Code
204
+ - JSDoc en funciones públicas
205
+ - Comentarios en bloques >15 líneas o lógica compleja
206
+ - TODOs con issue: `// TODO(#42): Refactor to use async/await`
207
+
208
+ ---
209
+
210
+ ## ✅ DECISIONES AUTOMÁTICAS
211
+
212
+ - Al añadir nuevas funciones o testar diferentes parámetros de configuración, siempre crear test particulares para cada escenario.
213
+ - Siempre mantener los tests actualizados de cualquier capa, módulo o servicio del proyecto.
214
+
215
+ ### Coverage & Quality
216
+ ```yaml
217
+ Tests pass: ✅ Auto-approve
218
+ Coverage ≥85%: ✅ Auto-approve
219
+ Lint errors: ❌ Block merge
220
+ Breaking changes: ⚠️ Require explicit approval
221
+ ```
222
+
223
+ ### Comandos
224
+ ```bash
225
+ /apply # Si tests pass → commit
226
+ /merge # Si CI pass + coverage OK → merge to main
227
+ /docs # Genera/actualiza docs antes de merge
228
+ ```
229
+
230
+ ---
231
+
232
+ ## 🔧 HERRAMIENTAS OPCIONALES
233
+
234
+ ### Browser Automation (si aplica)
235
+ - Puppeteer para E2E tests
236
+ - Playwright para cross-browser
237
+
238
+ ### MCP Servers (si aplica)
239
+ - GitHub MCP: Gestión issues/PRs
240
+ - Filesystem MCP: Operaciones archivo
241
+ - Database MCP: Queries directo
242
+
243
+ ### Monitoring (producción)
244
+ - Sentry (errores)
245
+ - Plausible/Umami (analytics ligero)
246
+ - Uptime robot (disponibilidad)
247
+
248
+ ---
249
+
250
+ ## 🎓 DECISIONES ARQUITECTÓNICAS
251
+
252
+ ### Cuándo Cambiar Stack
253
+ ```
254
+ JSON DB → PostgreSQL: >1000 registros o queries complejas
255
+ Context API → Zustand: >5 contexts o prop drilling
256
+ REST → GraphQL: Frontend necesita datos muy específicos
257
+ Monolito → Microservicios: >3 dominios independientes
258
+ ```
259
+
260
+ ### Logging
261
+ ```javascript
262
+ // Desarrollo: console.log OK
263
+ // Producción: winston/pino con niveles
264
+ logger.info('User created', { userId: 123 });
265
+ logger.error('DB connection failed', { error });
266
+ ```
267
+
268
+ ---
269
+
270
+ ## 🚨 EXCEPCIONES AL WORKFLOW
271
+
272
+ ### Requiere Aprobación Humana
273
+ - Cambios en AGENTS.md
274
+ - Eliminación datos producción
275
+ - Cambios permisos/seguridad
276
+ - Refactorización >500 líneas
277
+
278
+ ### Hotfix Critical
279
+ ```bash
280
+ # Branch directo desde main
281
+ hotfix-{descripción}-{timestamp}
282
+
283
+ # Deploy inmediato después de tests
284
+ # Notificar en #incidents canal
285
+ ```
286
+
287
+ ---
288
+
289
+ ## 📖 RECURSOS
290
+
291
+ - [Conventional Commits](https://www.conventionalcommits.org/)
292
+ - [Semantic Versioning](https://semver.org/)
293
+ - [GitHub Actions Docs](https://docs.github.com/en/actions)
294
+
295
+ ---
296
+
297
+ **Última actualización:** 2026-02-15
298
+ **Versión:** 1.0
299
+ **Mantenedor:** Equipo + AI Agents
@@ -0,0 +1,29 @@
1
+ # CODING NORMS
2
+
3
+ ## Stack base
4
+
5
+ - Backend: Express puerto 3001, db.json
6
+ - Frontend: React + Vite puerto 3002
7
+ - Tests: Jest y Vitest, cobertura objetivo >= 85%
8
+ - Git: ramas prefijo codex-*
9
+
10
+ ## Normas de desarrollo
11
+
12
+ - Crear carpeta `test/` en backend y frontend.
13
+ - Toda funcion nueva debe tener al menos un test asociado.
14
+ - Todo endpoint debe tener tests de integracion.
15
+ - No hacer cambios sin actualizar tests y documentacion si aplica.
16
+ - Validar entradas y manejar errores de forma consistente.
17
+ - Mantener estilos y dependencias simples.
18
+
19
+ ## CI
20
+
21
+ - CI debe correr en cada push y PR.
22
+ - Pasos minimos: install, test backend, test frontend, coverage.
23
+ - El pipeline debe ejecutar `npm run test:ci` en la raiz.
24
+ - Rechazar merges si coverage < 85% o tests fallan.
25
+
26
+ ## Documentacion
27
+
28
+ - README.md describe setup, arquitectura y endpoints.
29
+ - ROADMAP.md mantiene el plan de trabajo.
@@ -0,0 +1,48 @@
1
+ # Setup Project
2
+
3
+ Este documento define el flujo guiado para alinear el objetivo del proyecto, el alcance y las restricciones antes de tocar documentación o arquitectura.
4
+
5
+ ## Resultado acordado
6
+
7
+ Aplicación sencilla de lista de tareas con:
8
+
9
+ - CRUD básico (crear, listar, completar, eliminar)
10
+ - Web app con backend local
11
+ - Persistencia en SQLite
12
+ - UI cuidada aunque sea simple
13
+ - Sin usuarios ni autenticación
14
+ - Reaprovechar el código existente
15
+
16
+ ## Flujo Base (Iterativo)
17
+
18
+ 1. El usuario manifiesta objetivos o plan inicial.
19
+ 2. Si hubiera documentación previa y archivos de código, el agente la analiza todo y extrae puntos clave para la visión general.
20
+ 3. Si *NO* hubiera archivos previos (ignorar SETUP.md), el agente hace una primera pregunta abierta para entender el objetivo general del proyecto.
21
+ 4. A partir de ahí, el agente propone **tres escenarios posibles** basados en esa información.
22
+ 5. El usuario elige uno de los tres.
23
+ 6. El agente plantea otro cuestionario de **tres opciones** sobre un tema específico que necesite ser clarificado o ampliado.
24
+ 7. Repetir por **3 o 4 rondas** hasta lograr una visión general clara del proyecto y objetivos del usuario.
25
+ 8. El agente propone un **resumen breve** del proyecto.
26
+ 9. Si el usuario corrige, se abre una nueva ronda para aclarar y luego se actualiza el resumen.
27
+ 10. Si el usuario acepta, el agente redacta o corrige:
28
+ - `README.md`
29
+ - `ROADMAP.md`
30
+ - `docs/ARCHITECTURE.md`
31
+ - otros documentos relevantes
32
+ 11. El agente NO MODIFICA NI CREA CÓDIGO AUN, solo se enfoca en documentación, roadmap y arquitectura. El código se tocará en rondas posteriores.
33
+
34
+ ## Reglas del agente
35
+
36
+ - Preguntas cortas y enfocadas.
37
+ - Siempre ofrecer **tres opciones**, siendo la primera la recomendada.
38
+ - Si hubiera código o documentación previa, las opciones deben basarse en esa información, siendo la primera opción la que mejor se alinea con lo ya existente.
39
+ - No avanzar a documentación hasta tener una visión general aceptada.
40
+ - Reaprovechar el código existente siempre que sea posible.
41
+
42
+ ---
43
+
44
+ Estas instrucciones se usan al iniciar o retomar el proyecto, o para corregir dirección.
45
+
46
+ *NUNCA* se modifica el código previo en esta etapa, solo se propone la visión general, el roadmap y la arquitectura.
47
+
48
+