Files
fn_registry/python/functions/infra/mark_claude_role_test.py
T
agent 334a71eed1 feat: launcher arranca orquestador + idle, pin por role (flow 0012, fase 3b)
- mark_claude_role (python/functions/infra): resuelve PID->sessionId
  esperando sessions/<PID>.json y escribe role en el goal.json sin pisar
  el resto. 4 tests.
- launch_fleetclaude: el pane derecho arranca el ORQUESTADOR con el skill
  /orquestador embebido como primer prompt; tras arrancar, mark_claude_role
  le pone role=orchestrator (en background, no-fatal) para que la TUI lo
  pinee arriba; ademas siembra 1 ejecutor idle inicial en su propia window.
- skill /orquestador: regla 'no te vigiles a ti mismo' (ignora en la cola
  su propia sesion y cualquier role=orchestrator).

Validado en vivo (perfil aislado): claude /orquestador entra en modo,
role marcado, idle sembrado, pin correcto, fleet2 intacto.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 20:33:37 +02:00

120 lines
3.8 KiB
Python

"""Tests para mark_claude_role."""
import json
import os
import pytest
from mark_claude_role import mark_claude_role
def _write_session(sessions_dir, pid, session_id):
"""Escribe un sessions/<pid>.json con el sessionId dado."""
os.makedirs(sessions_dir, exist_ok=True)
path = os.path.join(sessions_dir, f"{pid}.json")
with open(path, "w", encoding="utf-8") as fh:
json.dump({"sessionId": session_id, "cwd": "/tmp/whatever"}, fh)
return path
def _write_goal(goals_dir, session_id, goal):
"""Escribe un goal/<sessionId>.json con el dict dado."""
os.makedirs(goals_dir, exist_ok=True)
path = os.path.join(goals_dir, f"{session_id}.json")
with open(path, "w", encoding="utf-8") as fh:
json.dump(goal, fh)
return path
def _read_goal(goals_dir, session_id):
path = os.path.join(goals_dir, f"{session_id}.json")
with open(path, "r", encoding="utf-8") as fh:
return json.load(fh)
def test_sessions_presente_resuelve_y_escribe_role_preservando_otros_campos(tmp_path):
sessions_dir = str(tmp_path / "sessions")
goals_dir = str(tmp_path / "goals")
pid = 4242
sid = "abc-123-uuid"
_write_session(sessions_dir, pid, sid)
# Goal preexistente con campos que NO deben perderse.
_write_goal(
goals_dir,
sid,
{
"goal": "implementar fase 3",
"phase": "trabajando",
"dod": ["compila", "tests verdes"],
"dod_contract": {"capa1": "mecanica"},
},
)
res = mark_claude_role(pid, "orchestrator", wait_s=2.0,
sessions_dir=sessions_dir, goals_dir=goals_dir)
assert res["ok"] is True
assert res["pid"] == pid
assert res["session_id"] == sid
assert res["role"] == "orchestrator"
assert res["path"] == os.path.join(goals_dir, f"{sid}.json")
goal = _read_goal(goals_dir, sid)
assert goal["role"] == "orchestrator"
# Todos los demas campos del goal se preservan intactos.
assert goal["goal"] == "implementar fase 3"
assert goal["phase"] == "trabajando"
assert goal["dod"] == ["compila", "tests verdes"]
assert goal["dod_contract"] == {"capa1": "mecanica"}
def test_role_invalido_lanza_value_error_sin_escribir(tmp_path):
sessions_dir = str(tmp_path / "sessions")
goals_dir = str(tmp_path / "goals")
pid = 4242
sid = "abc-123-uuid"
_write_session(sessions_dir, pid, sid)
with pytest.raises(ValueError):
mark_claude_role(pid, "supervisor", wait_s=2.0,
sessions_dir=sessions_dir, goals_dir=goals_dir)
# No escribio nada: el goals_dir ni siquiera deberia existir.
assert not os.path.exists(goals_dir)
def test_sessions_ausente_devuelve_timeout_sin_crash(tmp_path):
sessions_dir = str(tmp_path / "sessions")
goals_dir = str(tmp_path / "goals")
pid = 9999 # sin sessions/<pid>.json escrito
res = mark_claude_role(pid, "executor", wait_s=0.5,
sessions_dir=sessions_dir, goals_dir=goals_dir)
assert res["ok"] is False
assert res["pid"] == pid
assert "timeout" in res["error"]
assert f"{pid}.json" in res["error"]
# No se escribio ningun goal.
assert not os.path.exists(goals_dir)
def test_goal_inexistente_se_crea_con_solo_role(tmp_path):
sessions_dir = str(tmp_path / "sessions")
goals_dir = str(tmp_path / "goals")
pid = 7
sid = "fresh-session-uuid"
_write_session(sessions_dir, pid, sid)
# No existe goal previo para esta sesion.
res = mark_claude_role(pid, "executor", wait_s=2.0,
sessions_dir=sessions_dir, goals_dir=goals_dir)
assert res["ok"] is True
assert res["session_id"] == sid
assert res["role"] == "executor"
goal = _read_goal(goals_dir, sid)
assert goal == {"role": "executor"}