openprompt-lang 1.2.6 → 1.3.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 +62 -8
- package/docs/EMBEDDINGS.md +214 -0
- package/docs/FRAMEWORK.md +52 -0
- package/docs/ONBOARDING_WORKFLOW.md +151 -0
- package/docs/OPL-ERRORES.md +504 -0
- package/docs/OPL_ACADEMIC_ISSUES.md +158 -0
- package/docs/WEB_SCRAPER_PLAN.md +454 -0
- package/package.json +7 -1
- package/scripts/postinstall.js +37 -0
- package/src/cli/commands-knowledge.js +1 -0
- package/src/cli/commands-opl.js +79 -1
- package/src/cli/commands-work.js +3 -1
- package/src/cli/commands-workflow.js +125 -6
- package/src/commands/init-core.js +188 -12
- package/src/commands/init-existing.js +13 -6
- package/src/commands/init-helpers.js +20 -14
- package/src/commands/knowledge-ops.js +52 -0
- package/src/commands/opl-embeddings.js +556 -0
- package/src/commands/opl-help.js +26 -2
- package/src/commands/opl-search.js +106 -2
- package/src/commands/opl-webscrape.js +390 -0
- 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/epic-cli.js +192 -0
- package/src/commands/workflow/select.js +146 -0
- package/src/commands/workflow/specification/index.js +4 -0
- package/src/commands/workflow/sprint-cli.js +174 -0
- package/src/core/engine/sandbox.js +7 -3
- package/src/core/webscrape/analyzer.js +481 -0
- package/src/core/webscrape/deep-scraper.js +1027 -0
- package/src/core/workflow/epic-manager.js +845 -0
- package/src/core/workflow/gates.js +180 -1
- package/src/core/workflow/selector.js +707 -0
- package/src/embeddings/chunker.js +450 -0
- package/src/embeddings/embedder.js +431 -0
- package/src/embeddings/index-pipeline.js +320 -0
- package/src/embeddings/vector-store.js +505 -0
- 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
|
@@ -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*
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# 🎓 OPL Academic — Bitácora de Problemas
|
|
2
|
+
|
|
3
|
+
> Documento para registrar problemas, fricciones y errores detectados en el sistema de enseñanza (Teaching System) de openPrompt-Lang.
|
|
4
|
+
> Cada entrada documenta: síntoma, causa raíz, impacto, solución propuesta y estado.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 📋 Índice de Problemas
|
|
9
|
+
|
|
10
|
+
| # | Fecha | Título | Severidad | Estado |
|
|
11
|
+
|---|-------|--------|-----------|--------|
|
|
12
|
+
| 1 | 2026-05-24 | Onboarding IA en proyecto existente | 🔴 Alta | Abierto |
|
|
13
|
+
| 2 | 2026-05-24 | `opl rebuild` no detecta OPL automáticamente | 🟡 Media | Abierto |
|
|
14
|
+
| 3 | 2026-05-24 | Falta documento post-init para IA | 🔴 Alta | Abierto |
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 🐛 Problemas Reportados
|
|
19
|
+
|
|
20
|
+
### P-001: Onboarding IA en proyecto existente
|
|
21
|
+
|
|
22
|
+
| Campo | Valor |
|
|
23
|
+
|-------|-------|
|
|
24
|
+
| **Fecha** | 2026-05-24 |
|
|
25
|
+
| **Reportado por** | usuario |
|
|
26
|
+
| **Severidad** | 🔴 Alta |
|
|
27
|
+
| **Módulo** | Academic — Init / Onboarding |
|
|
28
|
+
| **Estado** | 🔴 Abierto |
|
|
29
|
+
|
|
30
|
+
**Síntoma:**
|
|
31
|
+
Al iniciar una sesión con IA en un proyecto existente que ya tiene elementos de OPL, la IA no sabe qué hacer. No hay un punto de entrada claro que le diga "esto ya tiene OPL, aquí está el estado actual, continúa desde aquí".
|
|
32
|
+
|
|
33
|
+
**Causa raíz:**
|
|
34
|
+
No existe un documento de onboarding generado automáticamente que la IA pueda leer al inicio de cada sesión para restaurar contexto.
|
|
35
|
+
|
|
36
|
+
**Impacto:**
|
|
37
|
+
- La IA pierde ~15 minutos regenerando contexto cada sesión
|
|
38
|
+
- Toma decisiones inconsistentes porque no conoce el estado real del proyecto
|
|
39
|
+
- El usuario tiene que re-explicar manualmente lo que ya se hizo
|
|
40
|
+
|
|
41
|
+
**Solución propuesta:**
|
|
42
|
+
- Crear `docs/ONBOARDING_WORKFLOW.md` — documento canónico que la IA lee al iniciar
|
|
43
|
+
- Integrar `opl init` para que genere este documento automáticamente
|
|
44
|
+
- Dos versiones: `INICIAR_NUEVO.md` (proyecto nuevo) e `INICIAR_EXISTENTE.md` (proyecto en curso)
|
|
45
|
+
|
|
46
|
+
**Referencias:**
|
|
47
|
+
- `erroresDeFlujo.md` (línea 2)
|
|
48
|
+
- Sprint embeddings → TICKET-011 (propuesto)
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
### P-002: `opl rebuild` no detecta OPL automáticamente
|
|
53
|
+
|
|
54
|
+
| Campo | Valor |
|
|
55
|
+
|-------|-------|
|
|
56
|
+
| **Fecha** | 2026-05-24 |
|
|
57
|
+
| **Reportado por** | usuario |
|
|
58
|
+
| **Severidad** | 🟡 Media |
|
|
59
|
+
| **Módulo** | CLI — rebuild |
|
|
60
|
+
| **Estado** | 🟡 Abierto |
|
|
61
|
+
|
|
62
|
+
**Síntoma:**
|
|
63
|
+
`opl rebuild` falla o funciona incorrectamente cuando los elementos de OPL no están presentes o no son detectables automáticamente.
|
|
64
|
+
|
|
65
|
+
**Causa raíz:**
|
|
66
|
+
El comando `rebuild` asume cierta estructura pre-existente en lugar de ser autosuficiente.
|
|
67
|
+
|
|
68
|
+
**Solución propuesta:**
|
|
69
|
+
Hacer que `rebuild` funciones en dos modos:
|
|
70
|
+
1. **Con detección**: Si encuentra elementos OPL, los respeta y reconstruye
|
|
71
|
+
2. **Sin detección**: Si no encuentra nada, crea la estructura desde cero con defaults inteligentes
|
|
72
|
+
|
|
73
|
+
**Referencias:**
|
|
74
|
+
- `erroresDeFlujo.md` (línea 4)
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
### P-003: Falta documento post-init para IA
|
|
79
|
+
|
|
80
|
+
| Campo | Valor |
|
|
81
|
+
|-------|-------|
|
|
82
|
+
| **Fecha** | 2026-05-24 |
|
|
83
|
+
| **Reportado por** | usuario |
|
|
84
|
+
| **Severidad** | 🔴 Alta |
|
|
85
|
+
| **Módulo** | CLI — init |
|
|
86
|
+
| **Estado** | 🔴 Abierto |
|
|
87
|
+
|
|
88
|
+
**Síntoma:**
|
|
89
|
+
Después de ejecutar `opl init`, no se genera ningún documento que la IA pueda usar para entender el contexto del proyecto. La IA llega "en frío" a cada sesión.
|
|
90
|
+
|
|
91
|
+
**Causa raíz:**
|
|
92
|
+
`opl init` configura el proyecto (crea prompt-lang.json, AGENTS.md, etc.) pero no genera un punto de entrada específico para la IA que le diga "esto es lo que hay, esto es lo que falta, continúa".
|
|
93
|
+
|
|
94
|
+
**Solución propuesta:**
|
|
95
|
+
Que `opl init` genere automáticamente:
|
|
96
|
+
- `INICIAR_NUEVO.md` si es proyecto nuevo
|
|
97
|
+
- `INICIAR_EXISTENTE.md` si es proyecto existente con OPL
|
|
98
|
+
|
|
99
|
+
Estos documentos deben incluir:
|
|
100
|
+
- Stack detectado
|
|
101
|
+
- Estado de la configuración OPL
|
|
102
|
+
- Próximos pasos recomendados
|
|
103
|
+
- Enlace a `AGENTS.md` y `docs/AI_CONTEXT.md`
|
|
104
|
+
|
|
105
|
+
**Referencias:**
|
|
106
|
+
- `erroresDeFlujo.md` (línea 6)
|
|
107
|
+
- `docs/ONBOARDING_WORKFLOW.md`
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 📊 Estadísticas
|
|
112
|
+
|
|
113
|
+
| Métrica | Valor |
|
|
114
|
+
|---------|-------|
|
|
115
|
+
| Total problemas | 3 |
|
|
116
|
+
| Severidad Alta | 2 |
|
|
117
|
+
| Severidad Media | 1 |
|
|
118
|
+
| Severidad Baja | 0 |
|
|
119
|
+
| Abiertos | 3 |
|
|
120
|
+
| En Progreso | 0 |
|
|
121
|
+
| Resueltos | 0 |
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 📝 Cómo Reportar un Problema Nuevo
|
|
126
|
+
|
|
127
|
+
Usa esta plantilla al añadir una nueva entrada:
|
|
128
|
+
|
|
129
|
+
```markdown
|
|
130
|
+
### P-XXX: Título descriptivo
|
|
131
|
+
|
|
132
|
+
| Campo | Valor |
|
|
133
|
+
|-------|-------|
|
|
134
|
+
| **Fecha** | YYYY-MM-DD |
|
|
135
|
+
| **Reportado por** | — |
|
|
136
|
+
| **Severidad** | 🔴 Alta / 🟡 Media / 🟢 Baja |
|
|
137
|
+
| **Módulo** | — |
|
|
138
|
+
| **Estado** | 🔴 Abierto |
|
|
139
|
+
|
|
140
|
+
**Síntoma:**
|
|
141
|
+
_¿Qué ocurre exactamente?_
|
|
142
|
+
|
|
143
|
+
**Causa raíz:**
|
|
144
|
+
_¿Por qué ocurre?_
|
|
145
|
+
|
|
146
|
+
**Impacto:**
|
|
147
|
+
_¿A quién afecta y cómo?_
|
|
148
|
+
|
|
149
|
+
**Solución propuesta:**
|
|
150
|
+
_¿Cómo se arreglaría?_
|
|
151
|
+
|
|
152
|
+
**Referencias:**
|
|
153
|
+
- _enlaces a código, docs, commits_
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
*Última actualización: 2026-05-24*
|