2026-09-19 — TypeSafe: usos factibles + lab v2 con gate anti-dato-sensible
Contexto: cierre de la sesión signal-only (~/typesafe-sandbox). El OpenAPI real
revela que /v1/systemone soporta 3 tipos de pregunta (noul, score, choice)
y que state admite texto completo. Uso seguro bajo políticas leoninas:
TypeSafe solo ve datos públicos o abstractos; lo sensible se procesa en local.
Contrato corregido (error de la sesión anterior)
state = CONTENIDO a evaluar. questions.*.instructions = la decisión a tomar.
El typesafe-prompt viejo enviaba state: {} — por eso el experimento del HTML
devolvió 0.61 sin sentido: no había contenido que evaluar.
Qué puede cruzar la frontera (y qué no)
| SALE (state允许的) | NUNCA SALE |
|---|---|
| Titulares/resúmenes de noticias publicadas | Nombres de clientes, marcas, proyectos WP |
| Features numéricos ya agregados (z-scores, ratios) | PII: emails, teléfonos, URLs internas |
| Descripción genérica de una idea (sin nombres/cifras) | Corpus ai-sessions/, notas del segundo cerebro |
| Texto sintético de prueba | Credenciales, tokens, contenido del .env |
El gate _ts_gate bloquea el envío si el stdin huele a email/URL/clave/dígitos largos.
Si hay que abstrair: primero Ollama (reescritura genérica en ~30 palabras), luego TypeSafe.
Primitivas (bloque verbatim ya instalado en ~/.zshrc, tras typesafe-prompt)
# ---- TypeSafe lab v2: state + noul/score/choice, con gate anti-dato-sensible ----
# Credenciales: locals dentro de cada funcion, leidas de .env; nunca exportadas al shell.
_ts_creds() {
local env_file="~//typesafe-sandbox/.env"
[[ -f "$env_file" ]] || { echo "ERROR: no existe $env_file" >&2; return 1 }
local u k
u="$(grep '^TYPESAFE_URL=' "$env_file" | head -n1 | cut -d= -f2-)"
k="$(grep '^TYPESAFE_API_KEY=' "$env_file" | head -n1 | cut -d= -f2-)"
[[ -n "$u" && -n "$k" ]] || { echo "ERROR: faltan TYPESAFE_URL o TYPESAFE_API_KEY en .env" >&2; return 1 }
print -r -- "$u"
print -r -- "$k"
}
_ts_gate() {
# Filtro por stdin: huele a email/URL/clave/numero largo -> bloquea el envio
local blob; blob="$(cat)"
if grep -qiE '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}|https?://[a-z0-9]|(api[_-]?key|token|secret|password|passphrase)[^a-z]|([0-9][ -/]?){10,}' <<<"$blob"; then
echo "BLOCKED: el state contiene algo con pinta de dato sensible. Abstrae o localiza antes de enviar." >&2
return 1
fi
print -r -- "$blob"
}
_ts_load() {
# sets globals _TS_URL/_TS_KEY; use inside functions that declare them local
local creds
creds="$(_ts_creds)" || return 1
_TS_URL="${creds%%$'\n'*}"
_TS_KEY="${creds#*$'\n'}"
[[ -n "$_TS_URL" && -n "$_TS_KEY" ]]
}
_ts_post() {
# stdin = payload JSON ya construido
local _TS_URL _TS_KEY payload
_ts_load || return 1
payload="$(cat)"
curl -sS "$_TS_URL" \
-H "Authorization: Bearer $_TS_KEY" \
-H "Content-Type: application/json" \
-d "$payload" | jq '{answers, usage}'
}
typesafe-noul() {
# echo "contenido" | typesafe-noul "¿pregunta si/no?" ["lo que cuenta como si" "lo que cuenta como no"]
local q="$1" t="$2" f="$3"
local state payload
[[ -n "$q" ]] || { echo "usa: typesafe-noul 'pregunta'" >&2; return 1 }
state="$(_ts_gate)" || return 1
[[ -n "$state" ]] || { echo "ERROR: state vacio por stdin" >&2; return 1 }
if [[ -n "$t" ]]; then
payload="$(jq -n --arg s "$state" --arg q "$q" --arg t "$t" --arg f "$f" \
'{state:$s, model:"jev-latest", questions:{a:{type:"noul", instructions:$q, criteria:{true:$t, false:$f}}}}')"
else
payload="$(jq -n --arg s "$state" --arg q "$q" \
'{state:$s, model:"jev-latest", questions:{a:{type:"noul", instructions:$q}}}')"
fi
print -r -- "$payload" | _ts_post
}
typesafe-choice() {
# echo "contenido" | typesafe-choice "instruccion" opcion1 opcion2 ...
local instr="$1"; shift
local state payload crit o
[[ -n "$instr" ]] || { echo "usa: typesafe-choice 'instruccion' opcion1 opcion2 ..." >&2; return 1 }
(( $# )) || { echo "usa: typesafe-choice 'instruccion' opcion1 opcion2 ..." >&2; return 1 }
state="$(_ts_gate)" || return 1
[[ -n "$state" ]] || { echo "ERROR: state vacio por stdin" >&2; return 1 }
crit='{}'
for o in "$@"; do crit="$(jq -c --arg k "$o" '. + {($k): $k}' <<<"$crit")"; done
payload="$(jq -n --arg s "$state" --arg i "$instr" --argjson c "$crit" \
'{state:$s, model:"jev-latest", questions:{a:{type:"choice", instructions:$i, criteria:$c}}}')"
print -r -- "$payload" | _ts_post
}
typesafe-score() {
# echo "contenido" | typesafe-score "instruccion" nivel0 nivel1 nivel2 ...
local instr="$1"; shift
local state payload crit
[[ -n "$instr" ]] || { echo "usa: typesafe-score 'instruccion' nivel0 nivel1 ..." >&2; return 1 }
(( $# )) || { echo "usa: typesafe-score 'instruccion' nivel0 nivel1 ..." >&2; return 1 }
state="$(_ts_gate)" || return 1
[[ -n "$state" ]] || { echo "ERROR: state vacio por stdin" >&2; return 1 }
crit="$(jq -cn '$ARGS.positional' --args "$@")"
payload="$(jq -n --arg s "$state" --arg i "$instr" --argjson c "$crit" \
'{state:$s, model:"jev-latest", questions:{a:{type:"score", instructions:$i, criteria:$c}}}')"
print -r -- "$payload" | _ts_post
}
typesafe-triage() {
# echo "resumen generico de la idea (sin nombres, marcas, cifras)" | typesafe-triage
local state payload
state="$(_ts_gate)" || return 1
[[ -n "$state" ]] || { echo "ERROR: state vacio por stdin" >&2; return 1 }
payload="$(jq -n --arg s "$state" '{
state: $s,
model: "jev-latest",
questions: {
factible: {type:"noul", instructions:"Can one designer-engineer ship a working version in two weekends?"},
novedoso: {type:"noul", instructions:"Is this meaningfully different from tools that already exist?"},
valor: {type:"score", instructions:"Value as portfolio or research work", criteria:["none", "some", "strong", "signature"]},
complejidad: {type:"score", instructions:"Implementation complexity", criteria:["trivial", "moderate", "heavy", "research-grade"]},
datos: {type:"noul", instructions:"Does the data this needs exist locally or as free public data?"}
}}')"
print -r -- "$payload" | _ts_post | jq '.answers | {factible:.factible.noul, novedoso:.novedoso.noul, valor:.valor.score, complejidad:.complejidad.score, datos:.datos.noul}'
}
typesafe-models() {
local _TS_URL _TS_KEY base
_ts_load || return 1
base="${_TS_URL%/v1/systemone}"
curl -sS "$base/v1/models" -H "Authorization: Bearer $_TS_KEY" | jq .
}Recetas de incorporación (verificadas live 2026-09-19)
-
nef-silo — árbitro de pares borde (mejora 8: silos por fuente, no por evento). Titulares públicos → sí cruzan la frontera. Calibrar epsilon del HDBSCAN:
printf 'TITULAR A\nTITULAR B' | typesafe-noul \ "Do these headlines describe the same real-world event?" "same event" "different events"Usar como juez en los pares con similitud coseno cerca del umbral (no para todo el corpus).
-
nef-silo / x-anti-fomo — score de urgencia para filtrar el
home.json:typesafe-score "How urgent is this for a solo researcher?" "can wait" "this week" "today" <<< "$resumen"confidencebaja (<0.4) → revisar humano; el score viene con probabilidades por nivel. -
nef-silo — clasificación de items fuera de silo (ruido HDBSCAN label -1):
typesafe-choice "What topic is this?" "IA" "Seguridad" "Infra" "Datos" "Prensa" <<< "$titulo"(Probado: choice con confidence 1.0 en un titular AI.)
-
Triage de ideas sin filtrar el plan — el patrón completo es:
idea sensible → Ollama: "reescribe en 30 palabras genericas, sin nombres ni cifras" → typesafe-triage → {factible, novedoso, valor, complejidad, datos} → solo las que pasan van a Claude/Qwen para generar artifactTypeSafe decide, el generativo crea, el código ejecuta, el humano gobierna.
-
Salud del silo-engine: noul sobre el log de corrida (“Did this run fail to fetch any source?“) — solo si el log no trae hostnames/creds.
Backlog del gateway (no abrir signal-only hoy; registrar para la v2)
- Registry
question_id→ esquema de pregunta con los 3 tipos (hoy solo noul fijo). - Validar en el gateway que
featuressea solo numérico (ya) + tamaño máx. de state. - Mantener fingerprint SHA-256 del outbound (auditoría sin payload).
Pendientes de seguridad (bloquean uso en serio)
- ROTAR
TYPESAFE_API_KEY— se imprimió en claro dos veces (docker inspect en la sesión previa; fallo de una funcion zsh hoy). Rotar = editar.env; las funciones lab no exportan nada al shell (verificado:NO_DEFINIDA). - Rotar
GATEWAY_TOKEN. docker inspect typesafe-blackboxsolo con--formatselectivo, nunca completo.
Verificación de esta sesión
typesafe-noul/choice/score/triage→ respuestas estructuradas correctas (jev-1.13.0).- Gate: email en el state →
BLOCKEDsin llamada saliente. - No hay
TYPESAFE_*ni_TS_KEYdefinidos en el shell tras usar las funciones.