executing-plans
executing-plans
Use when executing an implementation plan in the current session as the implementer yourself — your human partner chose inline execution, or no subagent tool is available
conduct-empirical-wire-captureCaptura HTTP saliente y telemetría de un arnés de CLI en tiempo de ejecución. Cubre la selección del canal de captura (archivo de transcripción vs stderr de verbose-fetch vs proxy saliente vs estado en disco), captura por evento mediante hooks vs captura de sesión de larga duración, formato de salida JSONL para artefactos comparables mediante diff, y la tab…
Independent GitHub snapshot · Automated classification · Original documentation governs
Configure un arnés de captura de tráfico de red reproducible para el HTTP saliente y la telemetría de una herramienta CLI, asignando cada objetivo de observabilidad al canal más barato que lo capture.
Lea esto antes de configurar cualquier captura.
redact-for-public-disclosure (Fase 5 de la guía padre), no por esta skill.No use esta skill para: establecer línea base de versiones (use monitor-binary-version-baselines), sondeo del estado de flags (use probe-feature-flag-state), o preparar artefactos redactados para publicación pública (use redact-for-public-disclosure).
./captures/ — debe estar en .gitignore.Antes de configurar cualquier captura, enumere las preguntas que necesita responder y asigne cada una a un canal de captura. Una fila por objetivo.
| objetivo | observable mediante | bloqueador |
|---|---|---|
| HTTP saliente al endpoint X | stderr de verbose-fetch | el ruido de la TUI contamina la terminal |
| Evento de telemetría Y al actuar el usuario | subproceso impulsado por hook | requiere superficie de hooks del arnés |
| Handshake de refresh de token | proxy HTTP saliente | requiere confianza del certificado |
| Evento de ciclo de vida de tarea programada | captura de sesión de larga duración | alineación de reloj |
| Mutación de configuración local | diff de estado en disco | ninguno — canal más barato |
Canales comunes, del más barato al más caro:
diff entre snapshots es gratis.BUN_CONFIG_VERBOSE_FETCH=curl de bun) enruta cada fetch a stderr. Ruidoso pero captura cada fetch.UserPromptSubmit, Stop, etc.), lance un subproceso corto de captura por evento.Elija el canal más barato que capture el objetivo. Una captura de 3 objetivos que responde a una pregunta específica vale más que una captura de 20 objetivos que no responde a ninguna.
Expected: una tabla de observabilidad con una fila por pregunta, cada una anotada con el canal y los bloqueadores conocidos. Los objetivos sin canal viable se marcan como "fuera de alcance en esta sesión".
On failure: si cada objetivo cae en la columna del proxy, la tabla es demasiado ambiciosa. Recorte a la una o dos preguntas de mayor valor y reconsidere los canales de menor costo para ellas.
La captura de tráfico contamina terminales, deja archivos en lugares inesperados y puede filtrar credenciales a los registros.
mkdir -p captures/$(date -u +%Y-%m-%dT%H-%M-%S)
cd captures/$(date -u +%Y-%m-%dT%H-%M-%S)
echo 'captures/' >> ../../.gitignore
git check-ignore captures/ || echo "WARNING: captures/ not git-ignored"
Confirme que la sesión de captura no es su sesión principal de trabajo — verbose-fetch y el renderizado de TUI se interfieren mutuamente.
Expected: un directorio de captura con marca de tiempo, ignorado por git, separado de su sesión de trabajo.
On failure: si git check-ignore informa que el directorio no está ignorado, corrija .gitignore antes de ejecutar cualquier comando de captura. No proceda con credenciales en riesgo.
Cuando el objetivo es un evento discreto (una invocación de herramienta, el envío de un prompt, la parada de una sesión), use la superficie de hooks del arnés. Lance un subproceso de captura de corta vida por evento; no permanezca en el proceso.
El patrón (ejemplo sintético):
# Hook script, registered with the harness's hook config.
# Invoked once per event; writes one JSONL line; exits.
#!/usr/bin/env bash
set -euo pipefail
TS=$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)
EVENT="${1:-unknown}"
PAYLOAD=$(jq -c --arg ts "$TS" --arg ev "$EVENT" \
'{ts:$ts, source:"hook", target:$ev, payload:.}' < /dev/stdin)
echo "$PAYLOAD" >> "$CAPTURE_DIR/events.jsonl"
Por qué subproceso-por-evento:
Expected: una línea JSONL por cada evento disparado en events.jsonl, cada una como JSON bien formado parseable con jq.
On failure: si jq reporta errores de parseo, el payload contiene caracteres de control sin escapar o datos binarios — canalice a través de jq -R (entrada cruda) y codifique el campo payload en base64 en su lugar.
Cuando el objetivo es una secuencia (handshake multi-turno, ciclo de vida de tarea programada, máquina de estado de reintentos/backoff), un proceso de captura a lo largo de la sesión, con marca de reloj.
# Run the harness with verbose-fetch routed to a tee-d log.
BUN_CONFIG_VERBOSE_FETCH=curl harness-cli run-task 2> >(
while IFS= read -r line; do
printf '%s\t%s\n' "$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)" "$line"
done >> "$CAPTURE_DIR/session.tsv"
)
El prefijo de reloj hace inequívoco el orden cuando varias capturas corren concurrentemente. TSV (separado por tabulaciones) es intencional — sobrevive a shells que manglean el entrecomillado de JSON en stderr.
Convierta TSV a JSONL después de que termine la sesión (Paso 5), no durante.
Expected: un registro TSV con marcas de tiempo monótonamente crecientes, una línea de stderr por fila.
On failure: si las marcas de tiempo retroceden, el arnés está bufferizando stderr — reejecute con stdbuf -oL -eL o el flag equivalente de buffer por línea del empaquetador.
JSONL es el formato del artefacto: un objeto JSON por línea, campos timestamp, source, target, payload. Amigable para diff, filtrable con jq y estable ante recargas del editor.
# Parse the TSV from Step 4 into JSONL.
awk -F'\t' '{
printf "{\"timestamp\":\"%s\",\"source\":\"verbose-fetch\",\"target\":\"%s\",\"payload\":%s}\n",
$1, "session", $2
}' < session.tsv | jq -c . > session.jsonl
Valide que cada línea parsea:
while IFS= read -r line; do
echo "$line" | jq -e . > /dev/null || echo "BAD LINE: $line"
done < session.jsonl
Uso típico de filtros:
# Show only requests to a specific endpoint pattern.
jq -c 'select(.payload | tostring | test("/api/v1/example"))' session.jsonl
# Show timing between consecutive captures.
jq -r '.timestamp' session.jsonl | sort | uniq -c
Expected: cada línea de *.jsonl parsea con jq -e .; sin advertencias BAD LINE.
On failure: si algunas líneas fallan la validación, el TSV fuente tenía tabulaciones incrustadas en el payload — reejecute el Paso 4 con un delimitador distinto o codifique el segundo campo en base64.
Elimine cabeceras de auth, IDs de sesión, tokens bearer y PII antes de escribir a disco. Los archivos events.jsonl y session.jsonl no deben, en su primera escritura, contener ni un solo secreto.
# Stream the raw capture through a redactor before persisting.
redact() {
sed -E \
-e 's/(authorization:[[:space:]]*Bearer[[:space:]]+)[A-Za-z0-9._-]+/\1<REDACTED>/gi' \
-e 's/(x-api-key:[[:space:]]*)[A-Za-z0-9._-]+/\1<REDACTED>/gi' \
-e 's/(cookie:[[:space:]]*)[^;]+/\1<REDACTED>/gi' \
-e 's/("password"[[:space:]]*:[[:space:]]*)"[^"]*"/\1"<REDACTED>"/g' \
-e 's/("token"[[:space:]]*:[[:space:]]*)"[^"]*"/\1"<REDACTED>"/g'
}
cat raw-capture.txt | redact > session.tsv
Después de la captura, verifique que nada se coló:
# Patterns that must not appear in any *.jsonl file.
grep -Ei 'bearer [A-Za-z0-9]{20,}|sk-[A-Za-z0-9]{20,}|ghp_[A-Za-z0-9]{20,}' captures/ \
&& { echo "LEAK DETECTED"; exit 1; } \
|| echo "redaction clean"
El artefacto capturado-luego-redactado siempre filtra algo. El único patrón seguro es redactado-al-capturar. Si descubre un token sin redactar en un artefacto finalizado, trate toda la captura como comprometida — elimínela, rote la credencial y reejecute.
Expected: la verificación LEAK DETECTED sale con 0 (sin coincidencias). grep para prefijos de credenciales conocidas no devuelve nada.
On failure: si la verificación de fugas encuentra un hit, no edite el archivo en su sitio. Borre todo el directorio de captura, extienda la regex del redactor para cubrir la categoría del patrón filtrado y reejecute desde el Paso 3 o 4.
Los códigos de estado HTTP tienen distinto peso semántico en distintos contextos. Clasifique antes de registrar para que los filtros jq aguas abajo operen sobre la intención, no sobre el código bruto.
| Estado observado | Contexto del canal | Clasificación |
|---|---|---|
| 200 / 201 | Cualquiera | éxito |
| 401 en endpoint de refresh de token | Handshake | paso de handshake esperado |
| 401 en endpoint de datos | Tras autenticación | fallo de auth (real) |
| 404 en recurso cargado perezosamente | Primera captura | miss esperado |
| 404 en endpoint documentado | Tras gate de función | ausencia inducida por el gate |
| 429 | Cualquiera | límite de tasa (retroceda; no reintente ajustado) |
| 5xx | Cualquiera | fallo de servidor (registre, no asuma) |
Añada un campo class en el momento de la captura:
jq -c '. + {class: (
if (.payload.status == 401 and (.target | test("token|refresh"))) then "handshake"
elif (.payload.status >= 200 and .payload.status < 300) then "success"
elif (.payload.status == 401) then "auth-fail"
elif (.payload.status == 429) then "rate-limit"
elif (.payload.status >= 500) then "server-fail"
else "other" end)}' session.jsonl > session.classified.jsonl
Un 401 en un canal de refresh de token no es un fallo — es la primera mitad de un handshake. Clasificar mal los pasos de handshake como fallos produce hallazgos falsos positivos que desperdician la atención del revisor.
Expected: cada línea en *.classified.jsonl tiene un campo class con un valor conocido.
On failure: si la clasificación produce muchas entradas other, la tabla anterior está incompleta para este arnés — extiéndala con una fila por cada patrón other recurrente antes de continuar el análisis.
Una ejecución de captura solo es reproducible si las entradas se registran junto a las salidas. Escriba un manifiesto:
cat > capture-manifest.json <<EOF
{
"captured_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"harness_version": "$(harness-cli --version 2>/dev/null || echo unknown)",
"channel": "verbose-fetch",
"question": "Does endpoint X fire on event Y?",
"targets": ["endpoint-X", "event-Y"],
"files": ["session.jsonl", "session.classified.jsonl"],
"redaction_check": "passed"
}
EOF
El manifiesto es lo que hace la captura diff-able contra futuras versiones.
Expected: capture-manifest.json existe, parsea con jq y lista todos los archivos de artefacto del directorio de captura.
On failure: si el arnés no tiene un flag de versión, registre el sha256sum del binario en su lugar. Un binario no identificado produce capturas incomparables.
*.jsonl parsea con jq -e . línea por líneaclass con valor conocidocapture-manifest.json registra la versión del arnés (o sha256), el canal y la preguntamitmproxy: el proxy saliente es el canal más invasivo. Requiere confianza del certificado, se rompe con certificate pinning y contamina el entorno del arnés. Úselo solo cuando los canales en disco, transcripción, verbose-fetch y hooks estén todos bloqueados.capture-manifest.json no es reproducible — no puede hacer diff contra el binario del mes que viene si no sabe qué versión lo produjo.monitor-binary-version-baselines — Fase 1 de la metodología padre; produce la línea base de versión a la que hace referencia el manifiesto de esta skill.probe-feature-flag-state — Fases 2-3; la captura de tráfico es una de sus vías de evidencia, y esta skill enseña la mitad relativa a la captura.instrument-distributed-tracing — comparte la filosofía de JSONL-sobre-reloj; aplicada aquí a un único binario en vez de a una malla de servicios.redact-for-public-disclosure — Fase 5; esta skill solo cubre la redacción en el momento de la captura para uso interno, no la redacción de nivel de publicación necesaria antes de que cualquier captura deje un espacio de trabajo privado.