siesa-agents 2.1.22 → 2.1.23-dev.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 +10 -7
- package/bin/install.js +7 -105
- package/bmad-core/agents/architect.md +0 -2
- package/bmad-core/agents/dev.md +2 -0
- package/bmad-core/agents/ux-expert.md +0 -1
- package/bmad-core/checklists/story-dod-checklist.md +1 -0
- package/bmad-core/data/frontend-standards.md +37 -1
- package/claude/hooks/file-restriction-hook.py +51 -0
- package/claude/hooks/track-agent.py +67 -0
- package/claude/settings.local.json +37 -1
- package/package.json +1 -1
- package/bmad-core/data/architecture-patterns.md +0 -114
- package/bmad-core/data/technology-stack.md +0 -81
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SIESA Agents
|
|
1
|
+
# SIESA BMAD Agents
|
|
2
2
|
|
|
3
3
|
Paquete para instalar y configurar agentes SIESA en tu proyecto.
|
|
4
4
|
|
|
@@ -52,7 +52,6 @@ El paquete instala las siguientes carpetas en tu directorio actual:
|
|
|
52
52
|
- **`.bmad-core/`** - Archivos principales del sistema BMAD
|
|
53
53
|
- **`.vscode/`** - Configuración de Visual Studio Code
|
|
54
54
|
- **`.github/`** - Configuración de GitHub Actions y workflows
|
|
55
|
-
- **`.claude/`** - Configuración de Claude Code Commands y workflows
|
|
56
55
|
|
|
57
56
|
## Características
|
|
58
57
|
|
|
@@ -71,17 +70,22 @@ El paquete instala las siguientes carpetas en tu directorio actual:
|
|
|
71
70
|
|
|
72
71
|
Para actualizar una instalación existente, simplemente ejecuta el comando nuevamente:
|
|
73
72
|
|
|
73
|
+
**Versión estable (recomendado):**
|
|
74
74
|
```bash
|
|
75
75
|
npx siesa-agents
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
+
**Versión de desarrollo:**
|
|
79
|
+
```bash
|
|
80
|
+
npx siesa-agents@dev
|
|
81
|
+
```
|
|
82
|
+
|
|
78
83
|
El sistema detectará automáticamente que ya existe una instalación y la actualizará.
|
|
79
84
|
|
|
80
85
|
## Requisitos
|
|
81
86
|
|
|
82
87
|
- Node.js >= 14.0.0
|
|
83
88
|
- npm >= 6.0.0
|
|
84
|
-
- Python >= 3.7 (requerido para hooks de Claude Code)
|
|
85
89
|
|
|
86
90
|
## Estructura de archivos instalados
|
|
87
91
|
|
|
@@ -95,6 +99,8 @@ tu-proyecto/
|
|
|
95
99
|
└── [workflows y configuración de GitHub]
|
|
96
100
|
```
|
|
97
101
|
|
|
102
|
+
|
|
103
|
+
|
|
98
104
|
## Soporte
|
|
99
105
|
|
|
100
106
|
Si encuentras algún problema durante la instalación, por favor verifica:
|
|
@@ -109,7 +115,4 @@ MIT
|
|
|
109
115
|
|
|
110
116
|
## Autor
|
|
111
117
|
|
|
112
|
-
SIESA - Sistemas de Información Empresarial
|
|
113
|
-
|
|
114
|
-
---
|
|
115
|
-
*Versión actualizada automáticamente por CI/CD*
|
|
118
|
+
SIESA - Sistemas de Información Empresarial
|
package/bin/install.js
CHANGED
|
@@ -14,18 +14,9 @@ class SiesaBmadInstaller {
|
|
|
14
14
|
{ source: 'claude', target: '.claude' },
|
|
15
15
|
{ source: 'resources', target: '.resources' }
|
|
16
16
|
];
|
|
17
|
-
|
|
18
|
-
// Lista de archivos que se preservan automáticamente (no se crean backups)
|
|
19
|
-
this.ignoredFiles = [
|
|
20
|
-
'data/technical-preferences.md'
|
|
21
|
-
];
|
|
22
|
-
|
|
23
17
|
this.targetDir = process.cwd();
|
|
24
18
|
// Intentar múltiples ubicaciones posibles para el paquete
|
|
25
19
|
this.packageDir = this.findPackageDir();
|
|
26
|
-
|
|
27
|
-
// Almacenamiento temporal para contenido de archivos ignorados
|
|
28
|
-
this.preservedContent = new Map();
|
|
29
20
|
}
|
|
30
21
|
|
|
31
22
|
showBanner() {
|
|
@@ -36,7 +27,8 @@ class SiesaBmadInstaller {
|
|
|
36
27
|
console.log('╚════██║██║██╔══╝ ╚════██║██╔══██║ ██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ╚════██║');
|
|
37
28
|
console.log('███████║██║███████╗███████║██║ ██║ ██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ███████║');
|
|
38
29
|
console.log('╚══════╝╚═╝╚══════╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝');
|
|
39
|
-
console.log('');
|
|
30
|
+
console.log('Version de Desarrollador');
|
|
31
|
+
console.log('\n');
|
|
40
32
|
}
|
|
41
33
|
|
|
42
34
|
findPackageDir() {
|
|
@@ -133,8 +125,7 @@ class SiesaBmadInstaller {
|
|
|
133
125
|
modifiedFiles.push({
|
|
134
126
|
folder: mapping.target,
|
|
135
127
|
file: relativePath,
|
|
136
|
-
fullPath: targetFile
|
|
137
|
-
is_ignored: this.ignoredFiles.includes(relativePath)
|
|
128
|
+
fullPath: targetFile
|
|
138
129
|
});
|
|
139
130
|
}
|
|
140
131
|
} catch (error) {
|
|
@@ -146,8 +137,7 @@ class SiesaBmadInstaller {
|
|
|
146
137
|
modifiedFiles.push({
|
|
147
138
|
folder: mapping.target,
|
|
148
139
|
file: relativePath,
|
|
149
|
-
fullPath: targetFile
|
|
150
|
-
is_ignored: this.ignoredFiles.includes(relativePath)
|
|
140
|
+
fullPath: targetFile
|
|
151
141
|
});
|
|
152
142
|
}
|
|
153
143
|
}
|
|
@@ -178,10 +168,6 @@ class SiesaBmadInstaller {
|
|
|
178
168
|
}
|
|
179
169
|
|
|
180
170
|
async promptUser(modifiedFiles) {
|
|
181
|
-
|
|
182
|
-
const hasNonIgnoredFiles = modifiedFiles.some(file => file.is_ignored == false)
|
|
183
|
-
if (!hasNonIgnoredFiles) return '2'
|
|
184
|
-
|
|
185
171
|
console.log('\n⚠️ Se detectaron archivos modificados:');
|
|
186
172
|
|
|
187
173
|
// Agrupar por carpeta
|
|
@@ -222,12 +208,6 @@ class SiesaBmadInstaller {
|
|
|
222
208
|
console.log('\n🔄 Creando backup de archivos modificados...');
|
|
223
209
|
|
|
224
210
|
for (const item of modifiedFiles) {
|
|
225
|
-
// No crear backup de archivos ignorados
|
|
226
|
-
if (item.is_ignored) {
|
|
227
|
-
console.log(`✓ Preservando: ${item.file} (sin backup)`);
|
|
228
|
-
continue;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
211
|
const originalPath = item.fullPath;
|
|
232
212
|
const backupPath = this.getBackupPath(originalPath);
|
|
233
213
|
|
|
@@ -292,19 +272,10 @@ class SiesaBmadInstaller {
|
|
|
292
272
|
// Obtener todos los archivos backup existentes
|
|
293
273
|
const backupFiles = await this.findBackupFiles(targetPath);
|
|
294
274
|
|
|
295
|
-
// Copiar la carpeta
|
|
275
|
+
// Copiar la carpeta completa sobrescribiendo
|
|
296
276
|
await fs.copy(sourcePath, targetPath, {
|
|
297
277
|
overwrite: true,
|
|
298
|
-
recursive: true
|
|
299
|
-
filter: (src) => {
|
|
300
|
-
const relativePath = path.relative(sourcePath, src);
|
|
301
|
-
// No sobrescribir archivos ignorados si ya existen
|
|
302
|
-
if (this.ignoredFiles.includes(relativePath)) {
|
|
303
|
-
const targetFile = path.join(targetPath, relativePath);
|
|
304
|
-
return !fs.existsSync(targetFile);
|
|
305
|
-
}
|
|
306
|
-
return true;
|
|
307
|
-
}
|
|
278
|
+
recursive: true
|
|
308
279
|
});
|
|
309
280
|
|
|
310
281
|
// Restaurar los archivos backup
|
|
@@ -359,16 +330,7 @@ class SiesaBmadInstaller {
|
|
|
359
330
|
if (fs.existsSync(sourcePath)) {
|
|
360
331
|
await fs.copy(sourcePath, targetPath, {
|
|
361
332
|
overwrite: true,
|
|
362
|
-
recursive: true
|
|
363
|
-
filter: (src) => {
|
|
364
|
-
const relativePath = path.relative(sourcePath, src);
|
|
365
|
-
// No sobrescribir archivos ignorados si ya existen
|
|
366
|
-
if (this.ignoredFiles.includes(relativePath)) {
|
|
367
|
-
const targetFile = path.join(targetPath, relativePath);
|
|
368
|
-
return !fs.existsSync(targetFile);
|
|
369
|
-
}
|
|
370
|
-
return true;
|
|
371
|
-
}
|
|
333
|
+
recursive: true
|
|
372
334
|
});
|
|
373
335
|
} else {
|
|
374
336
|
console.warn(`⚠️ Carpeta ${mapping.source} no encontrada en el paquete`);
|
|
@@ -404,9 +366,6 @@ class SiesaBmadInstaller {
|
|
|
404
366
|
await this.performUpdateWithBackups();
|
|
405
367
|
} else {
|
|
406
368
|
// Si no hay backups, hacer actualización normal (remover y copiar)
|
|
407
|
-
// Pero primero preservar archivos ignorados
|
|
408
|
-
await this.preserveIgnoredFiles();
|
|
409
|
-
|
|
410
369
|
for (const mapping of this.folderMappings) {
|
|
411
370
|
const targetPath = path.join(this.targetDir, mapping.target);
|
|
412
371
|
|
|
@@ -417,66 +376,9 @@ class SiesaBmadInstaller {
|
|
|
417
376
|
|
|
418
377
|
// Realizar instalación nueva
|
|
419
378
|
await this.performInstallation();
|
|
420
|
-
|
|
421
|
-
// Restaurar archivos ignorados
|
|
422
|
-
await this.restoreIgnoredFiles();
|
|
423
379
|
}
|
|
424
380
|
}
|
|
425
381
|
|
|
426
|
-
async preserveIgnoredFiles() {
|
|
427
|
-
console.log('🔒 Preservando archivos de configuración...');
|
|
428
|
-
|
|
429
|
-
for (const mapping of this.folderMappings) {
|
|
430
|
-
const targetFolderPath = path.join(this.targetDir, mapping.target);
|
|
431
|
-
|
|
432
|
-
if (!fs.existsSync(targetFolderPath)) {
|
|
433
|
-
continue;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
for (const ignoredFile of this.ignoredFiles) {
|
|
437
|
-
const filePath = path.join(targetFolderPath, ignoredFile);
|
|
438
|
-
|
|
439
|
-
if (fs.existsSync(filePath)) {
|
|
440
|
-
try {
|
|
441
|
-
const content = await fs.readFile(filePath, 'utf8');
|
|
442
|
-
const key = `${mapping.target}/${ignoredFile}`;
|
|
443
|
-
this.preservedContent.set(key, content);
|
|
444
|
-
console.log(`✓ Preservando: ${ignoredFile}`);
|
|
445
|
-
} catch (error) {
|
|
446
|
-
console.warn(`⚠️ Error leyendo ${ignoredFile}: ${error.message}`);
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
async restoreIgnoredFiles() {
|
|
454
|
-
if (this.preservedContent.size === 0) {
|
|
455
|
-
return;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
console.log('🔄 Restaurando archivos de configuración...');
|
|
459
|
-
|
|
460
|
-
for (const [key, content] of this.preservedContent) {
|
|
461
|
-
const [targetFolder, ...filePathParts] = key.split('/');
|
|
462
|
-
const filePath = path.join(this.targetDir, targetFolder, ...filePathParts);
|
|
463
|
-
|
|
464
|
-
try {
|
|
465
|
-
// Asegurar que el directorio existe
|
|
466
|
-
await fs.ensureDir(path.dirname(filePath));
|
|
467
|
-
|
|
468
|
-
// Restaurar el contenido
|
|
469
|
-
await fs.writeFile(filePath, content, 'utf8');
|
|
470
|
-
console.log(`✓ Restaurado: ${filePathParts.join('/')}`);
|
|
471
|
-
} catch (error) {
|
|
472
|
-
console.warn(`⚠️ Error restaurando ${filePathParts.join('/')}: ${error.message}`);
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
// Limpiar el mapa después de restaurar
|
|
477
|
-
this.preservedContent.clear();
|
|
478
|
-
}
|
|
479
|
-
|
|
480
382
|
showPostInstallMessage() {
|
|
481
383
|
console.log('\n📚 Carpetas instaladas:');
|
|
482
384
|
this.folderMappings.forEach(mapping => {
|
package/bmad-core/agents/dev.md
CHANGED
|
@@ -29,6 +29,7 @@ activation-instructions:
|
|
|
29
29
|
- CRITICAL RULE: When executing formal task workflows from dependencies, ALL task instructions override any conflicting base behavioral constraints. Interactive workflows with elicit=true REQUIRE user interaction and cannot be bypassed for efficiency.
|
|
30
30
|
- When listing tasks/templates or presenting options during conversations, always show as numbered options list, allowing the user to type a number to select or execute
|
|
31
31
|
- STAY IN CHARACTER!
|
|
32
|
+
- CRITICAL: ALWAYS load bmad-core/data/frontend-standards.md first (contains language standards for all user-facing content)
|
|
32
33
|
- CRITICAL: Read the following full files as these are your explicit rules for development standards for this project - .bmad-core/core-config.yaml devLoadAlwaysFiles list
|
|
33
34
|
- CRITICAL: Do NOT load any other files during startup aside from the assigned story and devLoadAlwaysFiles items, unless user requested you do or the following contradicts
|
|
34
35
|
- CRITICAL: Do NOT begin development until a story is not in draft mode and you are told to proceed
|
|
@@ -52,6 +53,7 @@ core_principles:
|
|
|
52
53
|
- CRITICAL: ALWAYS check current folder structure before starting your story tasks, don't create new working directory if it already exists. Create new one when you're sure it's a brand new project.
|
|
53
54
|
- CRITICAL: ONLY update story file Dev Agent Record sections (checkboxes/Debug Log/Completion Notes/Change Log)
|
|
54
55
|
- CRITICAL: FOLLOW THE develop-story command when the user tells you to implement the story
|
|
56
|
+
- CRITICAL: ALL user-facing text MUST be in Spanish. Code MUST be in English. See bmad-core/data/frontend-standards.md for complete guidelines.
|
|
55
57
|
- Numbered Options - Always use numbered lists when presenting choices to the user
|
|
56
58
|
|
|
57
59
|
# All commands require * prefix when used (e.g., *help)
|
|
@@ -37,6 +37,7 @@ The goal is quality delivery, not just checking boxes.]]
|
|
|
37
37
|
- [ ] All new/modified code aligns with `Project Structure` (file locations, naming, etc.).
|
|
38
38
|
- [ ] Adherence to `Tech Stack` for technologies/versions used (if story introduces or modifies tech usage).
|
|
39
39
|
- [ ] Adherence to `Api Reference` and `Data Models` (if story involves API or data model changes).
|
|
40
|
+
- [ ] **CRITICAL: All user-facing text (UI labels, buttons, error messages, validations, notifications, etc.) is in Spanish. Code (variables, functions, classes, comments) is in English. No mixed-language text in UI.**
|
|
40
41
|
- [ ] Basic security best practices (e.g., input validation, proper error handling, no hardcoded secrets) applied for new/modified code.
|
|
41
42
|
- [ ] No new linter errors or warnings introduced.
|
|
42
43
|
- [ ] Code is well-commented where necessary (clarifying complex logic, not obvious statements).
|
|
@@ -335,4 +335,40 @@ import { Button } from '@/components/ui/button';
|
|
|
335
335
|
- Cache-first for static assets
|
|
336
336
|
- Network-first for dynamic data
|
|
337
337
|
- Fallback pages for offline scenarios
|
|
338
|
-
- Sync when connection restored
|
|
338
|
+
- Sync when connection restored
|
|
339
|
+
|
|
340
|
+
## Language Standards (Frontend & Backend)
|
|
341
|
+
|
|
342
|
+
### Spanish for All User-Facing Content (CRITICAL RULE)
|
|
343
|
+
|
|
344
|
+
**MANDATORY: All text visible to end users MUST be in Spanish.**
|
|
345
|
+
|
|
346
|
+
#### ✅ Spanish Required:
|
|
347
|
+
- UI labels, buttons, forms, messages, notifications
|
|
348
|
+
- API responses, validation errors, email templates
|
|
349
|
+
- Any text the user sees (frontend or backend)
|
|
350
|
+
|
|
351
|
+
#### ✅ English Required:
|
|
352
|
+
- Code (variables, functions, classes)
|
|
353
|
+
- Technical logs, comments, git commits
|
|
354
|
+
- Developer documentation
|
|
355
|
+
|
|
356
|
+
#### ❌ Never mix languages in user-facing text
|
|
357
|
+
|
|
358
|
+
**Examples:**
|
|
359
|
+
```typescript
|
|
360
|
+
// ✅ CORRECT
|
|
361
|
+
<Button>Guardar</Button>
|
|
362
|
+
toast.success("Datos guardados correctamente");
|
|
363
|
+
throw new BadRequestException('No se pudo crear el usuario');
|
|
364
|
+
|
|
365
|
+
// ❌ INCORRECT
|
|
366
|
+
<Button>Save cambios</Button>
|
|
367
|
+
toast.error("Failed al guardar");
|
|
368
|
+
throw new BadRequestException('Invalid datos proporcionados');
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
**Implementation:**
|
|
372
|
+
- Create message constants in Spanish
|
|
373
|
+
- Validate all user-facing text before story completion
|
|
374
|
+
- Technical logs stay in English, user messages in Spanish
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import json
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
# Leer JSON desde stdin
|
|
7
|
+
data = json.load(sys.stdin)
|
|
8
|
+
|
|
9
|
+
# Obtener información del archivo y sesión
|
|
10
|
+
file_path = data.get('tool_input', {}).get('file_path', '')
|
|
11
|
+
extension = os.path.splitext(file_path)[1].lower() if file_path else ''
|
|
12
|
+
session_id = data.get('session_id', '')
|
|
13
|
+
cwd = data.get('cwd', '')
|
|
14
|
+
|
|
15
|
+
# Construir ruta relativa al log desde el cwd
|
|
16
|
+
log_file = os.path.join(cwd, '.claude', 'logs', 'active_agents.json')
|
|
17
|
+
|
|
18
|
+
# Agentes que solo pueden escribir markdown
|
|
19
|
+
MARKDOWN_ONLY_AGENTS = ['PO', 'SM', 'PM', 'ANALYST', 'ARCHITECT', 'UX-EXPERT']
|
|
20
|
+
|
|
21
|
+
# Verificar si la sesión actual tiene un agente activo
|
|
22
|
+
if session_id and os.path.exists(log_file):
|
|
23
|
+
try:
|
|
24
|
+
with open(log_file, 'r', encoding='utf-8') as f:
|
|
25
|
+
active_agents = json.load(f)
|
|
26
|
+
|
|
27
|
+
# Si la sesión actual tiene un agente activo
|
|
28
|
+
if session_id in active_agents:
|
|
29
|
+
agent_type = active_agents[session_id]['agent']
|
|
30
|
+
|
|
31
|
+
# Si el agente está en la lista de solo markdown
|
|
32
|
+
if agent_type in MARKDOWN_ONLY_AGENTS:
|
|
33
|
+
# Solo permitir archivos markdown
|
|
34
|
+
if extension != '.md':
|
|
35
|
+
result = {
|
|
36
|
+
"hookSpecificOutput": {
|
|
37
|
+
"hookEventName": "PreToolUse",
|
|
38
|
+
"permissionDecision": "deny",
|
|
39
|
+
"permissionDecisionReason": f"⛔ El agente de tipo {agent_type} solo puede redactar archivos markdown"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
print(json.dumps(result))
|
|
43
|
+
sys.exit(0)
|
|
44
|
+
except:
|
|
45
|
+
# Si hay error leyendo el log, permitir la operación
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
# Si no está bloqueado, permitir la operación (no imprimir nada)
|
|
49
|
+
except Exception as e:
|
|
50
|
+
# En caso de error, permitir la operación
|
|
51
|
+
pass
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import json
|
|
3
|
+
import os
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
|
|
6
|
+
try:
|
|
7
|
+
# Leer JSON desde stdin
|
|
8
|
+
data = json.load(sys.stdin)
|
|
9
|
+
|
|
10
|
+
session_id = data.get('session_id', '')
|
|
11
|
+
prompt = data.get('prompt', '').lower()
|
|
12
|
+
cwd = data.get('cwd', '')
|
|
13
|
+
|
|
14
|
+
# Construir ruta relativa al log desde el cwd
|
|
15
|
+
log_file = os.path.join(cwd, '.claude', 'logs', 'active_agents.json')
|
|
16
|
+
|
|
17
|
+
# Crear directorio si no existe
|
|
18
|
+
log_dir = os.path.dirname(log_file)
|
|
19
|
+
os.makedirs(log_dir, exist_ok=True)
|
|
20
|
+
|
|
21
|
+
# Lista completa de agentes disponibles
|
|
22
|
+
agent_identifiers = {
|
|
23
|
+
'agents:po': 'PO',
|
|
24
|
+
'agents:sm': 'SM',
|
|
25
|
+
'agents:pm': 'PM',
|
|
26
|
+
'agents:analyst': 'ANALYST',
|
|
27
|
+
'agents:architect': 'ARCHITECT',
|
|
28
|
+
'agents:dev': 'DEV',
|
|
29
|
+
'agents:backend': 'BACKEND',
|
|
30
|
+
'agents:frontend': 'FRONTEND',
|
|
31
|
+
'agents:qa': 'QA',
|
|
32
|
+
'agents:ux-expert': 'UX-EXPERT',
|
|
33
|
+
'agents:bmad-master': 'BMAD-MASTER',
|
|
34
|
+
'agents:bmad-orchestrator': 'BMAD-ORCHESTRATOR'
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
# Detectar si se está invocando un agente
|
|
38
|
+
agent_type = None
|
|
39
|
+
for identifier, agent_name in agent_identifiers.items():
|
|
40
|
+
if identifier in prompt or f'/bmad:{identifier}' in prompt:
|
|
41
|
+
agent_type = agent_name
|
|
42
|
+
break
|
|
43
|
+
|
|
44
|
+
if agent_type and session_id:
|
|
45
|
+
# Leer log existente
|
|
46
|
+
active_agents = {}
|
|
47
|
+
if os.path.exists(log_file):
|
|
48
|
+
try:
|
|
49
|
+
with open(log_file, 'r', encoding='utf-8') as f:
|
|
50
|
+
active_agents = json.load(f)
|
|
51
|
+
except:
|
|
52
|
+
active_agents = {}
|
|
53
|
+
|
|
54
|
+
# Actualizar o agregar la sesión con el agente actual
|
|
55
|
+
active_agents[session_id] = {
|
|
56
|
+
'agent': agent_type,
|
|
57
|
+
'timestamp': datetime.now().isoformat(),
|
|
58
|
+
'last_prompt': prompt[:100] # Guardar inicio del prompt para debug
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
# Guardar log actualizado
|
|
62
|
+
with open(log_file, 'w', encoding='utf-8') as f:
|
|
63
|
+
json.dump(active_agents, f, indent=2, ensure_ascii=False)
|
|
64
|
+
|
|
65
|
+
except Exception as e:
|
|
66
|
+
# En caso de error, no bloquear la operación
|
|
67
|
+
pass
|
|
@@ -16,5 +16,41 @@
|
|
|
16
16
|
],
|
|
17
17
|
"deny": [],
|
|
18
18
|
"ask": []
|
|
19
|
-
}
|
|
19
|
+
},
|
|
20
|
+
"hooks": {
|
|
21
|
+
"UserPromptSubmit": [
|
|
22
|
+
{
|
|
23
|
+
"matcher": ".*",
|
|
24
|
+
"hooks": [
|
|
25
|
+
{
|
|
26
|
+
"type": "command",
|
|
27
|
+
"command": "python .claude/hooks/track-agent.py"
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
"PreToolUse": [
|
|
33
|
+
{
|
|
34
|
+
"matcher": "Write|Edit",
|
|
35
|
+
"hooks": [
|
|
36
|
+
{
|
|
37
|
+
"type": "command",
|
|
38
|
+
"command": "python .claude/hooks/file-restriction-hook.py"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"SessionEnd": [
|
|
44
|
+
{
|
|
45
|
+
"matcher": ".*",
|
|
46
|
+
"hooks": [
|
|
47
|
+
{
|
|
48
|
+
"type": "command",
|
|
49
|
+
"command": "python .claude/hooks/cleanup-agent.py"
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
"disableAllHooks": false
|
|
20
56
|
}
|
package/package.json
CHANGED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
# Architecture Patterns & Design Decisions
|
|
2
|
-
|
|
3
|
-
## Frontend Architecture
|
|
4
|
-
|
|
5
|
-
### Architecture Style
|
|
6
|
-
- **Clean Architecture** + **Domain-Driven Design (DDD)**
|
|
7
|
-
|
|
8
|
-
### Folder Structure
|
|
9
|
-
|
|
10
|
-
Next.js 15 App Router Structure with Clean Architecture + DDD:
|
|
11
|
-
|
|
12
|
-
```
|
|
13
|
-
├── app/ # Next.js App Router directory
|
|
14
|
-
│ ├── (dashboard)/ # Route groups for dashboard
|
|
15
|
-
│ ├── sales/ # Routes for sales module
|
|
16
|
-
│ │ ├── quotes/ # Quote management pages
|
|
17
|
-
│ │ └── invoices/ # Invoice pages
|
|
18
|
-
│ ├── inventory/ # Inventory routes
|
|
19
|
-
│ ├── globals.css # Global styles
|
|
20
|
-
│ ├── layout.tsx # Root layout component
|
|
21
|
-
│ ├── page.tsx # Home page
|
|
22
|
-
│ ├── loading.tsx # Global loading UI
|
|
23
|
-
│ └── not-found.tsx # 404 page
|
|
24
|
-
│
|
|
25
|
-
├── src/
|
|
26
|
-
│ ├── modules/ # Business modules following DDD
|
|
27
|
-
│ │ ├── sales/ # Sales module
|
|
28
|
-
│ │ │ ├── quotes/ # Quote domain
|
|
29
|
-
│ │ │ │ ├── cart/ # Shopping cart feature
|
|
30
|
-
│ │ │ │ │ ├── domain/
|
|
31
|
-
│ │ │ │ │ │ ├── entities/
|
|
32
|
-
│ │ │ │ │ │ ├── repositories/
|
|
33
|
-
│ │ │ │ │ │ ├── services/
|
|
34
|
-
│ │ │ │ │ │ └── types/
|
|
35
|
-
│ │ │ │ │ ├── application/
|
|
36
|
-
│ │ │ │ │ │ ├── use-cases/
|
|
37
|
-
│ │ │ │ │ │ ├── hooks/
|
|
38
|
-
│ │ │ │ │ │ └── store/
|
|
39
|
-
│ │ │ │ │ ├── infrastructure/
|
|
40
|
-
│ │ │ │ │ │ ├── repositories/
|
|
41
|
-
│ │ │ │ │ │ ├── api/
|
|
42
|
-
│ │ │ │ │ │ └── adapters/
|
|
43
|
-
│ │ │ │ │ └── presentation/
|
|
44
|
-
│ │ │ │ │ └── components/ # Only components, pages in app/
|
|
45
|
-
│ │ │ │ └── products/ # Products feature
|
|
46
|
-
│ │ │ └── billing/ # Billing domain
|
|
47
|
-
│ │ ├── inventory/ # Inventory module
|
|
48
|
-
│ │ └── users/ # User module
|
|
49
|
-
│ │
|
|
50
|
-
│ ├── shared/
|
|
51
|
-
│ │ ├── components/ # Reusable UI components
|
|
52
|
-
│ │ ├── hooks/ # Shared hooks
|
|
53
|
-
│ │ ├── utils/ # Utility functions
|
|
54
|
-
│ │ ├── types/ # Common TypeScript types
|
|
55
|
-
│ │ └── constants/ # App constants
|
|
56
|
-
│ │
|
|
57
|
-
│ ├── providers/ # React context providers
|
|
58
|
-
│ ├── store/ # Global Zustand stores
|
|
59
|
-
│ └── middleware.ts # Next.js middleware
|
|
60
|
-
│
|
|
61
|
-
├── lib/ # Next.js utilities and configurations
|
|
62
|
-
├── components/ # Global UI components (alternative to src/shared)
|
|
63
|
-
├── public/ # Static assets and PWA manifest
|
|
64
|
-
└── styles/ # Additional stylesheets
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### Core Principles
|
|
68
|
-
|
|
69
|
-
#### Clean Architecture First
|
|
70
|
-
Strict separation of:
|
|
71
|
-
- **Domain layer** - Business entities, repositories interfaces, domain services, and types
|
|
72
|
-
- **Application layer** - Use cases, hooks, and state management (Zustand stores)
|
|
73
|
-
- **Infrastructure layer** - Repository implementations, API clients, and adapters
|
|
74
|
-
- **Presentation layer** - UI components (pages go in `app/`, components in `presentation/`)
|
|
75
|
-
|
|
76
|
-
#### Domain-Driven Design
|
|
77
|
-
Business logic drives architecture decisions. Organize by business modules and domains, not technical layers.
|
|
78
|
-
|
|
79
|
-
#### Component Composition
|
|
80
|
-
Build complex UIs from simple, reusable components.
|
|
81
|
-
|
|
82
|
-
#### Type Safety
|
|
83
|
-
Leverage TypeScript for compile-time safety and developer experience.
|
|
84
|
-
|
|
85
|
-
#### Performance by Design
|
|
86
|
-
- Lazy loading
|
|
87
|
-
- Memoization
|
|
88
|
-
- Bundle optimization
|
|
89
|
-
|
|
90
|
-
#### Accessibility as Standard
|
|
91
|
-
WCAG 2.1 AA compliance in all components.
|
|
92
|
-
|
|
93
|
-
#### Test-Driven Development
|
|
94
|
-
Unit tests for all use cases and components.
|
|
95
|
-
|
|
96
|
-
#### Progressive Web App
|
|
97
|
-
Offline-first approach with service workers.
|
|
98
|
-
|
|
99
|
-
#### Minimal and Functional
|
|
100
|
-
Only build what's explicitly requested, nothing more.
|
|
101
|
-
|
|
102
|
-
#### User-Centered Design
|
|
103
|
-
Start with user needs and work backward to implementation.
|
|
104
|
-
|
|
105
|
-
#### MCP Shadcn Available
|
|
106
|
-
Use MCP to install Shadcn components instead of creating manually.
|
|
107
|
-
|
|
108
|
-
### Framework Selection Rules
|
|
109
|
-
|
|
110
|
-
**Default**: Always use Next.js 15 with App Router unless explicitly told otherwise.
|
|
111
|
-
|
|
112
|
-
**Exceptions**: Only use pure React + Vite when user specifically mentions offline-first functionality or requests non-Next.js setup.
|
|
113
|
-
|
|
114
|
-
**Reasoning**: Next.js provides better developer experience, built-in optimization, and easier deployment while maintaining PWA capabilities.
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
# Technology Stack
|
|
2
|
-
|
|
3
|
-
## Frontend Stack
|
|
4
|
-
|
|
5
|
-
### Framework
|
|
6
|
-
- **Next.js 15** with TypeScript (App Router)
|
|
7
|
-
- Default framework unless explicitly told otherwise
|
|
8
|
-
- Built-in Turbopack/Webpack for building
|
|
9
|
-
- File-based routing with App Router
|
|
10
|
-
- Exception: Use pure React + Vite only when user specifically mentions offline-first functionality or requests non-Next.js setup
|
|
11
|
-
|
|
12
|
-
### State Management
|
|
13
|
-
- **Zustand**
|
|
14
|
-
|
|
15
|
-
### UI Framework & Styling
|
|
16
|
-
- **Shadcn/ui** (component library)
|
|
17
|
-
- **Radix UI** (primitives)
|
|
18
|
-
- **TailwindCSS v4** (styling)
|
|
19
|
-
|
|
20
|
-
### Architecture
|
|
21
|
-
- **Clean Architecture** + **Domain-Driven Design (DDD)**
|
|
22
|
-
|
|
23
|
-
### Testing
|
|
24
|
-
- **Vitest** (test runner)
|
|
25
|
-
- **React Testing Library** (component testing)
|
|
26
|
-
- **MSW** (Mock Service Worker - API mocking)
|
|
27
|
-
|
|
28
|
-
### Forms & Validation
|
|
29
|
-
- **React Hook Form** (form management)
|
|
30
|
-
- **Zod** (schema validation)
|
|
31
|
-
|
|
32
|
-
### HTTP Client
|
|
33
|
-
- **Axios** with interceptors
|
|
34
|
-
|
|
35
|
-
### Progressive Web App (PWA)
|
|
36
|
-
- **Next.js PWA plugin**
|
|
37
|
-
- **Workbox** (service worker library)
|
|
38
|
-
|
|
39
|
-
### Routing
|
|
40
|
-
- **Next.js App Router** (file-based routing)
|
|
41
|
-
|
|
42
|
-
## Core Principles
|
|
43
|
-
|
|
44
|
-
### Clean Architecture First
|
|
45
|
-
Strict separation of:
|
|
46
|
-
- Domain layer
|
|
47
|
-
- Application layer
|
|
48
|
-
- Infrastructure layer
|
|
49
|
-
- Presentation layer
|
|
50
|
-
|
|
51
|
-
### Domain-Driven Design
|
|
52
|
-
Business logic drives architecture decisions
|
|
53
|
-
|
|
54
|
-
### Component Composition
|
|
55
|
-
Build complex UIs from simple, reusable components
|
|
56
|
-
|
|
57
|
-
### Type Safety
|
|
58
|
-
Leverage TypeScript for compile-time safety and developer experience
|
|
59
|
-
|
|
60
|
-
### Performance by Design
|
|
61
|
-
- Lazy loading
|
|
62
|
-
- Memoization
|
|
63
|
-
- Bundle optimization
|
|
64
|
-
|
|
65
|
-
### Accessibility as Standard
|
|
66
|
-
WCAG 2.1 AA compliance in all components
|
|
67
|
-
|
|
68
|
-
### Test-Driven Development
|
|
69
|
-
Unit tests for all use cases and components
|
|
70
|
-
|
|
71
|
-
### Progressive Web App
|
|
72
|
-
Offline-first approach with service workers
|
|
73
|
-
|
|
74
|
-
### Minimal and Functional
|
|
75
|
-
Only build what's explicitly requested, nothing more
|
|
76
|
-
|
|
77
|
-
### User-Centered Design
|
|
78
|
-
Start with user needs and work backward to implementation
|
|
79
|
-
|
|
80
|
-
### MCP Shadcn Available
|
|
81
|
-
Use MCP to install Shadcn components instead of creating manually
|