diff --git a/.claude/hooks/goal_tracker.sh b/.claude/hooks/goal_tracker.sh index 12b3daf..12af9d3 100755 --- a/.claude/hooks/goal_tracker.sh +++ b/.claude/hooks/goal_tracker.sh @@ -27,8 +27,16 @@ PROMPT_TRIM=$(printf '%s' "$PROMPT" | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$ # Bloquea el prompt (no llega al agente) y muestra al usuario. block() { jq -n --arg r "$1" '{decision:"block", reason:$r}'; exit 0; } +# Los comandos meta (objetivo:/dod:/pausa) solo cuentan en la PRIMERA linea del +# prompt. Sin este recorte, un prompt multilinea que CONTENGA una linea +# "objetivo:"/"dod:" en su interior (p.ej. una de un subagente +# que trae DoD-contratos esbozados, o un mensaje que cita un DoD) se malinterpreta +# como comando meta: se bloquea con decision:block (atrapando la notificacion) y se +# corrompe el .dod del goal con esa linea interior. Anclar a la 1a linea lo evita. +FIRST_LINE=$(printf '%s' "$PROMPT" | head -1) + # --- objetivo: (manual; preserva el DoD si ya existia) --- -GOAL_LINE=$(printf '%s' "$PROMPT" | grep -ioE '^[[:space:]]*(objetivo|meta|goal)[[:space:]]*:[[:space:]]*.+' | head -1) +GOAL_LINE=$(printf '%s' "$FIRST_LINE" | 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 @@ -57,7 +65,7 @@ fi # asi el built-in /rename de Claude Code queda libre para renombrar la sesion. # --- dod: --- -DOD_LINE=$(printf '%s' "$PROMPT" | grep -ioE '^[[:space:]]*dod[[:space:]]*:[[:space:]]*.+' | head -1) +DOD_LINE=$(printf '%s' "$FIRST_LINE" | 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" ] || block "Fija primero un objetivo (\"objetivo: ...\") antes del DoD."