openprompt-lang 1.2.6 → 1.2.7
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/docs/FRAMEWORK.md +52 -0
- package/docs/OPL-ERRORES.md +504 -0
- package/package.json +1 -1
- package/src/cli/commands-work.js +3 -1
- package/src/commands/init-core.js +19 -7
- package/src/commands/init-existing.js +13 -6
- package/src/commands/init-helpers.js +20 -14
- package/src/commands/work-context.js +17 -0
- package/src/commands/workflow/close/index.js +2 -1
- package/src/commands/workflow/delivery/index.js +4 -0
- package/src/commands/workflow/discovery/index.js +4 -0
- package/src/commands/workflow/specification/index.js +4 -0
- package/src/core/engine/sandbox.js +7 -3
- package/src/mcp-plan-server.js +12 -5
- package/src/mcp-shared-state.js +25 -0
- package/src/mcp-refactor/mcp-server.js +0 -171
- package/src/mcp-server-backup.js +0 -1913
package/docs/FRAMEWORK.md
CHANGED
|
@@ -186,6 +186,37 @@ npx openPrompt-Lang work-context learn
|
|
|
186
186
|
npx openPrompt-Lang work-context report
|
|
187
187
|
```
|
|
188
188
|
|
|
189
|
+
### Plan y Modo (Planificación Ágil)
|
|
190
|
+
```
|
|
191
|
+
opl plan → Cambiar a modo PLAN (bloquea tools de escritura)
|
|
192
|
+
opl execute → Cambiar a modo EXECUTE (requiere plan aprobado)
|
|
193
|
+
opl mode → Mostrar modo actual (plan/execute)
|
|
194
|
+
opl workflow discovery → E.1 — Wizard de descubrimiento (8 bloques, 29 preguntas)
|
|
195
|
+
opl workflow specification → E.2 — Generar documentos y diagramas Mermaid
|
|
196
|
+
opl workflow delivery → E.3 — Iniciar desarrollo por tickets
|
|
197
|
+
opl workflow close → E.4 — Cerrar sesión y documentar aprendizajes
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Teaching (Enseñanza Adaptativa)
|
|
201
|
+
```
|
|
202
|
+
opl teach progress → Dashboard de progreso
|
|
203
|
+
opl teach template <id> → Lección desde template @teachMe
|
|
204
|
+
opl teach assess → Diagnosticar nivel de dominio
|
|
205
|
+
opl teach study → Unidad pedagógica adaptada
|
|
206
|
+
opl teach project-guide → Ruta de aprendizaje con tickets
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Ticket, Memoria y Diagnóstico
|
|
210
|
+
```
|
|
211
|
+
opl ticket create --title "..." → Crear ticket de trabajo
|
|
212
|
+
opl ticket list → Listar tickets (--status ready|backlog|done)
|
|
213
|
+
opl ticket close <id> → Cerrar ticket
|
|
214
|
+
opl recall "consulta" → Búsqueda en memoria del proyecto
|
|
215
|
+
opl doctor → Diagnóstico del sistema OPL
|
|
216
|
+
opl fix → Auto-corrección de errores
|
|
217
|
+
opl rebuild → Reconstrucción de configuración
|
|
218
|
+
```
|
|
219
|
+
|
|
189
220
|
### QA, Extracción y AI
|
|
190
221
|
```
|
|
191
222
|
npx openPrompt-Lang qa-gen [--lang L] [--source DIR] [--output DIR] [--dry-run] [--no-scan]
|
|
@@ -197,6 +228,12 @@ npx openPrompt-Lang db-rules [--list] [--id ID] [--tag TAG]
|
|
|
197
228
|
npx openPrompt-Lang scaffold folders FRAMEWORK [--name N] [--force]
|
|
198
229
|
```
|
|
199
230
|
|
|
231
|
+
### MCP Servers
|
|
232
|
+
```
|
|
233
|
+
npx openPrompt-Lang mcp → Iniciar servidor MCP principal (tools OPL)
|
|
234
|
+
npx openPrompt-Lang mcp-plan → Iniciar servidor MCP de planificación (tools plan_*)
|
|
235
|
+
```
|
|
236
|
+
|
|
200
237
|
### MCP Server
|
|
201
238
|
```
|
|
202
239
|
npx openPrompt-Lang mcp
|
|
@@ -234,6 +271,21 @@ npx openPrompt-Lang mcp
|
|
|
234
271
|
| `work_context_start` | Iniciar sesión con tracking | `task` (req), `domain?` |
|
|
235
272
|
| `work_context_status` | Estado actual de la sesión | — |
|
|
236
273
|
| `work_context_close` | Cerrar sesión y registrar métricas | `summary` (req) |
|
|
274
|
+
| `teach_progress` | Mostrar progreso de aprendizaje | `userId?`, `domain?` |
|
|
275
|
+
| `teach_assess` | Diagnosticar nivel de dominio | `conceptId` (req), `domain?` |
|
|
276
|
+
| `teach_study` | Generar unidad pedagógica adaptada | `conceptId` (req), `level?`, `includeExercises?` |
|
|
277
|
+
|
|
278
|
+
### Servidor OPL-Plan (tools adicionales)
|
|
279
|
+
|
|
280
|
+
| Herramienta | Descripción | Parámetros |
|
|
281
|
+
|------------|-------------|------------|
|
|
282
|
+
| `plan_recommend_stack` | Analizar proyecto y recomendar stack | `description` (req) |
|
|
283
|
+
| `plan_wizard` | Wizard interactivo de configuración | `project_name` (req), `context` (req) |
|
|
284
|
+
| `plan_create` | Crear plan formal @workflow | `project_name` (req), `language` (req), `stack` (req) |
|
|
285
|
+
| `plan_validate` | Validar que el plan esté completo | `plan_id?` |
|
|
286
|
+
| `plan_status` | Mostrar estado del plan actual | `plan_id?` |
|
|
287
|
+
| `plan_switch_mode` | Cambiar a EXECUTE mode | `plan_id?` |
|
|
288
|
+
| `plan_knowledge_filter` | Filtrar biblioteca por dominio | `domain` (req), `features?` |
|
|
237
289
|
|
|
238
290
|
## 11. Reglas Estrictas
|
|
239
291
|
|
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
# 📋 Auditoría OPL — AppMobilSaaSEcommerce
|
|
2
|
+
|
|
3
|
+
> **Generado:** 2026-05-23
|
|
4
|
+
> **Propósito:** Documentar todos los errores, problemas de anotaciones, y deuda técnica encontrada en el proyecto para resolverlos sistemáticamente.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 📊 Resumen del proyecto
|
|
9
|
+
|
|
10
|
+
| Aspecto | Valor |
|
|
11
|
+
|---------|-------|
|
|
12
|
+
| Stack | React 18 + Vite 6 + TypeScript 5.9 + Tailwind 3 |
|
|
13
|
+
| Mobile | Ionic 8 + Capacitor 7 (Android/iOS) |
|
|
14
|
+
| Backend | Supabase (Auth, DB, Realtime, Storage, Edge Functions) |
|
|
15
|
+
| Archivos totales | ~90+ archivos fuente |
|
|
16
|
+
| Componentes UI | 31 componentes de página + 49 shadcn/ui |
|
|
17
|
+
| Hooks | 10 hooks personalizados |
|
|
18
|
+
| Archivos con anotaciones OPL | **3 de 50+** (✅ `useOfflineQueue`, `useCapacitorLifecycle`, `DeliveryZones`, `pushNotifications`) |
|
|
19
|
+
| Archivos sin anotaciones OPL | **~46 archivos** |
|
|
20
|
+
| Tests unitarios | **0** |
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 🚨 CATEGORÍA 1: Anotaciones OPL faltantes
|
|
25
|
+
|
|
26
|
+
### 1.1 — `src/App.tsx` — Sin anotaciones OPL
|
|
27
|
+
**Archivo:** `src/App.tsx` (266 líneas)
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
// @use(kind, contract, limit, deps)
|
|
31
|
+
// @kind(page)
|
|
32
|
+
// @contract(in: void -> out: JSX.Element)
|
|
33
|
+
// @limit(lines: 300, deps: 10)
|
|
34
|
+
// @deps(@external: [react, sonner, lucide-react], @internal: [
|
|
35
|
+
// ./components/Login, ./components/Dashboard, ./components/Catalog,
|
|
36
|
+
// ./components/Reports, ./components/BottomNav, ./components/Settings,
|
|
37
|
+
// ./components/Notifications, ./components/QueueModal,
|
|
38
|
+
// ./components/OfferExecutionModal, ./components/CalendarModal,
|
|
39
|
+
// ./components/OfflineRestrictionModal, ./components/PinPadModal,
|
|
40
|
+
// ./hooks/useAuth, ./hooks/useAppData, ./hooks/useOfflineQueue,
|
|
41
|
+
// ./hooks/useCapacitorLifecycle, ./hooks/useRealtimeSync,
|
|
42
|
+
// ./hooks/useProducts, ./hooks/useOrders, ./hooks/useOffers,
|
|
43
|
+
// ./hooks/useMetrics, ./services/pushNotifications
|
|
44
|
+
// ])
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 1.2 — `src/main.tsx` — Sin anotaciones OPL
|
|
48
|
+
**Archivo:** `src/main.tsx` (11 líneas)
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
// @use(kind, deps)
|
|
52
|
+
// @kind(entry)
|
|
53
|
+
// @deps(@external: [react-dom, @ionic/react], @internal: [./App])
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 1.3 — `src/hooks/useAuth.ts` — Sin anotaciones OPL
|
|
57
|
+
**Archivo:** `src/hooks/useAuth.ts` (98 líneas)
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// @use(kind, contract, limit, deps)
|
|
61
|
+
// @kind(hook)
|
|
62
|
+
// @contract(in: void -> out: UseAuthReturn)
|
|
63
|
+
// @limit(lines: 100)
|
|
64
|
+
// @deps(@external: [react, sonner, @supabase/supabase-js], @internal: [../lib/supabase])
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 1.4 — `src/hooks/useAppData.ts` — Sin anotaciones OPL
|
|
68
|
+
**Archivo:** `src/hooks/useAppData.ts` (199 líneas)
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
// @use(kind, contract, limit, deps)
|
|
72
|
+
// @kind(hook)
|
|
73
|
+
// @contract(in: void -> out: UseAppDataReturn)
|
|
74
|
+
// @limit(lines: 200, params: 0)
|
|
75
|
+
// @deps(@external: [react, sonner, @supabase/supabase-js], @internal: [
|
|
76
|
+
// ../lib/supabase, ../lib/cache, ../utils/mappers, ../types
|
|
77
|
+
// ])
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 1.5 — `src/hooks/useOrders.ts` — Sin anotaciones OPL
|
|
81
|
+
**Archivo:** `src/hooks/useOrders.ts` (97 líneas)
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
// @use(kind, contract, limit, deps)
|
|
85
|
+
// @kind(hook)
|
|
86
|
+
// @contract(in: UseOrdersOptions -> out: UseOrdersReturn)
|
|
87
|
+
// @limit(lines: 100)
|
|
88
|
+
// @deps(@external: [react, sonner, @supabase/supabase-js], @internal: [../lib/supabase, ../types])
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 1.6 — `src/hooks/useProducts.ts` — Sin anotaciones OPL
|
|
92
|
+
**Archivo:** `src/hooks/useProducts.ts` (256 líneas)
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// @use(kind, contract, limit, deps)
|
|
96
|
+
// @kind(hook)
|
|
97
|
+
// @contract(in: UseProductsOptions -> out: UseProductsReturn)
|
|
98
|
+
// @limit(lines: 260, params: 1)
|
|
99
|
+
// @deps(@external: [react, sonner, @supabase/supabase-js], @internal: [
|
|
100
|
+
// ../lib/supabase, ../lib/cache, ../types/product, ../types
|
|
101
|
+
// ])
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### 1.7 — `src/hooks/useOffers.ts` — Sin anotaciones OPL
|
|
105
|
+
**Archivo:** `src/hooks/useOffers.ts` (60 líneas)
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
// @use(kind, contract, limit, deps)
|
|
109
|
+
// @kind(hook)
|
|
110
|
+
// @contract(in: UseOffersOptions -> out: UseOffersReturn)
|
|
111
|
+
// @limit(lines: 60)
|
|
112
|
+
// @deps(@external: [react, sonner, @supabase/supabase-js], @internal: [../lib/supabase, ../lib/cache, ../types])
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 1.8 — `src/hooks/useRealtimeSync.ts` — Sin anotaciones OPL
|
|
116
|
+
**Archivo:** `src/hooks/useRealtimeSync.ts` (102 líneas)
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
// @use(kind, contract, limit, deps)
|
|
120
|
+
// @kind(hook)
|
|
121
|
+
// @contract(in: UseRealtimeSyncOptions -> out: void)
|
|
122
|
+
// @limit(lines: 105)
|
|
123
|
+
// @deps(@external: [react, sonner, @supabase/supabase-js], @internal: [
|
|
124
|
+
// ../lib/supabase, ../types, ../types/product, ../utils/mappers
|
|
125
|
+
// ])
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### 1.9 — `src/hooks/useMetrics.ts` — Sin anotaciones OPL
|
|
129
|
+
**Archivo:** `src/hooks/useMetrics.ts` (154 líneas)
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
// @use(kind, contract, limit, deps)
|
|
133
|
+
// @kind(hook)
|
|
134
|
+
// @contract(in: orders: Order[], products: Product[], reviews: any[], userMetrics -> out: { metrics, isCrunching })
|
|
135
|
+
// @limit(lines: 155)
|
|
136
|
+
// @deps(@external: [react], @internal: [../types, ../types/product])
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 1.10 — `src/hooks/useDeliveryZones.ts` — TIENE anotaciones (bien)
|
|
140
|
+
✅ Archivo ya tiene `// @use(kind, contract, limit, deps)` correctamente.
|
|
141
|
+
|
|
142
|
+
### 1.11 — `src/lib/supabase.ts` — Sin anotaciones OPL
|
|
143
|
+
**Archivo:** `src/lib/supabase.ts` (27 líneas)
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
// @use(kind, contract, limit, deps)
|
|
147
|
+
// @kind(lib)
|
|
148
|
+
// @contract(in: void -> out: SupabaseClient)
|
|
149
|
+
// @limit(lines: 30)
|
|
150
|
+
// @deps(@external: [@supabase/supabase-js])
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### 1.12 — `src/lib/cache.ts` — Sin anotaciones OPL
|
|
154
|
+
**Archivo:** `src/lib/cache.ts` (59 líneas)
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
// @use(kind, contract, limit)
|
|
158
|
+
// @kind(service)
|
|
159
|
+
// @contract(in: setCache(key, data, ttl) -> void | getCache(key) -> T | null)
|
|
160
|
+
// @limit(lines: 60)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### 1.13 — `src/lib/queue.ts` — Sin anotaciones OPL
|
|
164
|
+
**Archivo:** `src/lib/queue.ts` (65 líneas)
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
// @use(kind, contract, limit)
|
|
168
|
+
// @kind(service)
|
|
169
|
+
// @contract(in: QueueItem -> out: void)
|
|
170
|
+
// @limit(lines: 65)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### 1.14 — `src/lib/storage.ts` — Sin anotaciones OPL
|
|
174
|
+
**Archivo:** `src/lib/storage.ts` (91 líneas)
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
// @use(kind, contract, limit, deps)
|
|
178
|
+
// @kind(service)
|
|
179
|
+
// @contract(in: files: File[], productId: string -> out: string[])
|
|
180
|
+
// @limit(lines: 95)
|
|
181
|
+
// @deps(@external: [@supabase/supabase-js], @internal: [./supabase])
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 1.15 — `src/lib/sanitizer.ts` — Sin anotaciones OPL
|
|
185
|
+
**Archivo:** `src/lib/sanitizer.ts` (27 líneas)
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
// @use(kind, contract, limit)
|
|
189
|
+
// @kind(util)
|
|
190
|
+
// @contract(in: text: string | undefined | null -> out: string)
|
|
191
|
+
// @limit(lines: 30)
|
|
192
|
+
// @forbidden(any)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### 1.16 — `src/lib/supabaseLogger.ts` — Sin anotaciones OPL
|
|
196
|
+
**Archivo:** `src/lib/supabaseLogger.ts` (172 líneas)
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
// @use(kind, contract, limit, deps)
|
|
200
|
+
// @kind(service)
|
|
201
|
+
// @contract(in: supabaseUrl: string -> out: class SupabaseLogger)
|
|
202
|
+
// @limit(lines: 175)
|
|
203
|
+
// @deps(@external: [crypto])
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## 🔴 CATEGORÍA 2: Componentes sin anotaciones OPL
|
|
209
|
+
|
|
210
|
+
### 2.1 — Componentes de página (todos sin anotaciones)
|
|
211
|
+
|
|
212
|
+
| Archivo | Líneas | Anotaciones |
|
|
213
|
+
|---------|--------|-------------|
|
|
214
|
+
| `src/components/Dashboard.tsx` | 148 | ❌ Faltan |
|
|
215
|
+
| `src/components/Catalog.tsx` | 379 | ❌ Faltan |
|
|
216
|
+
| `src/components/Login.tsx` | 294 | ❌ Faltan |
|
|
217
|
+
| `src/components/Reports.tsx` | 388 | ❌ Faltan |
|
|
218
|
+
| `src/components/Settings.tsx` | 402 | ❌ Faltan |
|
|
219
|
+
| `src/components/BottomNav.tsx` | 57 | ❌ Faltan |
|
|
220
|
+
| `src/components/Notifications.tsx` | 167 | ❌ Faltan |
|
|
221
|
+
| `src/components/OrderDetail.tsx` | 391 | ❌ Faltan |
|
|
222
|
+
| `src/components/OrderCard.tsx` | 92 | ❌ Faltan |
|
|
223
|
+
| `src/components/ProductCard.tsx` | 183 | ❌ Faltan |
|
|
224
|
+
| `src/components/ProductForm.tsx` | 468 | ❌ Faltan (**MUY GRANDE**, debe dividirse) |
|
|
225
|
+
| `src/components/UserManagement.tsx` | 238 | ❌ Faltan |
|
|
226
|
+
| `src/components/ReviewModeration.tsx` | 171 | ❌ Faltan |
|
|
227
|
+
| `src/components/InboxTab.tsx` | 31 | ❌ Faltan |
|
|
228
|
+
| `src/components/ActiveOrdersTab.tsx` | 31 | ❌ Faltan |
|
|
229
|
+
| `src/components/HistoryTab.tsx` | — | ❌ Faltan |
|
|
230
|
+
| `src/components/DeliveryZones.tsx` | 272 | ✅ **TIENE** anotaciones |
|
|
231
|
+
|
|
232
|
+
### 2.2 — Modales (todos sin anotaciones)
|
|
233
|
+
|
|
234
|
+
| Archivo | Líneas | Anotaciones |
|
|
235
|
+
|---------|--------|-------------|
|
|
236
|
+
| `src/components/PinPadModal.tsx` | 176 | ❌ Faltan |
|
|
237
|
+
| `src/components/OfferBuilderModal.tsx` | 202 | ❌ Faltan |
|
|
238
|
+
| `src/components/OfferExecutionModal.tsx` | — | ❌ Faltan |
|
|
239
|
+
| `src/components/QueueModal.tsx` | — | ❌ Faltan |
|
|
240
|
+
| `src/components/StockModal.tsx` | — | ❌ Faltan |
|
|
241
|
+
| `src/components/RejectModal.tsx` | — | ❌ Faltan |
|
|
242
|
+
| `src/components/DelayedConfirmModal.tsx` | — | ❌ Faltan |
|
|
243
|
+
| `src/components/CalendarModal.tsx` | — | ❌ Faltan |
|
|
244
|
+
| `src/components/ChangePasswordModal.tsx` | — | ❌ Faltan |
|
|
245
|
+
| `src/components/CategoryPickerModal.tsx` | — | ❌ Faltan |
|
|
246
|
+
| `src/components/AboutModal.tsx` | — | ❌ Faltan |
|
|
247
|
+
| `src/components/OfflineRestrictionModal.tsx` | — | ❌ Faltan |
|
|
248
|
+
| `src/components/ConnectionDebugModal.tsx` | — | ❌ Faltan (código muerto) |
|
|
249
|
+
| `src/components/DebugPanel.tsx` | — | ❌ Faltan (código muerto) |
|
|
250
|
+
|
|
251
|
+
### 2.3 — Servicios
|
|
252
|
+
|
|
253
|
+
| Archivo | Líneas | Anotaciones |
|
|
254
|
+
|---------|--------|-------------|
|
|
255
|
+
| `src/services/pushNotifications.ts` | 93 | ✅ **TIENE** anotaciones |
|
|
256
|
+
|
|
257
|
+
### 2.4 — Utils
|
|
258
|
+
|
|
259
|
+
| Archivo | Líneas | Anotaciones |
|
|
260
|
+
|---------|--------|-------------|
|
|
261
|
+
| `src/utils/mappers.ts` | 46 | ❌ Faltan |
|
|
262
|
+
| `src/utils/imageUtils.ts` | 73 | ❌ Faltan |
|
|
263
|
+
|
|
264
|
+
### 2.5 — Web/Theme
|
|
265
|
+
|
|
266
|
+
| Archivo | Líneas | Anotaciones |
|
|
267
|
+
|---------|--------|-------------|
|
|
268
|
+
| `src/web/ThemeContext.tsx` | 62 | ❌ Faltan |
|
|
269
|
+
| `src/web/themes.ts` | — | ❌ Faltan |
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## 🟡 CATEGORÍA 3: Errores de diseño y código detectados
|
|
274
|
+
|
|
275
|
+
### 3.1 — 🔴 Overfetching masivo de Supabase
|
|
276
|
+
**Archivo:** `src/hooks/useAppData.ts` (líneas 101-124)
|
|
277
|
+
```typescript
|
|
278
|
+
// ❌ Se traen TODAS las columnas de 5 tablas
|
|
279
|
+
const ordersPromise = supabase.from('orders').select('*, order_items(*)').range(0, 99);
|
|
280
|
+
const productsPromise = supabase.from('products').select('*');
|
|
281
|
+
```
|
|
282
|
+
**Impacto:** $40-80/mes extra en ancho de banda de Supabase.
|
|
283
|
+
|
|
284
|
+
### 3.2 — 🔴 3 canales Realtime en vez de 1
|
|
285
|
+
**Archivo:** `src/hooks/useRealtimeSync.ts` (líneas 28-93)
|
|
286
|
+
```typescript
|
|
287
|
+
// ❌ 3 suscripciones separadas
|
|
288
|
+
supabase.channel('public:orders')...
|
|
289
|
+
supabase.channel('public:offer_reminders')...
|
|
290
|
+
supabase.channel('public:products')...
|
|
291
|
+
```
|
|
292
|
+
**Impacto:** $20-50/mes extra. Debe ser un solo canal.
|
|
293
|
+
|
|
294
|
+
### 3.3 — 🔴 Efecto colateral dentro de setState
|
|
295
|
+
**Archivo:** `src/hooks/useProducts.ts` (líneas 140-191)
|
|
296
|
+
```typescript
|
|
297
|
+
setProducts(prevProducts => {
|
|
298
|
+
// ❌ Llamada a Supabase DENTRO del updater de setState
|
|
299
|
+
supabase.from('products').update(updates).eq('id', productId).then(...)
|
|
300
|
+
return prevProducts.map(...)
|
|
301
|
+
});
|
|
302
|
+
```
|
|
303
|
+
**Impacto:** Anti-pattern grave. Causa doble ejecución en StrictMode.
|
|
304
|
+
|
|
305
|
+
### 3.4 — 🔴 Sin RLS en tablas principales
|
|
306
|
+
**Archivo:** `supabase/migrations/`
|
|
307
|
+
- ✅ `admin_push_tokens` → RLS implementado
|
|
308
|
+
- ✅ `event_logs` → RLS implementado
|
|
309
|
+
- ❌ `orders` → SIN RLS
|
|
310
|
+
- ❌ `products` → SIN RLS
|
|
311
|
+
- ❌ `order_items` → SIN RLS
|
|
312
|
+
- ❌ `product_reviews` → SIN RLS
|
|
313
|
+
- ❌ `offer_reminders` → SIN RLS
|
|
314
|
+
- ❌ `delivery_zones` → SIN RLS
|
|
315
|
+
- ❌ `user_profiles` → SIN RLS
|
|
316
|
+
|
|
317
|
+
**Impacto:** Cualquiera con la anon key puede leer/modificar/borrar datos.
|
|
318
|
+
|
|
319
|
+
### 3.5 — 🔴 `.env` comiteado en Git
|
|
320
|
+
**Archivo:** `.env`
|
|
321
|
+
```env
|
|
322
|
+
VITE_SUPABASE_URL=https://cszlktmntlyqeslilpnu.supabase.co
|
|
323
|
+
VITE_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIs...
|
|
324
|
+
```
|
|
325
|
+
**Impacto:** Credenciales expuestas permanentemente en el historial de Git.
|
|
326
|
+
|
|
327
|
+
### 3.6 — 🔴 PIN secreto hardcodeado
|
|
328
|
+
**Archivo:** `src/components/Login.tsx` (línea 9)
|
|
329
|
+
```typescript
|
|
330
|
+
const CREATION_SECRET_PIN = '738250';
|
|
331
|
+
```
|
|
332
|
+
**Impacto:** Cualquiera que lea el código sabe el PIN para crear cuentas admin.
|
|
333
|
+
|
|
334
|
+
### 3.7 — 🟡 N+1 queries en bulk offer
|
|
335
|
+
**Archivo:** `src/hooks/useProducts.ts` (líneas 221-228)
|
|
336
|
+
```typescript
|
|
337
|
+
// ❌ N updates individuales en vez de 1 batch
|
|
338
|
+
const uparts = updates.map(u => supabase.from('products').update({...}).eq('id', u.id));
|
|
339
|
+
await Promise.all(uparts);
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### 3.8 — 🟡 `useMemo` usado como `useEffect`
|
|
343
|
+
**Archivo:** `src/App.tsx` (líneas 102-106)
|
|
344
|
+
```typescript
|
|
345
|
+
// ❌ useMemo es para valores computados, no efectos
|
|
346
|
+
useMemo(() => { registerPushNotifications(user.id) }, [user?.id]);
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### 3.9 — 🟡 JSON.stringify como dependencias de useEffect
|
|
350
|
+
**Archivo:** `src/hooks/useMetrics.ts` (líneas 144-151)
|
|
351
|
+
```typescript
|
|
352
|
+
// ❌ Serialización completa en cada render
|
|
353
|
+
useEffect(() => { ... }, [JSON.stringify(orders.map(...))]);
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### 3.10 — 🟡 Hook monstruo useAppData
|
|
357
|
+
**Archivo:** `src/hooks/useAppData.ts` (199 líneas)
|
|
358
|
+
**Problema:** Maneja 11 estados + 7 setters de 5 dominios diferentes (products, orders, reviews, reminders, metrics, dbStatus, loading).
|
|
359
|
+
|
|
360
|
+
### 3.11 — 🟡 ProductForm de 468 líneas
|
|
361
|
+
**Archivo:** `src/components/ProductForm.tsx` (468 líneas)
|
|
362
|
+
**Problema:** Supera el límite recomendado de 200-250 líneas. Debe dividirse en subcomponentes.
|
|
363
|
+
|
|
364
|
+
### 3.12 — 🟡 Caché inconsistente
|
|
365
|
+
**Archivo:** `src/hooks/useAppData.ts` (líneas 81-136)
|
|
366
|
+
**Problema:** `setCache` guarda datos crudos de Supabase, pero `getCache` consume datos mapeados. Hay doble transformación.
|
|
367
|
+
|
|
368
|
+
### 3.13 — 🟡 fetchRole llamado dos veces en useAuth
|
|
369
|
+
**Archivo:** `src/hooks/useAuth.ts` (líneas 46-69)
|
|
370
|
+
**Problema:** `getSession()` dispara fetchRole y `onAuthStateChange` también lo dispara para el evento INITIAL_SESSION.
|
|
371
|
+
|
|
372
|
+
### 3.14 — 🟡 handleDeleteUser solo elimina perfil, no auth user
|
|
373
|
+
**Archivo:** `src/components/UserManagement.tsx` (línea 103)
|
|
374
|
+
```typescript
|
|
375
|
+
await supabase.from('user_profiles').delete().eq('id', id);
|
|
376
|
+
// ❌ auth.users sigue existiendo
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### 3.15 — 🟡 Código muerto: ConnectionDebugModal, DebugPanel
|
|
380
|
+
**Archivos:** `src/components/ConnectionDebugModal.tsx`, `src/components/DebugPanel.tsx`
|
|
381
|
+
**Problema:** Componentes que existen pero no se importan ni usan en App.tsx.
|
|
382
|
+
|
|
383
|
+
### 3.16 — 🟡 49 componentes shadcn/ui instalados, muchos sin usar
|
|
384
|
+
**Archivo:** `src/components/ui/` (49 archivos)
|
|
385
|
+
**Problema:** Se instaló shadcn/ui completo pero muchos componentes (carousel, chart, command, context-menu, hover-card, input-otp, menubar, navigation-menu, pagination, resizable, scroll-area, sidebar, slider, toggle-group, tooltip, etc.) no se usan.
|
|
386
|
+
|
|
387
|
+
### 3.17 — 🟡 16 CSS modulares + Tailwind duplicados
|
|
388
|
+
**Archivo:** `src/styles/*.css` (16 archivos)
|
|
389
|
+
**Problema:** Se mezcla Tailwind (`@apply`) con CSS clásico, duplicando estilos y aumentando el bundle.
|
|
390
|
+
|
|
391
|
+
### 3.18 — 🟡 sanitizer.ts rompe caracteres UTF-8
|
|
392
|
+
**Archivo:** `src/lib/sanitizer.ts` (líneas 16-20)
|
|
393
|
+
```typescript
|
|
394
|
+
.replace(/'/g, '’') // ❌ Rompe "Don's Special" → "Don’s Special"
|
|
395
|
+
.replace(/"/g, '”') // ❌ Rompe comillas válidas
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### 3.19 — 🟡 Edge Functions no integradas con frontend
|
|
399
|
+
**Archivos:** `supabase/functions/` (4 funciones)
|
|
400
|
+
**Problema:** `apply-queue` duplica lógica del frontend, `sync-snapshot` nunca se llama, `new-order` solo logea.
|
|
401
|
+
|
|
402
|
+
### 3.20 — 🟡 16 parámetros en useCapacitorLifecycle
|
|
403
|
+
**Archivo:** `src/hooks/useCapacitorLifecycle.ts` (líneas 12-31)
|
|
404
|
+
**Problema:** Demasiadas propiedades en el options object (code smell).
|
|
405
|
+
|
|
406
|
+
### 3.21 — 🟡 Alias @/ configurado pero no usado
|
|
407
|
+
**Archivos:** `vite.config.ts:51`, `tsconfig.json:23-24`
|
|
408
|
+
```json
|
|
409
|
+
"paths": { "@/*": ["./src/*"] }
|
|
410
|
+
```
|
|
411
|
+
**Problema:** Ningún archivo importa con `@/`, todos usan rutas relativas como `../`.
|
|
412
|
+
|
|
413
|
+
### 3.22 — 🟡 edge functions `_shared/` con secretos hardcodeados potenciales
|
|
414
|
+
**Archivo:** `supabase/functions/notify-admin/index.ts`
|
|
415
|
+
**Problema:** Usa `Deno.env.get()` para credenciales de Firebase, pero no hay validación de que existan.
|
|
416
|
+
|
|
417
|
+
### 3.23 — 🟢 Duplicación de scrollbar-hide y hide-scrollbar
|
|
418
|
+
**Archivo:** `src/index.css` (líneas 90-104)
|
|
419
|
+
**Problema:** Dos utility classes con el mismo propósito.
|
|
420
|
+
|
|
421
|
+
### 3.24 — 🟢 Variables CSS --brand-* duplican propósito de Tailwind
|
|
422
|
+
**Archivo:** `src/index.css` (líneas 37-41)
|
|
423
|
+
**Problema:** Las variables CSS solo se usan en los CSS modulares, no en Tailwind.
|
|
424
|
+
|
|
425
|
+
### 3.25 — 🟢 Sin tests unitarios
|
|
426
|
+
**Problema:** No hay ningún archivo de test (`*.test.ts`, `*.spec.ts`). No se puede verificar regresión.
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
430
|
+
## 💰 Impacto económico estimado en Supabase
|
|
431
|
+
|
|
432
|
+
| Problema | Costo/mes | Solución |
|
|
433
|
+
|----------|-----------|----------|
|
|
434
|
+
| Overfetching (SELECT *) | $40-80 | Columnas específicas |
|
|
435
|
+
| 3 canales Realtime | $20-50 | 1 canal |
|
|
436
|
+
| N+1 queries bulk offers | $5-15 | Batch `.in()` |
|
|
437
|
+
| Sin RLS (riesgo de abuso) | $100+ | RLS policies |
|
|
438
|
+
| Sin paginación real | $10-30 | Cursor-based |
|
|
439
|
+
| **Total evitable** | **~$75-175/mes** | |
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## 📋 Checklist de resolución
|
|
444
|
+
|
|
445
|
+
### 🔴 Prioridad 1 — Seguridad (HACER AHORA)
|
|
446
|
+
|
|
447
|
+
- [ ] **P1.1** Agregar `@use()`, `@kind`, `@contract`, `@deps` a TODOS los archivos
|
|
448
|
+
- [ ] **P1.2** Implementar RLS en todas las tablas (orders, products, order_items, product_reviews, offer_reminders, delivery_zones, user_profiles)
|
|
449
|
+
- [ ] **P1.3** Agregar `.env` a `.gitignore` y rotar la anon key
|
|
450
|
+
- [ ] **P1.4** Mover PIN secreto a variable de entorno
|
|
451
|
+
- [ ] **P1.5** Fix: handleToggleSale — sacar efecto colateral de setState
|
|
452
|
+
|
|
453
|
+
### 🔴 Prioridad 2 — Performance (HACER PRONTO)
|
|
454
|
+
|
|
455
|
+
- [ ] **P2.1** Optimizar fetchData con columnas específicas + paginación cursor-based
|
|
456
|
+
- [ ] **P2.2** Reducir de 3 a 1 canal Realtime con filtros por tabla
|
|
457
|
+
- [ ] **P2.3** Cambiar N+1 queries a batch update con `.in()`
|
|
458
|
+
- [ ] **P2.4** Reemplazar `useMemo` por `useEffect` en push notifications
|
|
459
|
+
|
|
460
|
+
### 🟡 Prioridad 3 — Refactor (PLAZO MEDIO)
|
|
461
|
+
|
|
462
|
+
- [ ] **P3.1** Separar `useAppData` en hooks por dominio
|
|
463
|
+
- [ ] **P3.2** Dividir ProductForm en subcomponentes (< 250 líneas c/u)
|
|
464
|
+
- [ ] **P3.3** Unificar CSS: eliminar 16 CSS modulares, usar solo Tailwind
|
|
465
|
+
- [ ] **P3.4** Limpiar shadcn/ui no utilizados
|
|
466
|
+
- [ ] **P3.5** Eliminar código duplicado (compressImage, scrollbar classes)
|
|
467
|
+
- [ ] **P3.6** Eliminar código muerto (ConnectionDebugModal, DebugPanel)
|
|
468
|
+
- [ ] **P3.7** Usar alias @/ en imports
|
|
469
|
+
- [ ] **P3.8** Revisar/fix sanitizer.ts (no romper UTF-8)
|
|
470
|
+
- [ ] **P3.9** Integrar Edge Functions reales con frontend
|
|
471
|
+
- [ ] **P3.10** Agregar test unitarios (mínimo 1 por hook)
|
|
472
|
+
|
|
473
|
+
### 🟢 Prioridad 4 — Deuda técnica menor
|
|
474
|
+
|
|
475
|
+
- [ ] **P4.1** Crear @learn-error por cada bug fijo
|
|
476
|
+
- [ ] **P4.2** Configurar `prompt-lang.json` con strict mode
|
|
477
|
+
- [ ] **P4.3** Establecer dominio en `prompt-lang.json`
|
|
478
|
+
- [ ] **P4.4** Ejecutar `npx openprompt-lang qa-gen` para generar tests
|
|
479
|
+
|
|
480
|
+
---
|
|
481
|
+
|
|
482
|
+
## 📌 Archivos con anotaciones OPL ya existentes (para referencia)
|
|
483
|
+
|
|
484
|
+
✅ Estos archivos ya tienen anotaciones y sirven como modelo:
|
|
485
|
+
|
|
486
|
+
1. `src/hooks/useOfflineQueue.ts`
|
|
487
|
+
2. `src/hooks/useCapacitorLifecycle.ts`
|
|
488
|
+
3. `src/hooks/useDeliveryZones.ts`
|
|
489
|
+
4. `src/services/pushNotifications.ts`
|
|
490
|
+
5. `src/components/DeliveryZones.tsx`
|
|
491
|
+
|
|
492
|
+
---
|
|
493
|
+
|
|
494
|
+
## 🏁 Notas finales
|
|
495
|
+
|
|
496
|
+
Este documento debe actualizarse a medida que se resuelvan los problemas.
|
|
497
|
+
Cada vez que se corrija un error, agregar:
|
|
498
|
+
```typescript
|
|
499
|
+
// @learn-error id=XXX input='...' expected=200 actual=500 fix='...'
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
|
|
504
|
+
*Documento generado durante sesión de auditoría OPL — 2026-05-23*
|
package/package.json
CHANGED
package/src/cli/commands-work.js
CHANGED
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
export function register(program) {
|
|
7
7
|
const workContext = program
|
|
8
8
|
.command("work-context")
|
|
9
|
-
.description(
|
|
9
|
+
.description(
|
|
10
|
+
"Gestionar contexto de trabajo (integrado con 'opl workflow' — start≈delivery, close≈close)"
|
|
11
|
+
)
|
|
10
12
|
|
|
11
13
|
workContext
|
|
12
14
|
.command("init")
|
|
@@ -15,7 +15,8 @@ export async function init(options) {
|
|
|
15
15
|
const dryRun = options.dryRun || false
|
|
16
16
|
|
|
17
17
|
const cwd = process.cwd()
|
|
18
|
-
const isInitialized =
|
|
18
|
+
const isInitialized =
|
|
19
|
+
existsSync(join(cwd, "prompt-lang.json")) || existsSync(join(cwd, ".openprompt"))
|
|
19
20
|
|
|
20
21
|
if (interactive && !options.existing && !options.name && !options.preset && !options.stack) {
|
|
21
22
|
console.log(chalk.cyan("\n🧙 openPrompt-Lang — Inicialización\n"))
|
|
@@ -23,7 +24,10 @@ export async function init(options) {
|
|
|
23
24
|
const choices = []
|
|
24
25
|
|
|
25
26
|
if (isInitialized) {
|
|
26
|
-
choices.push({
|
|
27
|
+
choices.push({
|
|
28
|
+
name: chalk.yellow(" Actualizar/Reconstruir la integración (Rebuild)"),
|
|
29
|
+
value: "rebuild",
|
|
30
|
+
})
|
|
27
31
|
choices.push(new inquirer.Separator())
|
|
28
32
|
}
|
|
29
33
|
|
|
@@ -41,7 +45,9 @@ export async function init(options) {
|
|
|
41
45
|
{
|
|
42
46
|
type: "list",
|
|
43
47
|
name: "projectType",
|
|
44
|
-
message: isInitialized
|
|
48
|
+
message: isInitialized
|
|
49
|
+
? "Este proyecto ya tiene OPL. ¿Qué deseas hacer?"
|
|
50
|
+
: "¿Qué tipo de proyecto?",
|
|
45
51
|
choices,
|
|
46
52
|
},
|
|
47
53
|
])
|
|
@@ -137,9 +143,14 @@ export async function init(options) {
|
|
|
137
143
|
// ── Handoff a la IA ──
|
|
138
144
|
console.log(chalk.cyan("\n✨ OPL Init: Estructura base lista."))
|
|
139
145
|
console.log(chalk.yellow("OPL delega ahora la inicialización estratégica a tu Agente IA."))
|
|
140
|
-
console.log(
|
|
141
|
-
|
|
142
|
-
|
|
146
|
+
console.log(
|
|
147
|
+
chalk.white(
|
|
148
|
+
"Copia y pega el siguiente prompt en tu chat con la IA (ej. Cline, Cursor, OpenCode, etc.):\n"
|
|
149
|
+
)
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
console.log(
|
|
153
|
+
chalk.bgGray.white(`
|
|
143
154
|
"Asume el rol de Arquitecto Principal OPL. Acabo de ejecutar opl init para un proyecto NUEVO llamado '${finalName}'.
|
|
144
155
|
|
|
145
156
|
Tu proceso obligatorio es:
|
|
@@ -149,7 +160,8 @@ Tu proceso obligatorio es:
|
|
|
149
160
|
4. Usa 'init_project' y 'scaffold_project' para configurar el proyecto.
|
|
150
161
|
5. Genera los archivos canónicos: AGENTS.md, prompt-lang.json, .openprompt/FRAMEWORK.md.
|
|
151
162
|
6. Confirma explícitamente que el proyecto quedó estabilizado e indícame el siguiente paso operativo."
|
|
152
|
-
`)
|
|
163
|
+
`)
|
|
164
|
+
)
|
|
153
165
|
|
|
154
166
|
return finalBaseDir
|
|
155
167
|
}
|