From d4640a06609f8f636b2d5d61947a28dd454ef9e2 Mon Sep 17 00:00:00 2001 From: integrador Date: Sun, 21 Jun 2026 14:59:15 +0200 Subject: [PATCH] fix(goal): poblar goal de ejecutores spawneados (statusline/FleetView sin objetivo) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit spawn_fleet_agent pre-crea ~/.claude/goals/.json con solo {role, parent_orchestrator} antes del primer prompt. goal_tracker.sh usaba 'el archivo existe' como proxy de 'objetivo definitivo', así que para esos ejecutores nunca lanzaba goal_autogen: el goal quedaba vacío para siempre y el statusline (LINE0) y FleetView mostraban '(sin objetivo)'. Fix: 'definitivo' ahora exige .goal NO vacío (no solo que el archivo exista). Cuando el archivo existe pero sin goal (ejecutor spawneado), se fija un goal provisional PRESERVANDO role/parent_orchestrator y se lanza autogen, que lo pisa con el definitivo. No regresiona el caso definitivo ni el primer-prompt sin archivo (verificado con 3 casos). --- .claude/hooks/goal_tracker.sh | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/.claude/hooks/goal_tracker.sh b/.claude/hooks/goal_tracker.sh index 0e6c225..12b3daf 100755 --- a/.claude/hooks/goal_tracker.sh +++ b/.claude/hooks/goal_tracker.sh @@ -100,9 +100,18 @@ esac # + `dod_status` (set_dod_contract.py, sin LLM). El DoD inicial lo fija autogen # una vez; el usuario lo ajusta a mano con "dod: ...". PROV="false" -[ -f "$F" ] && PROV=$(jq -r '.provisional // false' "$F" 2>/dev/null) +GOAL_NOW="" +if [ -f "$F" ]; then + PROV=$(jq -r '.provisional // false' "$F" 2>/dev/null) + GOAL_NOW=$(jq -r '.goal // ""' "$F" 2>/dev/null) +fi -if [ -f "$F" ] && [ "$PROV" != "true" ]; then +# "Objetivo definitivo" = archivo con goal NO vacio y no provisional. El check de +# goal no vacio es clave para los ejecutores lanzados por spawn_fleet_agent: su +# goal.json se PRE-CREA con solo {role, parent_orchestrator} (sin goal). Sin este +# guard, el hook tomaria ese archivo como objetivo definitivo y nunca lanzaria +# autogen, dejando el goal vacio para siempre (statusline y FleetView sin objetivo). +if [ -f "$F" ] && [ "$PROV" != "true" ] && [ -n "$GOAL_NOW" ]; 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) @@ -114,11 +123,17 @@ else # 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. + PROV_GOAL=$(printf '%s' "$PROMPT_TRIM" | head -c 70) + if [ -n "$GOAL_NOW" ]; then + # Ya habia goal 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" + elif [ -f "$F" ]; then + # Archivo PRE-CREADO por spawn_fleet_agent ({role, parent_orchestrator}) + # sin goal: fija el provisional PRESERVANDO los campos existentes (role, + # parent_orchestrator) y deja que autogen lo pise con el definitivo. + jq --arg g "$PROV_GOAL" --arg p "$PROMPT_TRIM" \ + '. + {goal:$g, phase:"planificando", history:["planificando"], prompts:[$p], provisional:true}' "$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