1840402453
El objetivo y el DoD dejan de quedarse congelados en el primer prompt: - goal_tracker acumula cada prompt sustantivo del usuario en .prompts y lanza goal_refine.sh (background, haiku) para mantener objetivo y DoD coherentes con TODO lo pedido (action refine), o dejarlos igual (action same). - goal_refine marca alert=true (action switch) cuando el ultimo prompt introduce una tarea completamente distinta del objetivo: senal de que la terminal mezcla tareas (principio: una terminal = una tarea). No cambia el objetivo, solo avisa. - statusline muestra ⚠️ en rojo antes del objetivo cuando alert=true. - Comando 'recalcular' (recalcula/replantea): fuerza regenerar objetivo+DoD desde los prompts y limpia la alerta (para cuando el cambio de tarea es intencional). - goal_autogen inicializa .prompts con el primer prompt. Coste: 1 haiku/prompt sustantivo en background (ademas del haiku de reposo del Stop), solicitado para mantener la coherencia. No bloquea el turno. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
78 lines
3.6 KiB
Bash
Executable File
78 lines
3.6 KiB
Bash
Executable File
#!/bin/bash
|
|
# Mantiene objetivo+DoD coherentes con los prompts acumulados del usuario y avisa
|
|
# si la terminal empieza a mezclar tareas. Lo lanza goal_tracker.sh en background
|
|
# (no bloquea). Usa ask_llm (haiku, API directa; nunca `claude -p`).
|
|
#
|
|
# Args: <session_id> <goal_json_file> [force]
|
|
# force: regenera siempre objetivo+DoD desde los prompts y limpia la alerta
|
|
# (lo usa el comando "recalcular").
|
|
#
|
|
# Decision normal (sin force): el modelo devuelve
|
|
# {"action":"same|refine|switch","goal":"...","dod":"..."}
|
|
# - same : el objetivo ya describe bien el conjunto -> no se toca nada.
|
|
# - refine : ajusta objetivo/DoD para englobar mejor TODO lo pedido (estable).
|
|
# - switch : el ultimo prompt es una tarea COMPLETAMENTE distinta -> alert=true
|
|
# (una terminal deberia ser una sola tarea). No cambia el objetivo.
|
|
|
|
SID="$1"
|
|
F="$2"
|
|
FORCE="$3"
|
|
|
|
[ -f "$F" ] || exit 0
|
|
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
|
|
|
|
GOAL=$(jq -r '.goal // ""' "$F" 2>/dev/null)
|
|
[ -z "$GOAL" ] && exit 0
|
|
DOD=$(jq -r '.dod // ""' "$F" 2>/dev/null)
|
|
PROMPTS=$(jq -r '(.prompts // []) | to_entries | map("\(.key+1). \(.value)") | join("\n")' "$F" 2>/dev/null)
|
|
[ -z "$PROMPTS" ] && exit 0
|
|
|
|
if [ "$FORCE" = "force" ]; then
|
|
SYS="Regenera el OBJETIVO y el DoD de una terminal de trabajo a partir de la lista de prompts del usuario, sintetizando lo que se esta haciendo realmente. Responde SOLO JSON en una linea, sin markdown: {\"action\":\"refine\",\"goal\":\"...\",\"dod\":\"...\"}. goal: maximo 9 palabras en espanol. dod: condicion concreta de terminado, maximo 9 palabras en espanol."
|
|
else
|
|
SYS="Mantienes coherentes el OBJETIVO y el DoD de una terminal de trabajo segun los prompts del usuario. Principio: una terminal = una sola tarea. Analiza si el conjunto de prompts sigue describiendo UNA tarea coherente. Responde SOLO JSON en una linea, sin markdown: {\"action\":\"same|refine|switch\",\"goal\":\"...\",\"dod\":\"...\"}. action=same: el objetivo actual ya describe bien el conjunto (deja goal y dod vacios, no se cambia nada). action=refine: conviene ajustar objetivo/DoD para englobar mejor TODO lo pedido, manteniendolo estable y breve (goal y dod max 9 palabras cada uno, en espanol). action=switch: el ULTIMO prompt introduce una tarea COMPLETAMENTE distinta y no relacionada con el objetivo actual (la terminal esta mezclando tareas); deja goal y dod vacios. Se conservador con 'switch': uselo solo ante un cambio claro de tema, no por matices o sub-tareas del mismo objetivo."
|
|
fi
|
|
|
|
PROMPT="OBJETIVO ACTUAL: ${GOAL}
|
|
DoD ACTUAL: ${DOD}
|
|
|
|
PROMPTS DEL USUARIO (orden cronologico):
|
|
${PROMPTS}
|
|
|
|
Responde el JSON:"
|
|
|
|
RAW=$("$PY" "$ASK" --system "$SYS" "$PROMPT" 2>/dev/null)
|
|
[ -z "$RAW" ] && exit 0
|
|
JSON=$(printf '%s' "$RAW" | tr '\n' ' ' | grep -o '{[^{}]*}' | head -1)
|
|
[ -z "$JSON" ] && exit 0
|
|
|
|
ACTION=$(printf '%s' "$JSON" | jq -r '.action // ""' 2>/dev/null)
|
|
NG=$(printf '%s' "$JSON" | jq -r '.goal // ""' 2>/dev/null)
|
|
ND=$(printf '%s' "$JSON" | jq -r '.dod // ""' 2>/dev/null)
|
|
|
|
case "$ACTION" in
|
|
refine)
|
|
TMP="${F}.tmp.$$"
|
|
if jq --arg g "$NG" --arg d "$ND" '
|
|
(if $g != "" then .goal=$g else . end)
|
|
| (if $d != "" then .dod=$d else . end)
|
|
| .alert=false
|
|
' "$F" > "$TMP" 2>/dev/null; then
|
|
mv "$TMP" "$F"
|
|
else
|
|
rm -f "$TMP"
|
|
fi
|
|
;;
|
|
switch)
|
|
TMP="${F}.tmp.$$"
|
|
if jq '.alert=true' "$F" > "$TMP" 2>/dev/null; then mv "$TMP" "$F"; else rm -f "$TMP"; fi
|
|
;;
|
|
*)
|
|
: # same / desconocido -> no tocar
|
|
;;
|
|
esac
|
|
exit 0
|