varias sesiones a la vez: si la instancia está ocupada, se abre la siguiente

El kernel niega dos overlays sobre el mismo upper y eso no se discute. Pero «un solo Claude» era
empaquetado nuestro: instancias distintas tienen upper distintos y conviven. Ahora el lanzador busca
una libre y, si hace falta, la crea.

La instancia nueva NO se aprovisiona: se CLONA la capa ya hecha. Con un mapa de un solo id —lo que
hay hoy— pacman no puede chownear su descarga y el provision muere en «failed to chown temporary
download directory», que es exactamente la consecuencia que el aviso de qorpa predice. Copiar el
upper cuesta ~1 s y 169 M y no depende de eso; cuando el mapeo por rango funcione, `provision` vuelve
a ser el camino.

De paso quedó medido por qué el provision fallaba antes incluso con root = true: la IMAGEN es de
root y el mapa tiene un solo id, así que adentro sus ficheros aparecen sin mapear y no se pueden
escribir. Con la imagen pasada a la persona, el mkdir de /run/user/0 pasa y se llega hasta pacman.

Probado con la primera sesión viva (1h39m): la segunda abre y contesta.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sergio
2026-09-18 17:22:26 +00:00
co-authored by Claude Opus 5
parent 2bbfd80d93
commit 95093ac827
+29 -2
View File
@@ -54,8 +54,35 @@ set -eu
# ln -sf /opt/takana/scripts/servidor/claude-caja.sh /usr/bin/claude
_yo="$(id -un)"
_hogar="${HOME:-/root}"
_inst="claude"
[ "$_yo" != "root" ] && _inst="claude-$_yo"
_base="claude"
[ "$_yo" != "root" ] && _base="claude-$_yo"
# ── VARIAS SESIONES A LA VEZ ────────────────────────────────────────────────────────────────────
# El kernel niega DOS overlays sobre el mismo `upper` —la capa mutable se corrompería— y eso no se
# discute. Pero «un solo Claude» era empaquetado nuestro, no del kernel: instancias distintas tienen
# `upper` distintos y conviven. Así que si la de siempre está ocupada, se usa la siguiente.
#
# ⚠ La instancia nueva NO se aprovisiona: se CLONA la capa ya hecha. Con un mapa de un solo id
# —lo que hay hoy, ver §6.55— `pacman` no puede chownear su descarga y el `provision` muere en
# «failed to chown temporary download directory». Copiar el `upper` cuesta ~1 s y 169 M y no depende
# de eso. Cuando el mapeo por rango funcione, `takana qorpa provision` vuelve a ser el camino.
BASEDIR=${BASEDIR:-/var/lib/hammer/qorpa/instances}
_libre() { ! pgrep -f "[q]orpa run $1 " >/dev/null 2>&1; }
_inst="$_base"; _n=2
while ! _libre "$_inst"; do
_inst="$_base-$_n"; _n=$((_n+1))
[ "$_n" -gt 9 ] && { echo "claude: hay 8 sesiones abiertas de $_base — cerrá alguna" >&2; exit 1; }
done
if [ ! -d "$BASEDIR/$_inst" ]; then
echo "claude: abro una sesión más ($_inst) — clonando la capa, ~1 s" >&2
_sha=$(sed -n 's/^base = "sha256:\(.*\)"//p' "$BASEDIR/$_base/instance.toml")
takana qorpa create "$_inst" --base "$_sha" >/dev/null || { echo "claude: no pude crear $_inst" >&2; exit 1; }
cp "$BASEDIR/$_base/instance.toml" "$BASEDIR/$_inst/instance.toml"
rm -rf "$BASEDIR/$_inst/upper"
cp -a "$BASEDIR/$_base/upper" "$BASEDIR/$_inst/upper"
mkdir -p "$BASEDIR/$_inst/work"
fi
# El `cd` no es comodidad: la memoria del agente se indexa POR RUTA DE TRABAJO. Desde `/` —que es
# donde `qorpa run` deja el shell— la sesión usa el proyecto `-` y el agente empieza sin saber nada