#!/bin/bash
# Worker del Stop hook: resuelve el estado de REPOSO de la tarea cuando el
# asistente para y cede el control. Clasifica con ask_llm (haiku, API directa;
# nunca `claude -p`, ver regla llm_invocation.md) y lo escribe en el goal JSON
# manteniendo el historial.
#
# El estado ACTIVO (mientras se trabaja: investigando/haciendo/testeando) lo
# marca el hook PostToolUse (goal_phase_active.sh), de forma determinista. Este
# worker SOLO produce estados de reposo: hecho, pendiente_revision, bloqueado,
# en_pausa.
#
# Args: <session_id> <transcript_path> <goal_json>

SID="$1"
TRANSCRIPT="$2"
F="$3"

PY="$HOME/fn_registry/python/.venv/bin/python3"
ASK="$HOME/fn_registry/python/functions/core/ask_llm.py"

[ -x "$PY" ] || exit 0
[ -f "$ASK" ] || exit 0
[ -f "$F" ] || exit 0
[ -f "$TRANSCRIPT" ] || exit 0

GOAL=$(jq -r '.goal // ""' "$F" 2>/dev/null)
[ -z "$GOAL" ] && exit 0
CUR=$(jq -r '.phase // ""' "$F" 2>/dev/null)
DOD=$(jq -r '.dod // ""' "$F" 2>/dev/null)
[ -z "$DOD" ] && DOD="(no definido)"

is_active() {
    case "$1" in
        investigando|planificando|haciendo|testeando|puliendo) return 0 ;;
        *) return 1 ;;
    esac
}

# Una pasada de abajo a arriba sobre el turno actual: ultima respuesta de texto
# del asistente + ultima peticion del usuario + si hubo trabajo (tool_use).
LAST=""
USER_MSG=""
HAS_WORK=0
while IFS= read -r line; do
    t=$(printf '%s' "$line" | jq -r '.type // empty' 2>/dev/null)
    if [ "$t" = "assistant" ]; then
        if [ -z "$LAST" ]; then
            txt=$(printf '%s' "$line" | jq -r '(.message.content // [])[]? | select(.type=="text") | .text' 2>/dev/null)
            [ -n "$txt" ] && LAST="$txt"
        fi
        if printf '%s' "$line" | jq -e '(.message.content // [])[]? | select(.type=="tool_use")' >/dev/null 2>&1; then
            HAS_WORK=1
        fi
    elif [ "$t" = "user" ]; then
        ctype=$(printf '%s' "$line" | jq -r '.message.content | type' 2>/dev/null)
        if [ "$ctype" = "string" ]; then
            USER_MSG=$(printf '%s' "$line" | jq -r '.message.content' 2>/dev/null)
            break
        fi
        if ! printf '%s' "$line" | jq -e '(.message.content // [])[]? | select(.type=="tool_result")' >/dev/null 2>&1; then
            USER_MSG=$(printf '%s' "$line" | jq -r '(.message.content // [])[]? | select(.type=="text") | .text' 2>/dev/null)
            break
        fi
    fi
done < <(tac "$TRANSCRIPT")

# Solo resolver reposo si hubo trabajo este turno o si veniamos de un estado
# activo (paramos tras currar). Charla sobre un reposo previo: no tocar.
if [ "$HAS_WORK" = "0" ] && ! is_active "$CUR"; then
    exit 0
fi

LAST=$(printf '%s' "$LAST" | tail -c 4000)
[ -z "$LAST" ] && exit 0
USER_MSG=$(printf '%s' "$USER_MSG" | tail -c 1500)

SYS="El asistente acaba de PARAR y cede el control al usuario. Clasifica el estado de REPOSO en que queda la tarea. Responde UNA sola palabra, sin nada mas, de: hecho pendiente_revision preguntando bloqueado en_pausa sin_cambio. hecho=el objetivo esta completo y verificado; pendiente_revision=el asistente termino un trabajo y espera que el humano lo revise o apruebe (no hace una pregunta directa); preguntando=el asistente termina formulando una o varias PREGUNTAS concretas al usuario y necesita su respuesta o decision para continuar; bloqueado=no puede avanzar por un error o por falta de informacion/acceso; en_pausa=hizo un avance y espera la siguiente indicacion, sin estar terminado ni preguntar ni bloqueado; sin_cambio=el turno no altera el estado de reposo actual (charla irrelevante). Distingue: si la respuesta acaba con preguntas al usuario es 'preguntando'; si deja un resultado para que lo mire es 'pendiente_revision'. REGLA DEL DoD: se te da el DoD (definition of done) que define cuando la tarea esta TERMINADA. Marca 'hecho' UNICAMENTE si el resultado descrito por el asistente CUMPLE ese DoD de forma clara y verificada; compara punto por punto el resultado contra el DoD. Si el DoD no se cumple del todo, o no esta verificado, NO uses 'hecho': usa 'pendiente_revision' (dejas un resultado para que el humano lo revise) o 'en_pausa' (avance parcial). Si el DoD es '(no definido)', usa tu criterio: 'hecho' solo si el objetivo esta claramente completo y verificado."

PROMPT="OBJETIVO DE LA TAREA: ${GOAL}

DEFINITION OF DONE (DoD) — la tarea esta TERMINADA solo si esto se cumple:
${DOD}

ULTIMA PETICION DEL USUARIO:
${USER_MSG}

ULTIMA RESPUESTA DEL ASISTENTE:
${LAST}

Compara el resultado contra el DoD y responde con una sola palabra de la lista permitida:"

RAW=$("$PY" "$ASK" --model claude-haiku-4-5-20251001 --system "$SYS" "$PROMPT" 2>/dev/null | tr '[:upper:]' '[:lower:]')
[ -z "$RAW" ] && exit 0

case "$RAW" in
    *sin_cambio*|*sincambio*|*ninguna*|*charla*) exit 0 ;;
    *pregunt*|*consulta*|*respuesta*)     PHASE=preguntando ;;
    *pendiente*revis*|*revis*|*aprob*)    PHASE=pendiente_revision ;;
    *bloque*)                             PHASE=bloqueado ;;
    *hecho*|*complet*|*termin*|*done*)    PHASE=hecho ;;
    *pausa*|*pause*|*siguiente*)          PHASE=en_pausa ;;
    # Si por error devuelve un estado activo al parar, lo tratamos como pausa.
    investigando|planificando|haciendo|testeando|puliendo) PHASE=en_pausa ;;
    *) exit 0 ;;
esac

# Escribir la fase + mantener historial (append solo si cambia respecto al
# ultimo; se conservan los ultimos 12 estados).
TMP="${F}.tmp.$$"
if jq --arg p "$PHASE" '
      .phase = $p
    | .history = (
        ( .history // [] ) as $h
        | ( if ($h | length) > 0 and ($h[-1] == $p) then $h else ($h + [$p]) end )
        | .[-12:]
      )
  ' "$F" > "$TMP" 2>/dev/null; then
    mv "$TMP" "$F"
else
    rm -f "$TMP"
fi
exit 0
