feat(statusline): seguimiento de objetivo + fase por terminal
Cada terminal muestra su objetivo (color estable por session_id) y la fase de
trabajo actual, para distinguir sesiones y saber cuando algo esta hecho.
- statusline.sh: linea 0 con objetivo (izq, color por sesion) + fase (der) con
el separador estandar; 9 fases (investigando, planificando, haciendo,
testeando, puliendo, iterando, pendiente_revision, bloqueado, hecho) con icono,
color y etiqueta. Purga de goal files de sesiones muertas (>7 dias).
- hooks/goal_tracker.sh (UserPromptSubmit): fija el objetivo leyendo el prompt
del usuario ("objetivo: ...", "objetivo: clear" lo borra); si no, informa el
estado actual al modelo.
- hooks/goal_phase_eval.sh (Stop): al terminar el turno lanza el worker en
background, sin bloquear.
- hooks/goal_phase_worker.sh: clasifica la fase con ask_llm (haiku, API directa,
nunca claude -p) usando la peticion del usuario + la ultima respuesta del
asistente. Solo reevalua si el turno tuvo trabajo real (tool_use); en charla
pura no toca la fase ni gasta llamada.
- settings.json: registra los hooks UserPromptSubmit y Stop.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -23,6 +23,11 @@ MODEL=$(echo "$INPUT" | jq -r '.model.display_name // "Unknown"')
|
||||
CONTEXT_PCT=$(echo "$INPUT" | jq -r '.context_window.used_percentage // 0' | xargs printf "%.0f")
|
||||
CONTEXT_TOTAL=$(echo "$INPUT" | jq -r '.context_window.context_window_size // 200000')
|
||||
CURRENT_DIR=$(echo "$INPUT" | jq -r '.workspace.current_dir // "~"' | sed "s|$HOME|~|")
|
||||
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // ""')
|
||||
|
||||
# Purga: borra goal files de sesiones muertas (no tocados en >7 dias). El worker
|
||||
# refresca el mtime en cada respuesta, asi que las sesiones vivas nunca caen.
|
||||
find "$HOME/.claude/goals" -maxdepth 1 -name '*.json' -mtime +7 -delete 2>/dev/null
|
||||
|
||||
# Tokens de entrada y salida (current_usage puede ser null antes del primer API call)
|
||||
INPUT_TOKENS=$(echo "$INPUT" | jq -r '.context_window.current_usage.input_tokens // 0')
|
||||
@@ -91,6 +96,34 @@ if git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
GIT_STATUS=$(echo "$GIT_STATUS" | sed 's/ $//')
|
||||
fi
|
||||
|
||||
# Color estable por sesión (hash del session_id → paleta ANSI 256 legible).
|
||||
# Cada terminal mantiene su color toda su vida; distinto entre terminales.
|
||||
goal_color() {
|
||||
local sid="$1"
|
||||
local palette=(39 45 51 75 81 114 120 156 183 210 215 222 213 159 228)
|
||||
local h
|
||||
h=$(printf '%s' "$sid" | cksum | cut -d' ' -f1)
|
||||
local idx=$(( h % ${#palette[@]} ))
|
||||
printf '\033[1;38;5;%dm' "${palette[$idx]}"
|
||||
}
|
||||
|
||||
# Fase de trabajo → icono | color ANSI | etiqueta visible.
|
||||
# El slug (clave) lo escribe el agente del Stop hook; aqui se mapea a su estilo.
|
||||
phase_style() {
|
||||
case "$1" in
|
||||
investigando) printf '🔎|36|investigando' ;;
|
||||
planificando) printf '📋|34|planificando' ;;
|
||||
haciendo) printf '🔨|33|haciendo' ;;
|
||||
testeando) printf '🧪|35|testeando' ;;
|
||||
puliendo) printf '✨|95|puliendo detalles' ;;
|
||||
iterando) printf '🔁|94|iterando' ;;
|
||||
pendiente_revision) printf '👀|93|pendiente de revisión' ;;
|
||||
bloqueado) printf '⛔|31|bloqueado' ;;
|
||||
hecho) printf '✅|32|hecho' ;;
|
||||
*) printf "•|90|$1" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Función para crear barra de progreso
|
||||
progress_bar() {
|
||||
local pct=$1
|
||||
@@ -251,6 +284,30 @@ fi
|
||||
# 6. Directorio actual
|
||||
LINE2="${LINE2} ${GRAY}│${RESET} ${BLUE}${CURRENT_DIR}${RESET}"
|
||||
|
||||
# ===== LÍNEA 0: Objetivo (izq) + Fase (der) =====
|
||||
# Solo si la sesión tiene archivo de objetivo con goal no vacío.
|
||||
GOAL_FILE="$HOME/.claude/goals/${SESSION_ID}.json"
|
||||
if [ -n "$SESSION_ID" ] && [ -f "$GOAL_FILE" ]; then
|
||||
GOAL=$(jq -r '.goal // ""' "$GOAL_FILE" 2>/dev/null)
|
||||
PHASE=$(jq -r '.phase // ""' "$GOAL_FILE" 2>/dev/null)
|
||||
if [ -n "$GOAL" ]; then
|
||||
GC=$(goal_color "$SESSION_ID")
|
||||
LEFT_PLAIN="🎯 ${GOAL}"
|
||||
LEFT="${GC}${LEFT_PLAIN}${RESET}"
|
||||
|
||||
LINE0="${LEFT}"
|
||||
if [ -n "$PHASE" ]; then
|
||||
PS=$(phase_style "$PHASE")
|
||||
PICON="${PS%%|*}"
|
||||
REST="${PS#*|}"
|
||||
PCOL="${REST%%|*}"
|
||||
PLABEL="${REST#*|}"
|
||||
LINE0="${LINE0} ${GRAY}│${RESET} \033[1;${PCOL}m${PICON} ${PLABEL}${RESET}"
|
||||
fi
|
||||
echo -e "$LINE0"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Imprimir resultado (2 líneas)
|
||||
echo -e "$LINE1"
|
||||
echo -e "$LINE2"
|
||||
|
||||
Reference in New Issue
Block a user