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,164 @@
|
||||
---
|
||||
name: docmost-context
|
||||
description: >-
|
||||
Carga el contexto del proyecto actual desde Docmost (MCP) al inicio de una conversación: lista los
|
||||
spaces, identifica cuál corresponde al proyecto del directorio actual, y lee solo las páginas
|
||||
más relevantes (arquitectura, estructura, tecnologías, estilo de código, etc.). Se activa
|
||||
automáticamente vía el hook SessionStart (ver ~/.claude/hooks/docmost-session-start.sh) — no
|
||||
requiere que el usuario la invoque a mano, aunque también responde a "carga el contexto de
|
||||
Docmost", "lee el proyecto en Docmost", "/docmost-context".
|
||||
effort: medium
|
||||
argument-hint: "[nombre del proyecto, si ya se conoce]"
|
||||
---
|
||||
|
||||
# docmost-context — Cargar contexto relevante del proyecto desde Docmost
|
||||
|
||||
Lee solo las páginas más importantes de Docmost para arrancar la conversación con contexto
|
||||
estructural, en lugar de leer todo ciegamente.
|
||||
|
||||
Se dispara automáticamente al inicio de la conversación vía el hook `SessionStart`
|
||||
(`~/.claude/hooks/docmost-session-start.sh`), que inyecta una instrucción con el `PROJECT_NAME` ya
|
||||
detectado. También puede invocarse a mano.
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Determinar el nombre del proyecto
|
||||
- Si vino como argumento (`args`), úsalo directamente.
|
||||
- Si no, detéctalo en este orden de prioridad (igual que `agent-orchestrator`):
|
||||
```bash
|
||||
PROJECT_NAME=$(jq -r '.name // empty' package.json 2>/dev/null)
|
||||
[ -z "$PROJECT_NAME" ] && PROJECT_NAME=$(grep -oP '^\s*name\s*=\s*"\K[^"]+' pyproject.toml 2>/dev/null | head -1)
|
||||
[ -z "$PROJECT_NAME" ] && PROJECT_NAME=$(basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)")
|
||||
```
|
||||
|
||||
### 2. Listar spaces
|
||||
Llama a `mcp__docmost__list_spaces`.
|
||||
|
||||
### 3. Buscar la coincidencia
|
||||
Compara `PROJECT_NAME` contra el `name` y el `slug` de cada space, **normalizando** ambos lados antes de
|
||||
comparar: minúsculas, sin espacios/guiones/guiones bajos, y **sin el scope de npm** si lo tiene (quita el
|
||||
prefijo `@algo/` de nombres tipo `@aleleba/create-react-component-library` → `create-react-component-library`)
|
||||
— los nombres de space no siempre calzan literal con el nombre del repo o del `package.json`
|
||||
(ej. space "Create React SSR App" vs. repo `create-react-ssr-app`, o `@aleleba/create-react-component-library`
|
||||
vs. space "Create React Component Library").
|
||||
|
||||
Si tras esa normalización no hay match exacto, prueba también un match por contención (el nombre
|
||||
normalizado de uno está contenido en el del otro) antes de darte por vencido.
|
||||
|
||||
- **Una sola coincidencia** → úsala directamente, sin confirmar con el usuario.
|
||||
- **Cero coincidencias** → usa `AskUserQuestion` mostrando la lista de spaces disponibles (nombre +
|
||||
descripción) y deja elegir uno existente, o la opción de que ninguno corresponde. Si el usuario dice
|
||||
que ninguno corresponde, no cargues nada y continúa la conversación normalmente — no insistas.
|
||||
- **Varias coincidencias ambiguas** → pregunta igual, mostrando solo los candidatos ambiguos.
|
||||
|
||||
### 4. Dos pasos: puntuar y leer
|
||||
|
||||
Llama a `mcp__docmost__list_pages({spaceId})` para obtener el árbol completo de páginas.
|
||||
No llames a `get_page` todavía. Primero **puntuar** todas las páginas, luego **leer** solo las seleccionadas.
|
||||
|
||||
#### Paso A: Puntuar cada página
|
||||
|
||||
Asigna un score a cada página con esta fórmula:
|
||||
|
||||
```
|
||||
score = keyword_score + depth_score + name_quality + topic_bonus
|
||||
```
|
||||
|
||||
**keyword_score** (2 puntos por cada keyword que coincida con el nombre o ruta de la página):
|
||||
|
||||
| Categoría | Keywords |
|
||||
|---|---|
|
||||
| Arquitectura y estructura | arquitectura, estructura, stack, tecnologías, componentes, layout, routing, routes, endpoints, models, schema, database, base de datos |
|
||||
| Configuración y herramientas | config, configuration, tsconfig, vite.config, next.config, eslint, prettier, biome, tailwind, tailwind.config, dependencies, dependencias |
|
||||
| Convenios y estilo | estilo de código, convenciones, code style, coding conventions, guidelines, guía, style guide |
|
||||
| Onboarding y setup | onboarding, setup, getting started, entorno, environment, variables, entorno, configuración, install, instalación |
|
||||
| Testing | testing, tests, jest, vitest, cypress, playwright, e2e, integration |
|
||||
| Deploy y CI/CD | deploy, deployment, CI/CD, pipeline, github actions, vercel, netlify, docker, docker-compose |
|
||||
| Migración y estado | migración, migrations, roadmap, estado actual, changelog, release |
|
||||
| API y backend | API, endpoint, route, controller, service, middleware |
|
||||
| Genéricos (páginas raíz) | overview, introduction, getting started, readme, documentación, inicio, home |
|
||||
|
||||
**depth_score** (basado en la profundidad en la jerarquía):
|
||||
- 0 niveles (página raíz): **+3**
|
||||
- 1 nivel de profundidad: **+2**
|
||||
- 2 niveles de profundidad: **+1**
|
||||
- 3+ niveles de profundidad: **+0**
|
||||
|
||||
**name_quality** (1 si el nombre es significativo, 0 si no):
|
||||
- **+1** si el nombre no es "Untitled", "Sin título", vacío, o genérico sin contexto
|
||||
- **+0** si el nombre es vacío, "Untitled", o similar
|
||||
|
||||
**topic_bonus** (2 puntos si la página coincide con el tema del usuario, 0 si no):
|
||||
|
||||
Si el mensaje del usuario o el hook mencionan un tema específico, aplica bonus:
|
||||
|
||||
| Tema del usuario | Keywords de bonus |
|
||||
|---|---|
|
||||
| Testing | test, jest, vitest, cypress, playwright, e2e |
|
||||
| Deploy/CI/CD | deploy, CI/CD, pipeline, docker, vercel, github actions |
|
||||
| Database | database, schema, migration, prisma, drizzle, kysely |
|
||||
| UI/Components | component, design system, tailwind, theme, layout |
|
||||
| API/Backend | API, endpoint, route, controller, service |
|
||||
|
||||
El topic_bonus es un **extra** sobre el keyword_score base. No reemplaza las keywords de
|
||||
arquitectura/estructura — se suma a ellas.
|
||||
|
||||
#### Paso B: Reglas de selección
|
||||
|
||||
Clasifica las páginas en tres tiers según el score:
|
||||
|
||||
| Tier | Score | Qué hacer |
|
||||
|---|---|---|
|
||||
| **Crítico** | >= 8 | Leer completo con `get_page` |
|
||||
| **Importante** | 4-7 | Leer título + snippet (primeros 300 caracteres) |
|
||||
| **Nice-to-know** | < 4 | No leer contenido, solo anotar título |
|
||||
|
||||
**Límite de páginas completas:** máximo **5 páginas** se leen en detalle.
|
||||
|
||||
**Regla de selección según el total de páginas del space:**
|
||||
|
||||
| Total páginas | Páginas completas | Snippets | Ignorar |
|
||||
|---|---|---|---|
|
||||
| 0-3 | Todas | 0 | 0 |
|
||||
| 4-10 | Top 3-5 | Resto | 0 |
|
||||
| 11+ | Top 5 | Siguientes 5 | Resto |
|
||||
|
||||
**Lectura parcial con contenido-gated expansion (para tier "Importante"):**
|
||||
|
||||
1. Leer título + primeros 300 caracteres del contenido.
|
||||
2. Evaluar: ¿el snippet contiene información relevante para el tema que el usuario está trabajando?
|
||||
3. Si SÍ → leer la página completa con `get_page`.
|
||||
4. Si NO → descartar, no leer más.
|
||||
|
||||
**Páginas ignoradas:** solo anotar el título en el reporte final. No llamar a `get_page`.
|
||||
|
||||
### 5. Leer solo lo seleccionado
|
||||
|
||||
Para cada página seleccionada:
|
||||
|
||||
- **Tier Crítico** (hasta 5 páginas): llamar a `mcp__docmost__get_page({pageId})` y leer el contenido completo.
|
||||
- **Tier Importante** (lectura parcial): llamar a `get_page`, leer solo título + primeros 300 caracteres.
|
||||
Si el snippet es relevante para el tema del usuario, leer el resto.
|
||||
- **Tier Nice-to-know**: no llamar a `get_page`. Solo usar el título de la lista.
|
||||
|
||||
### 6. Reportar, no transcribir
|
||||
|
||||
Una vez cargado, responde con un mensaje breve (1-2 líneas): qué space se usó y cuántas páginas
|
||||
relevantes se cargaron. No repitas el contenido de las páginas en el chat — ya quedó en tu contexto
|
||||
para usarlo cuando haga falta.
|
||||
|
||||
Ejemplo de reporte:
|
||||
|
||||
```
|
||||
Contexto cargado desde Docmost:
|
||||
- Space: <nombre>
|
||||
- Fase 1 (baseline): <n> páginas (arquitectura, estructura, tecnologías)
|
||||
- Fase 2 (contexto específico): <n> páginas (<temas>)
|
||||
Total: <n> páginas relevantes cargadas.
|
||||
```
|
||||
|
||||
### 7. Una sola vez por conversación
|
||||
|
||||
Ejecuta esto una sola vez, al primer turno disparado por el hook. No lo repitas en turnos posteriores
|
||||
de la misma conversación salvo que el usuario lo pida explícitamente (ej. "recarga el contexto de
|
||||
Docmost").
|
||||
Reference in New Issue
Block a user