Fase 2: 04_sanitize.py - scrubbing de secretos de skills/agentes/plans (10 secretos unicos, gate en verde)
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
# GFIBER-711 — Tutorial interactivo de My Usage
|
||||
|
||||
## Contexto
|
||||
|
||||
GFIBER-711 ("Tutorial: My Usage") es la tercera subtarea de GFIBER-710 ("Implement
|
||||
additional in-app tutorials") que se aborda, después de GFIBER-702 (Upsell Evaluator,
|
||||
mergeado a `dev`) y GFIBER-712 (Dashboard, actualmente en curso en background vía
|
||||
`agente-gfiber-712-dashboard-tour`, todavía no mergeado). Quedan además GFIBER-713 (Admin)
|
||||
y GFIBER-714 (Leagues) para más adelante.
|
||||
|
||||
A diferencia del Dashboard (solo admin/owner), `/my-metrics` — la ruta real detrás del link
|
||||
"My Usage" del NavBar — es accesible a **todos los roles autenticados** (confirmado: no hay
|
||||
`layout.tsx` propio, solo el gate de autenticación general; el propio código documenta
|
||||
"Accessible to all authenticated roles", con scoping de datos vía RLS por `created_by`/
|
||||
`agent_id`, no por rol).
|
||||
|
||||
El usuario decidió lanzar el agente de GFIBER-711 **en paralelo** con el de GFIBER-712,
|
||||
aceptando el riesgo de un conflicto de merge en los archivos compartidos de infraestructura
|
||||
del tour (ver sección de riesgo más abajo), en vez de esperar a que Dashboard termine primero.
|
||||
|
||||
## Estructura real de la pantalla
|
||||
|
||||
`app/(protected)/my-metrics/page.tsx` (Server Component, `dynamic = "force-dynamic"`)
|
||||
renderiza, en este orden:
|
||||
|
||||
1. Header + `<DateRangeControl>` (línea con `basePath="/my-metrics"`, `activeFilter="mine"`)
|
||||
— **mismo componente compartido** que usa el Dashboard (`components/dashboard/DateRangeControl.tsx`).
|
||||
2. Grid de 5 `<AgentStatCard>` (design system): Interactions, Offers Made, Accepted,
|
||||
Rejected, Conversion Rate.
|
||||
3. `<AdoptionCharts variant="individual">` — también compartido con el Dashboard
|
||||
(`components/dashboard/AdoptionCharts.tsx`), pero el tour de Dashboard (GFIBER-712) **no**
|
||||
lo ancla en su alcance aprobado, así que hoy no hay colisión de anclaje ahí.
|
||||
4. Sección "Sessions" → `<SessionHistoryView showStats={false} detailBasePath="/my-metrics">`
|
||||
(`app/(protected)/upsell-evaluator/_history/SessionHistoryView.tsx`, ya es `'use client'`).
|
||||
5. Estado vacío (sin interacciones aún) — sin anclajes, no bloqueante, igual que el caso
|
||||
análogo en Dashboard.
|
||||
|
||||
Grep exhaustivo confirmó: cero `data-tour` en esta pantalla o sus componentes hoy.
|
||||
|
||||
## Coordinación de naming con GFIBER-712 (componente compartido)
|
||||
|
||||
`DateRangeControl` es usado por ambos tours. Para evitar que el mismo `data-tour` fijo en el
|
||||
componente diga "dashboard-*" cuando también aparece en `/my-metrics`, ya le pedí al agente
|
||||
de GFIBER-712 (vía tmux, en curso) que renombre su anclaje de `dashboard-date-range` a
|
||||
**`date-range-control`** (genérico, por componente, no por página que lo consume). Este plan
|
||||
asume ese nombre ya renombrado y lo usa igual acá. Si por algún motivo el agente de Dashboard
|
||||
no llegó a aplicarlo antes de que el de My Usage lo necesite, el agente de My Usage debe
|
||||
usar `date-range-control` de todos modos (es el nombre correcto a largo plazo) y, si
|
||||
encuentra `dashboard-date-range` en su lugar, renombrarlo él mismo.
|
||||
|
||||
## Reuso de infraestructura
|
||||
|
||||
- **`utils/upsell/tour-storage.ts`** — reusar tal cual, `tourId = "my-usage"` → key
|
||||
`gfiber:tour-seen:my-usage`, independiente de los otros dos tours.
|
||||
- **`utils/upsell/tour-bridge.ts`** — GFIBER-712 lo está refactorizando de singleton a
|
||||
`Map<tourId, fn>` en paralelo, en su propio worktree, todavía sin mergear. **Riesgo de
|
||||
conflicto aceptado por el usuario**: el agente de My Usage va a encontrar la versión
|
||||
singleton vieja en `dev`. Debe hacer el mismo refactor (`Map<string, fn>` keyado por
|
||||
`tourId`) de forma independiente, **en un commit dedicado y aislado** (sin mezclarlo con
|
||||
cambios específicos de My Usage), para que sea lo más fácil posible de reconciliar cuando
|
||||
ambos PRs converjan — el usuario resolverá ese conflicto de merge manualmente más adelante.
|
||||
- **`components/NavBar/TourButton.tsx`** — mismo caso: GFIBER-712 lo está creando (reemplaza
|
||||
a `UpsellTourButton.tsx`) con un mapa `pathname → tourId`. El agente de My Usage debe crear
|
||||
este mismo componente si todavía no existe en su rama (heredada de `dev` sin ese cambio),
|
||||
agregando la entrada `"/my-metrics": "my-usage"` al mapa, también en un commit aislado.
|
||||
- **Patrón de `ProductTour.tsx`** — igual que Dashboard: sin `flow` (no hay máquina de
|
||||
etapas), `TourController` interno + `TourProvider` + `SkipButton`/`nextButton` custom +
|
||||
estilos `--fiber-*`.
|
||||
|
||||
## Anclajes del tour (4 pasos)
|
||||
|
||||
| # | `data-tour` | Elemento real | Contenido del paso |
|
||||
| 1 | `date-range-control` | `<DateRangeControl>` (compartido) | "Filtra tus métricas por rango de fechas." |
|
||||
| 2 | `my-usage-stats` | Grid de 5 `<AgentStatCard>` en `page.tsx` | "Tus estadísticas personales: interacciones, ofertas, aceptadas/rechazadas y tasa de conversión." |
|
||||
| 3 | `adoption-charts` | `<AdoptionCharts variant="individual">` (compartido, sin uso previo por otro tour) | "Tu tendencia de adopción de la herramienta, día a día." |
|
||||
| 4 | `session-history` | `<SessionHistoryView>` | "Revisa tu historial de sesiones — click en cualquier fila para ver el detalle completo." |
|
||||
|
||||
## Cambios a implementar
|
||||
|
||||
- `utils/upsell/tour-bridge.ts` — refactor a `Map<tourId, fn>` (si no llegó ya mergeado desde
|
||||
GFIBER-712 al momento de implementar).
|
||||
- `components/NavBar/TourButton.tsx` — crear (si no existe ya) o extender su mapa con
|
||||
`"/my-metrics": "my-usage"`.
|
||||
- Nuevo `app/(protected)/my-metrics/_flow/ProductTour.tsx` (o ubicación equivalente,
|
||||
`'use client'`): `TOUR_ID = "my-usage"`, 4 steps de la tabla de arriba.
|
||||
- `app/(protected)/my-metrics/page.tsx`: envolver el `return` con `<ProductTour>{...}</ProductTour>`.
|
||||
- `data-tour` en: `components/dashboard/DateRangeControl.tsx` (ya debería tener
|
||||
`date-range-control` si GFIBER-712 aplicó el rename; si no, renombrarlo), el grid de
|
||||
`AgentStatCard` en `page.tsx`, `components/dashboard/AdoptionCharts.tsx`,
|
||||
`app/(protected)/upsell-evaluator/_history/SessionHistoryView.tsx`.
|
||||
|
||||
## Riesgo aceptado
|
||||
|
||||
Conflicto de merge probable en `tour-bridge.ts` y `TourButton.tsx` cuando los PRs de
|
||||
GFIBER-712 y GFIBER-711 converjan (ambos tocan los mismos archivos de infraestructura
|
||||
compartida en paralelo). El usuario ya decidió aceptar este costo a cambio de arrancar ambos
|
||||
tours en paralelo. Mitigación: instruir a ambos agentes a mantener esos cambios de
|
||||
infraestructura en commits aislados y descriptivos, para facilitar un rebase/resolución
|
||||
manual posterior.
|
||||
|
||||
## Verificación end-to-end
|
||||
|
||||
- Con `localStorage` vacío, login con cualquier rol (no solo admin/owner) → el tour se
|
||||
dispara solo en `/my-metrics`.
|
||||
- Recorrer los 4 pasos, incluido el estado con datos reales (no el estado vacío).
|
||||
- Completar/Saltar → `localStorage["gfiber:tour-seen:my-usage"] === "true"`; reload no lo
|
||||
re-dispara.
|
||||
- Botón de reinicio en NavBar (`TourButton`) → en `/my-metrics` relanza el tour de My Usage;
|
||||
en `/dashboard` y `/upsell-evaluator` sigue relanzando el suyo respectivo, sin pisarse.
|
||||
- Probar con un agente sin interacciones aún (estado vacío) → confirmar que no rompe nada.
|
||||
- Confirmar que el tour de Upsell Evaluator y el de Dashboard (si ya está mergeado) siguen
|
||||
funcionando sin regresión tras el refactor de `tour-bridge.ts`/`TourButton.tsx`.
|
||||
Reference in New Issue
Block a user