feat(statusline): estado 'preguntando', DoD junto al objetivo y comando pausa
- Nuevo estado de reposo 'preguntando' (❓ esperando respuesta), distinto de pendiente_revision: lo usa el Stop worker cuando la respuesta termina con preguntas concretas al usuario en vez de dejar un resultado para revisar. - DoD corto opcional junto al objetivo: se fija con "dod: <texto>" ("dod: clear" lo borra) y se muestra atenuado con 🏁 tras el objetivo. Re-fijar el objetivo preserva el DoD existente. - Comando "pausa" (prompt) marca la fase en en_pausa. Es la alternativa manual a Ctrl-C: Claude Code no dispara ningun hook al interrumpir un turno (el Stop hook solo corre en finalizacion normal; feature pedido, sin implementar), asi que no es posible detectar la interrupcion automaticamente. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,14 +1,17 @@
|
||||
#!/bin/bash
|
||||
# UserPromptSubmit hook del sistema de objetivo+fase por terminal.
|
||||
#
|
||||
# Dos funciones:
|
||||
# 1) Si tu prompt empieza por "objetivo:" (o "meta:" / "goal:"), fija el objetivo
|
||||
# de esta terminal leyendolo DIRECTAMENTE de tu prompt, sin intervencion del
|
||||
# modelo. "objetivo: clear" (o -, none, borrar, quitar, reset) lo elimina.
|
||||
# 2) En cualquier otro caso, inyecta el estado actual (goal+phase) como contexto
|
||||
# para que el modelo sepa donde esta el archivo y que objetivo hay vigente.
|
||||
# Comandos que lee directamente de tu prompt (sin intervencion del modelo):
|
||||
# objetivo: <texto> fija el objetivo de la terminal (meta:/goal: equivalen).
|
||||
# objetivo: clear lo borra (tambien -, none, borrar, quitar, reset).
|
||||
# dod: <texto> fija un Definition of Done corto (se muestra junto al objetivo).
|
||||
# dod: clear lo borra.
|
||||
# pausa marca la fase en en_pausa. Util tras interrumpir con Ctrl-C,
|
||||
# que en Claude Code no dispara ningun hook (no hay forma de
|
||||
# detectar la interrupcion automaticamente).
|
||||
# En cualquier otro caso, inyecta el estado actual como contexto para el modelo.
|
||||
#
|
||||
# La FASE no la toca este hook: la mantiene el Stop hook (goal_phase_eval.sh).
|
||||
# La FASE la mantienen los hooks de fase: PostToolUse (activo) y Stop (reposo).
|
||||
|
||||
INPUT=$(cat)
|
||||
SID=$(printf '%s' "$INPUT" | jq -r '.session_id // empty' 2>/dev/null)
|
||||
@@ -16,41 +19,72 @@ SID=$(printf '%s' "$INPUT" | jq -r '.session_id // empty' 2>/dev/null)
|
||||
|
||||
F="$HOME/.claude/goals/${SID}.json"
|
||||
PROMPT=$(printf '%s' "$INPUT" | jq -r '.prompt // ""' 2>/dev/null)
|
||||
PROMPT_TRIM=$(printf '%s' "$PROMPT" | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//')
|
||||
|
||||
# 1) Fijar/limpiar el objetivo leyendo el prompt del usuario.
|
||||
# --- objetivo: <texto> (preserva el DoD si ya existia) ---
|
||||
GOAL_LINE=$(printf '%s' "$PROMPT" | grep -ioE '^[[:space:]]*(objetivo|meta|goal)[[:space:]]*:[[:space:]]*.+' | head -1)
|
||||
if [ -n "$GOAL_LINE" ]; then
|
||||
NEWGOAL=$(printf '%s' "$GOAL_LINE" | sed -E 's/^[^:]*:[[:space:]]*//; s/[[:space:]]+$//')
|
||||
case "$NEWGOAL" in
|
||||
-|clear|none|borrar|quitar|reset)
|
||||
rm -f "$F"
|
||||
echo "GOAL-TRACKER: objetivo de esta terminal borrado. El statusline deja de mostrar la linea de objetivo."
|
||||
exit 0
|
||||
;;
|
||||
echo "GOAL-TRACKER: objetivo de esta terminal borrado."
|
||||
exit 0 ;;
|
||||
esac
|
||||
if [ -f "$F" ]; then
|
||||
PH=$(jq -r '.phase // "planificando"' "$F" 2>/dev/null)
|
||||
DD=$(jq -r '.dod // ""' "$F" 2>/dev/null)
|
||||
else
|
||||
PH="planificando"
|
||||
PH="planificando"; DD=""
|
||||
fi
|
||||
TMP="${F}.tmp.$$"
|
||||
if jq -n --arg g "$NEWGOAL" --arg p "$PH" '{goal:$g, phase:$p}' > "$TMP" 2>/dev/null; then
|
||||
if jq -n --arg g "$NEWGOAL" --arg p "$PH" --arg d "$DD" \
|
||||
'{goal:$g, phase:$p} | if $d != "" then .dod=$d else . end' > "$TMP" 2>/dev/null; then
|
||||
mv "$TMP" "$F"
|
||||
else
|
||||
rm -f "$TMP"
|
||||
fi
|
||||
echo "GOAL-TRACKER: objetivo fijado desde tu prompt -> \"$NEWGOAL\" (phase=$PH). El statusline ya lo muestra; la fase la mantiene el Stop hook automaticamente."
|
||||
echo "GOAL-TRACKER: objetivo fijado desde tu prompt -> \"$NEWGOAL\"."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 2) Informativo: estado actual para el modelo.
|
||||
# La fase la mantienen los hooks automaticamente: PostToolUse marca el estado
|
||||
# ACTIVO segun las herramientas usadas; el Stop hook resuelve el REPOSO con haiku.
|
||||
# --- dod: <texto> ---
|
||||
DOD_LINE=$(printf '%s' "$PROMPT" | grep -ioE '^[[:space:]]*dod[[:space:]]*:[[:space:]]*.+' | head -1)
|
||||
if [ -n "$DOD_LINE" ]; then
|
||||
NEWDOD=$(printf '%s' "$DOD_LINE" | sed -E 's/^[^:]*:[[:space:]]*//; s/[[:space:]]+$//')
|
||||
[ -f "$F" ] || { echo "GOAL-TRACKER: fija primero un objetivo (\"objetivo: ...\") antes del DoD."; exit 0; }
|
||||
case "$NEWDOD" in
|
||||
-|clear|none|borrar|quitar|reset)
|
||||
TMP="${F}.tmp.$$"
|
||||
jq 'del(.dod)' "$F" > "$TMP" 2>/dev/null && mv "$TMP" "$F"
|
||||
echo "GOAL-TRACKER: DoD borrado."
|
||||
exit 0 ;;
|
||||
esac
|
||||
TMP="${F}.tmp.$$"
|
||||
if jq --arg d "$NEWDOD" '.dod=$d' "$F" > "$TMP" 2>/dev/null; then mv "$TMP" "$F"; else rm -f "$TMP"; fi
|
||||
echo "GOAL-TRACKER: DoD fijado -> \"$NEWDOD\"."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- pausa (marca manual; Ctrl-C no dispara hooks en Claude Code) ---
|
||||
case "$PROMPT_TRIM" in
|
||||
pausa|pause|pausar|"en pausa"|/pausa)
|
||||
[ -f "$F" ] || exit 0
|
||||
TMP="${F}.tmp.$$"
|
||||
if jq '.phase="en_pausa" | .history=((.history // [])+["en_pausa"])[-12:]' "$F" > "$TMP" 2>/dev/null; then
|
||||
mv "$TMP" "$F"
|
||||
fi
|
||||
echo "GOAL-TRACKER: fase marcada en_pausa."
|
||||
exit 0 ;;
|
||||
esac
|
||||
|
||||
# --- informativo: estado actual para el modelo ---
|
||||
if [ -f "$F" ]; then
|
||||
G=$(jq -r '.goal // ""' "$F" 2>/dev/null)
|
||||
P=$(jq -r '.phase // ""' "$F" 2>/dev/null)
|
||||
echo "GOAL-TRACKER: file=$F | goal=\"$G\" phase=\"$P\". La fase la mantienen los hooks automaticamente (PostToolUse = activo, Stop = reposo) — NO escribas la fase. El usuario fija el objetivo escribiendo \"objetivo: <texto>\"; si redefine la tarea en lenguaje natural, actualiza \"goal\" en ese JSON."
|
||||
D=$(jq -r '.dod // ""' "$F" 2>/dev/null)
|
||||
echo "GOAL-TRACKER: file=$F | goal=\"$G\" dod=\"$D\" phase=\"$P\". La fase la mantienen los hooks (PostToolUse=activo, Stop=reposo) — NO la escribas. El usuario fija objetivo con \"objetivo: ...\" y un DoD corto con \"dod: ...\"; si redefine la tarea en lenguaje natural, actualiza \"goal\" en ese JSON."
|
||||
else
|
||||
echo "GOAL-TRACKER: file=$F (sin objetivo aun). El usuario fija el objetivo de la terminal escribiendo \"objetivo: <texto>\" (lo captura este hook directo de su prompt). Si describe una tarea clara sin ese prefijo, crea {\"goal\":\"<su objetivo>\",\"phase\":\"planificando\"} leyendo su prompt. Sin objetivo, ignora."
|
||||
echo "GOAL-TRACKER: file=$F (sin objetivo aun). El usuario fija el objetivo con \"objetivo: <texto>\" y opcionalmente un DoD con \"dod: <texto>\". Si describe una tarea clara sin prefijo, crea {\"goal\":\"<su objetivo>\",\"phase\":\"planificando\"} leyendo su prompt. Sin objetivo, ignora."
|
||||
fi
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user