feat(infra): grupo claude-fleet — FleetView TUI + orquestacion de Claudes

Sistema FleetView para centralizar la flota de procesos Claude Code vivos en una
sola ventana kitty + tmux (socket aislado -L fleet) con un panel TUI:

- list_claude_fleet (+ tipo claude_fleet): escanea ~/.claude/sessions + goals +
  runtime, valida procesos vivos (anti-PID-reciclado), join por sessionId.
- list_resumable_claudes (+ tipo resumable_claude): sesiones cerradas reanudables.
- wrappers tmux: tmux_new_claude_window (con --resume), tmux_swap_window_into_console
  (preserva ancho del sidebar), tmux_map_claude_panes.
- launch_kittyclaude: comando entrypoint; instala atajos alt+flechas/enter/n/0/k/r,
  mouse on, remain-on-exit off; fija el ancho del sidebar con hooks.
- docs/capabilities/claude-fleet.md + entrada en el INDEX.

Incluye ademas funciones datascience en progreso (excel/duckdb/postgres) y ajustes
varios de docs e infra de otra sesion, agrupados aqui para no perderlos.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-17 00:04:41 +02:00
parent 7d395f39e5
commit 927437a8d8
58 changed files with 5961 additions and 2 deletions
+93
View File
@@ -0,0 +1,93 @@
---
name: read_xlsx
kind: function
lang: py
domain: infra
version: "1.0.0"
purity: impure
signature: "def read_xlsx(path: str, sheet: str = None, max_rows: int = None, header: bool = True) -> dict"
description: "Lee un archivo Excel (.xlsx) a estructuras en memoria con openpyxl (NO a markdown; complementa a excel_to_markdown). Espejo en lectura de write_xlsx_sheets: devuelve {status, sheets: {nombre: {headers: [...], rows: [[...]]}}}. Si sheet=None lee todas las hojas; si se indica, solo esa. Con header=True la primera fila de cada hoja son los headers. Maneja tipos de celda: fechas/datetime a ISO 8601, int/float, bool, None y formulas (valor calculado via data_only=True). Trunca por hoja a max_rows filas de datos si se indica. Impura: lee disco y NO lanza: en fallo devuelve {status: 'error', error}."
tags: [excel, xlsx, openpyxl, spreadsheet, office, onlyoffice, read, io, infra]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [openpyxl]
params:
- name: path
desc: "Ruta al archivo .xlsx a leer. Vacio o inexistente devuelve {status: 'error'} (no lanza). Se resuelve a ruta absoluta internamente."
- name: sheet
desc: "Nombre de la hoja a leer. None (default) lee TODAS las hojas del libro. Si se indica una hoja que no existe, devuelve {status: 'error'} con la lista de hojas disponibles."
- name: max_rows
desc: "Maximo de filas de DATOS a devolver por hoja (no cuenta la cabecera cuando header=True). None (default) = sin limite. Util para previsualizar libros grandes sin cargarlos enteros."
- name: header
desc: "Si True (default) la primera fila de cada hoja se interpreta como cabecera y va en 'headers'; el resto en 'rows'. Si False, 'headers' es [] y TODAS las filas (incluida la primera) van en 'rows'."
output: "Dict. En exito: {status: 'ok', sheets: {nombre_hoja: {headers: [...], rows: [[...], ...]}}}. En error: {status: 'error', error: '<mensaje>'}. Valores de celda como tipos nativos de Python: fechas/datetime como str ISO 8601, int/float, bool, str y None."
tested: true
tests: ["test_round_trip_escribe_lee_compara", "test_lee_solo_la_hoja_indicada", "test_max_rows_trunca_filas_de_datos", "test_header_false_no_consume_cabecera", "test_fecha_se_devuelve_como_iso", "test_formula_se_lee_como_valor_calculado", "test_archivo_inexistente_devuelve_error", "test_hoja_inexistente_devuelve_error", "test_path_vacio_devuelve_error"]
test_file_path: "python/functions/infra/read_xlsx_test.py"
file_path: "python/functions/infra/read_xlsx.py"
---
## Ejemplo
```python
import sys, os
sys.path.insert(0, os.path.join("python", "functions"))
from infra.read_xlsx import read_xlsx
from infra.write_xlsx_sheets import write_xlsx_sheets
# Escribe un libro y leelo de vuelta (round-trip)
write_xlsx_sheets("/tmp/ventas.xlsx", {
"Ventas": [
["Producto", "Unidades", "Precio", "Activo"],
["Teclado", 12, 29.99, True],
["Raton", 30, 14.5, False],
["Monitor", None, 199.0, True], # None -> None al leer
],
})
res = read_xlsx("/tmp/ventas.xlsx")
print(res["status"]) # ok
print(list(res["sheets"].keys())) # ['Ventas']
print(res["sheets"]["Ventas"]["headers"]) # ['Producto', 'Unidades', 'Precio', 'Activo']
print(res["sheets"]["Ventas"]["rows"][0]) # ['Teclado', 12, 29.99, True]
# Solo una hoja, primeras 1 fila de datos
res = read_xlsx("/tmp/ventas.xlsx", sheet="Ventas", max_rows=1)
print(res["sheets"]["Ventas"]["rows"]) # [['Teclado', 12, 29.99, True]]
```
## Cuando usarla
Usala cuando necesites los datos de un .xlsx como **estructuras de Python**
(listas y dicts) para procesarlos en codigo: validar, transformar, alimentar
otra funcion, hacer asserts. Es el espejo en lectura de `write_xlsx_sheets`
(mismo shape `{hoja: {headers, rows}}`) y la base para round-trips
escribir->leer. Si lo que quieres es una representacion **textual** del libro
para mostrar o resumir (p.ej. pasarla a un LLM), usa `excel_to_markdown_py_core`
en su lugar: aquella produce tablas markdown, esta produce datos crudos.
## Gotchas
- **Impura — lee de disco.** No lanza: devuelve `{"status": "error", ...}` ante
archivo inexistente, hoja inexistente, path vacio o openpyxl ausente.
- **openpyxl carga el libro entero en memoria.** Aun en `read_only=True`, un
libro muy grande consume RAM proporcional a su tamano; usa `max_rows` para
previsualizar sin materializar todas las filas, pero recuerda que openpyxl
igual abre el archivo completo.
- **`data_only=True`** devuelve el valor **cacheado** de las formulas, no la
formula. Ese cache solo existe si un motor (Excel/LibreOffice) abrio y guardo
el libro tras escribir la formula. openpyxl NO evalua formulas: un .xlsx con
formulas escritas por openpyxl y nunca abierto en Excel devolvera `None` en
esas celdas. Para round-trips fiables, escribe el VALOR, no la formula.
- **Requiere openpyxl** (ya instalado en `python/.venv`, version 3.1.5).
- **Tipos de celda**: None se conserva como None; int/float/str/bool nativos;
`datetime.date` -> `"YYYY-MM-DD"`; `datetime.datetime` sin hora -> `"YYYY-MM-DD"`,
con hora -> `"YYYY-MM-DDTHH:MM:SS"`. Cualquier otro tipo se serializa a str.
- **`header=False`** NO consume la primera fila: todas las filas (incluida la
cabecera real, si la hubiera) van en `rows`. Util cuando el libro no tiene
cabecera o quieres procesarla como dato.
- **Orden de hojas preservado** segun el orden del libro (igual que
`write_xlsx_sheets` preserva el orden de insercion del dict).