Citando fuentes con fragmentos textuales
Visión general
Cada afirmación citada lleva su prueba incorporada: el pasaje textual, un enlace que salta y resalta ese pasaje, y opcionalmente una captura de pantalla. Los lectores verifican sin hacer clic; al hacer clic, llegan exactamente al texto. Funciona para archivos markdown y para respuestas en chat.
Cada cita debe provenir de la salida de snap.mjs, nunca de la memoria, del resumen de un resultado de búsqueda o de una herramienta de resumen. Los resúmenes de búsqueda y las herramientas tipo WebFetch parafrasean las páginas; solo el script verifica el texto renderizado textualmente.
Verifica afirmaciones, no solo citas. Una cita que coincide demuestra que la página dice eso. No demuestra nada sobre lo que la página no dice. Dos tipos de afirmaciones siempre deben pasar por el script como entradas propias en el lote, incluso cuando solo estás "verificando un borrador":
- Ausencia: antes de escribir que una página no dice, menciona o requiere algo, añade la frase que estaría allí si lo hiciera (p. ej.
Las respuestas con el código de estado 429 NO DEBEN ser almacenadas por una caché.). Solomatch: nonerespalda la ausencia, y entonces escribe "no encontrado en <página>", nunca "la especificación no dice nada sobre X". - Desacuerdo: cuando la memoria, un resumen de búsqueda, un borrador que ya escribiste o los ejemplos de este skill difieren sobre lo que dice una página, añade la frase en disputa. El resultado del script lo resuelve, independientemente de qué lado favorezca. (Cada cita en los ejemplos de este skill fue verificada con el script.)
Configuración (una vez por máquina)
npm install --prefix <directorio-del-skill>/scripts && npx --prefix <directorio-del-skill>/scripts playwright install chromium
<directorio-del-skill> es el directorio que contiene este SKILL.md.
El script
Redacta el documento o la respuesta primero, recopila cada cita, luego verifícalas todas en una sola llamada por lotes:
node <directorio-del-skill>/scripts/snap.mjs --batch - <<'EOF'
[
{"url": "https://www.rfc-editor.org/rfc/rfc6585.html", "quote": "Responses with the 429 status code MUST NOT be stored by a cache."},
{"url": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Retry-After", "quote": "A non-negative decimal integer", "out": "/abs/path/docs/refs/delay.png"}
]
EOF
Un navegador para el lote; las citas de la misma URL comparten una carga de página. Usa rutas absolutas para out. La entrada también puede ser {"defaults": {...}, "cites": [...]} para aplicar opciones de captura de pantalla a cada entrada. La salida del lote es un array JSON en el orden de entrada (el modo individual, snap.mjs "<url>" --quote "...", imprime un objeto). Cada entrada:
| Campo | Uso |
|---|---|
ok / match | exact/loose = textual. fuzzy = tu cita era incorrecta; usa quote_on_page en su lugar y vuelve a verificar que la afirmación sigue siendo válida. none = no está en la página. |
quote_on_page | El texto para poner en el bloque de cita. Nunca tu --quote original. |
fragment_url | El enlace a usar (tiene #:~:text=, resalta en Chrome/Safari/Firefox). |
excerpt | El párrafo circundante, para verificar el contexto (negaciones, salvedades, "excepto cuando…"). ¿Quieres citar más de él? Vuelve a ejecutar con ese pasaje más largo como --quote para que el enlace y la captura coincidan. |
title, section, retrieved | La línea de atribución: [<título> — <sección>](fragment_url) · recuperado <fecha>, o [<título>](fragment_url) cuando falta section. Usa estos campos; no añadas números de sección de memoria. |
occurrences / occurrence | Presente cuando la cita aparece más de una vez. Verifica que excerpt sea el que querías; si no, vuelve a ejecutar con prefix/suffix (las palabras justo antes/después en la página). |
hidden | La cita está en contenido que la página oculta (p. ej. una pestaña inactiva): verificado, pero sin captura de pantalla. |
note | Cualquier otra cosa que valga la pena saber (coincidencia aproximada, sección expandida, fallback de frame). Léelo. |
internal | La página está en una red interna. Su contenido puede ser confidencial; no cites más de lo que la afirmación necesita. |
Salida 0 = todas encontradas, 1 = algunas no encontradas, 2 = algunas con error (PDF, 4xx, muro de inicio de sesión, verificación de bot, tiempo de espera). Espera un lote de seguimiento: pon cada entrada que necesite otra pasada (fallida, aproximada, ocurrencia incorrecta o un pasaje más largo deseado) junto en él.
Opciones de captura de pantalla
Campos opcionales en cualquier entrada (o en defaults). Mapa el wording del usuario; sin wording, déjalos fuera.
| El usuario dice | Campo |
|---|---|
| "capturas ajustadas", "solo la cita" | "frame": "quote" (predeterminado paragraph) |
| "muestra la sección completa" | "frame": "section" (el límite de altura sube automáticamente a 1200) |
| "pantalla completa", "muestra la página alrededor" | "frame": "viewport" |
| "un par de líneas alrededor" | "context": 2 (líneas de texto completas arriba y abajo) |
| "tamaño móvil" | "width": 390 (predeterminado 1100) |
| "mantenlas cortas" | "max_height": 150 (predeterminado 500; el recorte se centra en la cita) |
| "resaltar en amarillo", "sin resaltar" | "highlight": "#fff3a0" / "none" |
| "modo oscuro" | "theme": "dark" (solo sitios con tema oscuro; note dice lo contrario) |
| "imágenes más pequeñas" | "scale": 1 (predeterminado 2) |
Estas solo dan forma a las capturas de pantalla. ¿Quieres contexto en el texto mismo (o sin capturas)? Cita un pasaje más largo tomado de excerpt, vuelve a ejecutar en el lote de seguimiento. Las citas en celdas de tabla enmarcan automáticamente la fila más la fila del encabezado. Cada opción, con su captura, está en examples/README.md del repositorio.
Formato de salida
Elige el formato según dónde vaya el texto.
Archivo Markdown: afirmación en la prosa, nota al pie con la prueba:
Los clientes no deberían almacenar en caché las respuestas de límite de velocidad.[^429-cache]
[^429-cache]: > Las respuestas con el código de estado 429 NO DEBEN ser almacenadas por una caché.
>
> — [Códigos de Estado HTTP Adicionales — 4. 429 Demasiadas Solicitudes](https://www.rfc-editor.org/rfc/rfc6585.html#:~:text=Responses%20with%20the%20429%20status%20code%20MUST%20NOT%20be%20stored%20by%20a%20cache.) · recuperado 2026-11-08
>
> 
- Los IDs de las notas al pie son slugs descriptivos cortos, no números. Reutiliza el mismo
[^id]cuando el mismo pasaje respalde dos afirmaciones. - Guarda las capturas de pantalla en
refs/junto al archivo markdown; nombre del archivo = slug de la nota al pie. Elimina los PNG de las citas que hayas descartado.
Respuesta de chat: sin notas al pie (los terminales las muestran como texto sin formato). Pon la prueba directamente debajo de la afirmación que respalda:
Los clientes no deberían almacenar en caché las respuestas de límite de velocidad:
> Las respuestas con el código de estado 429 NO DEBEN ser almacenadas por una caché.
> — [Códigos de Estado HTTP Adicionales — 4. 429 Demasiadas Solicitudes](https://www.rfc-editor.org/rfc/rfc6585.html#:~:text=Responses%20with%20the%20429%20status%20code%20MUST%20NOT%20be%20stored%20by%20a%20cache.)
- Sin fecha
retrieved(la respuesta es la recuperación). - Guarda las capturas de chat en el directorio temporal del sistema (p. ej.
$TMPDIR/receipts/<slug>.png), nunca en el proyecto del usuario. Si tu anfitrión tiene una herramienta para mostrar un archivo o imagen al usuario, muestra cada captura con ella; de lo contrario, da la ruta absoluta completa de cada una en su propia línea después de la cita. - Sin capturas solicitadas → termina la respuesta con una oferta de una línea, p. ej. "¿Quieres capturas de pantalla de estos pasajes?"
Ambos:
- Tu propio razonamiento o recomendación no lleva cita; di que es tu razonamiento (o del equipo), no de la fuente. Una afirmación factual sobre el mundo exterior (cómo se comportan las bibliotecas, navegadores o estándares) necesita una cita o debe redactarse como una expectativa.
- Las capturas de pantalla son opt-in: son baratas (aproximadamente medio segundo por página) pero añaden archivos de imagen que el usuario debe conservar o eliminar. Añade
"out"solo cuando el usuario solicite capturas, o, en un archivo markdown, la evidencia sea visual (una tabla, figura, diseño de código) donde el texto solo pierde significado. Incluye una imagen o ruta solo para las entradas que tenganscreenshoten el resultado. - Cita el pasaje más corto que respalde completamente la afirmación (una frase es típico).
Cuando el script falla
| Resultado | Qué hacer |
|---|---|
match: fuzzy | Usa quote_on_page (la captura de pantalla ya lo resalta). Si ya no respalda tu afirmación, cambia la afirmación. |
match: none | Busca en la página de otra manera (pasaje diferente, URL de sección diferente). Sigue sin aparecer → descarta la afirmación o márcala como **NO VERIFICADO:** con un enlace simple. Nunca presentes una cita no verificada como bloque de cita. |
ok: false + error (PDF, muro de inicio de sesión, verificación de bot, 403) | Enlace simple + **NO VERIFICADO (no se pudo cargar: <error>)**. No fabriques la cita de memoria o WebFetch. |
occurrences > 1 y excerpt es el incorrecto | Vuelve a ejecutar con "prefix" o "suffix" establecido en las palabras vecinas de la que querías. |
Errores comunes
- Citar lo que la página "básicamente dice" → los bloques de cita son solo textuales; la paráfrasis va en la prosa.
- Usar un ancla de sección (
#section-4) en lugar defragment_url→ el lector aún tiene que buscar. - Citar un pasaje cuyo
excerptcontradice la afirmación (p. ej., la siguiente frase dice "esto no se aplica a…"). - Ejecutar WebFetch para "verificar" → resume; no puede confirmar texto textual. Usa el script.
- Confiar en el resumen de respuesta de una herramienta de búsqueda sobre lo que una página dice u omite → parafrasea como WebFetch, y a menudo sitúa mal qué sección dice qué. Pon la frase en disputa a través del script.
- "Verificar" un borrador comprobando solo las citas que ya contiene → sus afirmaciones de ausencia y afirmaciones en disputa quedan sin probar, por lo que una respuesta falsa parece completamente verificada.
