fix(goals): /rename solo para FleetView + objetivo provisional
- /rename escribe el nombre en FleetView (.rename del goal). NO renombra el titulo de la sesion de Claude Code: el built-in /rename usa estado interno y no re-lee el transcript, asi que un evento ai-title no cambia el prompt bar (comprobado). - objetivo provisional: el primer prompt fija un goal placeholder hasta que haiku genera el definitivo, para que el statusline no quede vacio. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
---
|
||||
description: Renombra esta terminal/Claude en FleetView (no toca el título de la sesión)
|
||||
---
|
||||
rename: $ARGUMENTS
|
||||
@@ -9,8 +9,12 @@ SID="$1"
|
||||
F="$2"
|
||||
PROMPT="$3"
|
||||
|
||||
# Si ya existe objetivo (lo creo otro proceso o el usuario), no pisar.
|
||||
[ -f "$F" ] && exit 0
|
||||
# Si ya existe objetivo DEFINITIVO (usuario manual u otro autogen ya termino), no
|
||||
# pisar. Un archivo PROVISIONAL (.provisional=true) SI se pisa: es el placeholder
|
||||
# (= texto del usuario) que pusimos para que el statusline no quede vacio.
|
||||
if [ -f "$F" ] && [ "$(jq -r '.provisional // false' "$F" 2>/dev/null)" != "true" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
PY="$HOME/fn_registry/python/.venv/bin/python3"
|
||||
ASK="$HOME/fn_registry/python/functions/core/ask_llm.py"
|
||||
@@ -34,14 +38,29 @@ DOD=$(printf '%s' "$JSON" | jq -r '.dod // ""' 2>/dev/null)
|
||||
EMOJIS=$(printf '%s' "$JSON" | jq -r '.emojis // ""' 2>/dev/null)
|
||||
[ -z "$GOAL" ] && exit 0
|
||||
|
||||
# Carrera: si entre tanto se creo el archivo, no pisar.
|
||||
[ -f "$F" ] && exit 0
|
||||
# Carrera: si entre tanto aparecio un objetivo DEFINITIVO (manual), respetarlo.
|
||||
# Si solo esta el provisional, lo pisamos abajo con el definitivo.
|
||||
if [ -f "$F" ] && [ "$(jq -r '.provisional // false' "$F" 2>/dev/null)" != "true" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TMP="${F}.tmp.$$"
|
||||
if jq -n --arg g "$GOAL" --arg d "$DOD" --arg e "$EMOJIS" --arg p "$P" \
|
||||
'{goal:$g, phase:"planificando", history:["planificando"], prompts:[$p]} | (if $d != "" then .dod=$d else . end) | (if $e != "" then .emojis=$e else . end)' > "$TMP" 2>/dev/null; then
|
||||
mv "$TMP" "$F"
|
||||
if [ -f "$F" ]; then
|
||||
# Pisar el provisional: fija goal/dod/emojis definitivos y quita el flag,
|
||||
# preservando phase/history/prompts que el provisional ya hubiera acumulado.
|
||||
if jq --arg g "$GOAL" --arg d "$DOD" --arg e "$EMOJIS" \
|
||||
'del(.provisional) | .goal=$g | (if $d != "" then .dod=$d else . end) | (if $e != "" then .emojis=$e else . end)' \
|
||||
"$F" > "$TMP" 2>/dev/null; then
|
||||
mv "$TMP" "$F"
|
||||
else
|
||||
rm -f "$TMP"
|
||||
fi
|
||||
else
|
||||
rm -f "$TMP"
|
||||
if jq -n --arg g "$GOAL" --arg d "$DOD" --arg e "$EMOJIS" --arg p "$P" \
|
||||
'{goal:$g, phase:"planificando", history:["planificando"], prompts:[$p]} | (if $d != "" then .dod=$d else . end) | (if $e != "" then .emojis=$e else . end)' > "$TMP" 2>/dev/null; then
|
||||
mv "$TMP" "$F"
|
||||
else
|
||||
rm -f "$TMP"
|
||||
fi
|
||||
fi
|
||||
exit 0
|
||||
|
||||
@@ -52,27 +52,26 @@ if [ -n "$GOAL_LINE" ]; then
|
||||
block "🎯 Objetivo fijado: ${NEWGOAL}"
|
||||
fi
|
||||
|
||||
# --- /rename <texto>: guarda el nombre para FleetView (.rename del goal) pero NO
|
||||
# bloquea, para que el comando NATIVO /rename de Claude Code renombre tambien
|
||||
# la sesion (prompt bar + /resume picker). Por eso NO debe existir
|
||||
# ~/.claude/commands/rename.md: competiria con el built-in y lo taparia. ---
|
||||
RENAME_LINE=$(printf '%s' "$PROMPT" | grep -ioE '^[[:space:]]*/rename([[:space:]]+.*)?$' | head -1)
|
||||
# --- /rename <texto> (o rename: <texto> via el command rename.md): pone el nombre
|
||||
# de la terminal en FleetView (.rename del goal) y bloquea el prompt.
|
||||
# NO renombra el titulo de la sesion de Claude Code: el built-in /rename usa
|
||||
# estado interno y NO re-lee el transcript, asi que appendear un evento ai-title
|
||||
# no cambia el prompt bar (comprobado 2026-06-17). El rename queda solo para
|
||||
# FleetView. ---
|
||||
RENAME_LINE=$(printf '%s' "$PROMPT" | grep -ioE '^[[:space:]]*(/rename|rename[[:space:]]*:)[[:space:]]*.*$' | head -1)
|
||||
if [ -n "$RENAME_LINE" ]; then
|
||||
NEWNAME=$(printf '%s' "$RENAME_LINE" | sed -E 's#^[[:space:]]*/rename[[:space:]]*##; s/[[:space:]]+$//')
|
||||
NEWNAME=$(printf '%s' "$RENAME_LINE" | sed -E 's#^[[:space:]]*(/rename|rename[[:space:]]*:)[[:space:]]*##; s/[[:space:]]+$//')
|
||||
case "$NEWNAME" in
|
||||
""|-|clear|none|borrar|quitar|reset)
|
||||
# /rename sin texto: Claude Code auto-genera; borramos el override de FleetView.
|
||||
[ -f "$F" ] && { TMP="${F}.tmp.$$"; jq 'del(.rename)' "$F" > "$TMP" 2>/dev/null && mv "$TMP" "$F"; } ;;
|
||||
*)
|
||||
if [ -f "$F" ]; then
|
||||
TMP="${F}.tmp.$$"; jq --arg n "$NEWNAME" '.rename=$n' "$F" > "$TMP" 2>/dev/null && mv "$TMP" "$F"
|
||||
else
|
||||
TMP="${F}.tmp.$$"; jq -n --arg n "$NEWNAME" '{rename:$n, phase:"planificando", prompts:[]}' > "$TMP" 2>/dev/null && mv "$TMP" "$F"
|
||||
fi ;;
|
||||
[ -f "$F" ] && { TMP="${F}.tmp.$$"; jq 'del(.rename)' "$F" > "$TMP" 2>/dev/null && mv "$TMP" "$F"; }
|
||||
block "🏷️ Nombre de la terminal borrado." ;;
|
||||
esac
|
||||
# NO bloquear: el prompt sigue su curso y el built-in /rename de Claude Code
|
||||
# renombra la sesion. El hook solo capturo el nombre para la lista de FleetView.
|
||||
exit 0
|
||||
if [ -f "$F" ]; then
|
||||
TMP="${F}.tmp.$$"; jq --arg n "$NEWNAME" '.rename=$n' "$F" > "$TMP" 2>/dev/null && mv "$TMP" "$F"
|
||||
else
|
||||
TMP="${F}.tmp.$$"; jq -n --arg n "$NEWNAME" '{rename:$n, phase:"planificando", prompts:[]}' > "$TMP" 2>/dev/null && mv "$TMP" "$F"
|
||||
fi
|
||||
block "🏷️ Renombrado en FleetView: ${NEWNAME}"
|
||||
fi
|
||||
|
||||
# --- dod: <texto> ---
|
||||
@@ -103,7 +102,18 @@ case "$PROMPT_TRIM" in
|
||||
esac
|
||||
|
||||
# --- prompt NORMAL: pasa al agente + acumula para refinar el DoD + estado ---
|
||||
if [ -f "$F" ]; then
|
||||
# Distinguimos tres situaciones por el flag .provisional del goal file:
|
||||
# - no existe el archivo -> primer prompt: ponemos objetivo PROVISIONAL = tu
|
||||
# texto + lanzamos autogen (haiku) que lo definira.
|
||||
# - existe pero .provisional -> autogen aun no termino (o fallo): conservamos el
|
||||
# provisional, acumulamos el prompt y relanzamos
|
||||
# autogen (idempotente, self-healing).
|
||||
# - existe y NO provisional -> objetivo definitivo: acumulamos prompt y solo
|
||||
# refinamos el DoD; el objetivo no se toca.
|
||||
PROV="false"
|
||||
[ -f "$F" ] && PROV=$(jq -r '.provisional // false' "$F" 2>/dev/null)
|
||||
|
||||
if [ -f "$F" ] && [ "$PROV" != "true" ]; then
|
||||
G=$(jq -r '.goal // ""' "$F" 2>/dev/null)
|
||||
P=$(jq -r '.phase // ""' "$F" 2>/dev/null)
|
||||
D=$(jq -r '.dod // ""' "$F" 2>/dev/null)
|
||||
@@ -119,11 +129,22 @@ if [ -f "$F" ]; then
|
||||
fi
|
||||
echo "GOAL-TRACKER: file=$F | goal=\"$G\" dod=\"$D\" phase=\"$P\". El objetivo es fijo (identificativo de la terminal, NO lo cambies). El DoD se ajusta solo con los prompts; la fase la mantienen los hooks (PostToolUse=activo, Stop=reposo) — NO la escribas. Comandos meta del usuario (no los uses tu): objetivo:/dod:/pausa."
|
||||
else
|
||||
# Sin objetivo: autogenerar objetivo + DoD desde el primer prompt sustantivo,
|
||||
# en background (no bloquea). Se omite para prompts triviales (saludos, ok...).
|
||||
# Sin objetivo definitivo todavia. Mostramos de inmediato un objetivo PROVISIONAL
|
||||
# igual a tu propio texto (truncado), para que el statusline no quede vacio
|
||||
# mientras haiku genera el real en background. autogen pisara este provisional
|
||||
# con el definitivo al terminar (su guard respeta .provisional).
|
||||
if [ "${#PROMPT_TRIM}" -ge 12 ]; then
|
||||
TMP="${F}.tmp.$$"
|
||||
if [ -f "$F" ]; then
|
||||
# Ya habia provisional: conserva su goal, solo acumula el prompt.
|
||||
jq --arg p "$PROMPT_TRIM" '.prompts = ((.prompts // []) + [$p])[-12:]' "$F" > "$TMP" 2>/dev/null && mv "$TMP" "$F" || rm -f "$TMP"
|
||||
else
|
||||
PROV_GOAL=$(printf '%s' "$PROMPT_TRIM" | head -c 70)
|
||||
jq -n --arg g "$PROV_GOAL" --arg p "$PROMPT_TRIM" \
|
||||
'{goal:$g, phase:"planificando", history:["planificando"], prompts:[$p], provisional:true}' > "$TMP" 2>/dev/null && mv "$TMP" "$F" || rm -f "$TMP"
|
||||
fi
|
||||
nohup bash "$HOME/.claude/hooks/goal_autogen.sh" "$SID" "$F" "$PROMPT" >/dev/null 2>&1 &
|
||||
fi
|
||||
echo "GOAL-TRACKER: file=$F (sin objetivo aun). Autogenerando objetivo+DoD desde tu prompt en background (haiku). El usuario tambien puede fijarlo con \"objetivo: ...\" / \"dod: ...\"."
|
||||
echo "GOAL-TRACKER: file=$F (objetivo PROVISIONAL = tu texto; generando el objetivo+DoD real con haiku en background). El usuario tambien puede fijarlo con \"objetivo: ...\" / \"dod: ...\"."
|
||||
fi
|
||||
exit 0
|
||||
|
||||
+13
-1
@@ -323,9 +323,21 @@ 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)
|
||||
DOD=$(jq -r '.dod // ""' "$GOAL_FILE" 2>/dev/null)
|
||||
EMOJIS=$(jq -r '.emojis // ""' "$GOAL_FILE" 2>/dev/null)
|
||||
PROVISIONAL=$(jq -r '.provisional // false' "$GOAL_FILE" 2>/dev/null)
|
||||
if [ -n "$GOAL" ]; then
|
||||
GC=$(goal_color "$SESSION_ID")
|
||||
LEFT="${GC}🎯 ${GOAL}${RESET}"
|
||||
# Prefijo del objetivo:
|
||||
# - provisional (= tu propio texto, mientras haiku genera el real) -> ⏳ atenuado.
|
||||
# - los 3 emojis generados (representan la tarea, igual que FleetView).
|
||||
# - fallback al marcador generico de objetivo.
|
||||
if [ "$PROVISIONAL" = "true" ]; then
|
||||
LEFT="${GC}⏳ ${DIM}${GOAL}${RESET}"
|
||||
elif [ -n "$EMOJIS" ]; then
|
||||
LEFT="${GC}${EMOJIS} ${GOAL}${RESET}"
|
||||
else
|
||||
LEFT="${GC}🎯 ${GOAL}${RESET}"
|
||||
fi
|
||||
|
||||
LINE0="${LEFT}"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user