triaje: los 170 candidatos de frontera clasificados, y la cadena se ejerce entera

Evidencia dura primero: NINGUNO de los 170 bloquea un build. Toda receta que
pide uno de estos ya está sellada al menos una vez ⇒ hammer construye sin
ninguno. Eso descarta empíricamente "hueco de build" para los 170 y deja sólo
la pregunta de runtime.

VEREDICTOS
  provisto  11 — no faltan: ya los da otra receta con otro nombre. nixpkgs parte
                 en varios paquetes lo que acá es uno solo. Verificado contra el
                 store: wayland-scanner→wayland, mesa-libgbm→mesa (nuestros tres
                 mesa producen libgbm.so.1), libxcb-*→xcb-util-*, poppler-qt6→
                 poppler, gmp-with-cxx→gmp, uname→coreutils.
  nix-ismo   5 — andamiaje de nixpkgs (env wrappers, helpers del stdenv, glibc
                 asomando por su libc).
  opcional 150 — software real que nixpkgs habilita y hammer no necesita, con el
                 porqué agrupado: systemd (usamos arje-zero), X11 heredado (el
                 escritorio es Wayland), Vulkan/shaders, audio/multimedia,
                 conectores de BD, tooling de docs/tests, bindings Python de Qt,
                 paquetería ajena (tenemos .swm).
  hueco      4 — gaps de RUNTIME, no de build: shared-mime-info (sin base MIME
                 no hay tipos de fichero), xwayland (ninguna app X11 corre),
                 polkit-qt-1 (sin diálogos de autorización), qqc2-breeze-style
                 (los controles QML caen a un estilo genérico).

CORRIGE UN ERROR MÍO DE P3: dije que mesa-libgbm/libglvnd eran "el muro de
GBM/EGL". Falso — libgbm ya lo produce nuestro mesa. El muro era softpipe vs
llvmpipe, no un paquete ausente.

CUARTO VEREDICTO NUEVO (`provisto`) con su propio lazo: sale a alias-triaje.txt
y seed-graph.py lo carga en MAPA ⇒ esos 11 nombres dejan de contarse como hueco
para siempre. Junto con nixismos-triaje.txt, el sembrador aprende de su triaje.

Y LA CADENA SE EJERCE ENTERA POR PRIMERA VEZ: los 4 huecos entraron como raíces
de escritorio-kde → nacieron 4 nodos `wanted` (raíces 11, sin receta 4; el grafo
sigue cerrando, --check exit 0) → seed-graph los sembró (42 aristas conocidas,
21 candidatos nuevos de frontera) → drenar.py los ordena marcándolos [semilla],
que es la regla de la fuente única a la vista. qqc2-breeze-style no cae en la
onda 1 porque sus deps SEMBRADAS la traban (kcodecs, kirigami…): el andamio
funcionando como se diseñó.

De paso: qtbase se selló mientras corría esto ⇒ la onda 1 de KDE se abrió de 1 a
13 recetas. El cuello de botella que reportó P4 ya está destrabado.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-22 18:30:19 -04:00
co-authored by Claude Opus 4.8
parent ec28a9b394
commit 9b67268a65
9 changed files with 1125 additions and 761 deletions
+21 -3
View File
@@ -14,6 +14,9 @@
# Queda registrada para que deje de reaparecer como pregunta.
# nix-ismo → andamiaje de nixpkgs sin contraparte acá ⇒ vuelve a `seed-graph.py` como descarte,
# así la próxima corrida es más limpia. El sembrador aprende de su propio triaje.
# provisto → NO falta: ya lo da otra receta con otro nombre (nixpkgs parte en varios paquetes
# lo que acá es uno solo: `mesa-libgbm`→mesa, `libxcb-image`→xcb-util-image).
# Vuelve a `seed-graph.py` como ALIAS ⇒ deja de contarse como hueco para siempre.
#
# NO decide nada solo. `sugerencia` propone con evidencia mecánica (cuántas recetas lo piden, si el
# nombre tiene forma de env/wrapper de nix), pero `veredicto` arranca en `pendiente` y sólo lo
@@ -29,7 +32,8 @@ ROOT = Path(__file__).resolve().parent.parent
FRONTERA = ROOT / "docs/state/seed-frontera.json"
TRIAJE = ROOT / "docs/state/frontera-triaje.toml"
DESCARTE = ROOT / "docs/state/nixismos-triaje.txt"
VEREDICTOS = ("pendiente", "hueco", "opcional", "nix-ismo")
ALIAS = ROOT / "docs/state/alias-triaje.txt"
VEREDICTOS = ("pendiente", "hueco", "opcional", "nix-ismo", "provisto")
# Formas de nombre que en nixpkgs son andamiaje casi seguro. Sólo alimenta `sugerencia`, nunca
# `veredicto`: una heurística no cierra un juicio, lo abarata.
@@ -61,13 +65,15 @@ def escribir(cands):
"# pone un HUMANO editando este fichero. Sincronizar NO pisa lo ya decidido: sólo agrega",
"# candidatos nuevos y marca `[ausente]` los que dejaron de aparecer.",
"#",
"# veredicto ∈ pendiente | hueco | opcional | nix-ismo",
"# veredicto ∈ pendiente | hueco | opcional | nix-ismo | provisto",
"# hueco — falta de verdad. Ponelo como raíz en docs/state/targets.toml ⇒ nace un nodo",
"# `wanted` en el grafo y entra al drenaje. (`triaje.py --aplicar` te da la línea.)",
"# opcional — dep que nixpkgs habilita y nosotros no queremos. Queda registrada para que no",
"# vuelva a preguntarse.",
"# nix-ismo — andamiaje de nixpkgs sin contraparte acá. `--aplicar` lo manda al descarte del",
"# sembrador ⇒ la próxima corrida sale más limpia.",
"# provisto — no falta: ya lo da otra receta con otro nombre. `provee = \"<receta>\"` dice cuál;",
"# `--aplicar` lo manda al sembrador como alias.",
"#",
"# `sugerencia` es una heurística con evidencia, NO un veredicto: abarata el juicio, no lo cierra.",
'schema = "hammer-frontera-triaje/1"',
@@ -79,6 +85,8 @@ def escribir(cands):
lineas.append(f'veredicto = "{c.get("veredicto", "pendiente")}"')
if c.get("sugerencia"):
lineas.append(f'sugerencia = "{c["sugerencia"]}"')
if c.get("provee"):
lineas.append(f'provee = "{c["provee"]}"')
if c.get("porque"):
lineas.append(f'porque = "{c["porque"]}"')
lineas.append(f'perfiles = {json.dumps(sorted(c.get("perfiles", [])))}')
@@ -114,7 +122,8 @@ def sincronizar():
nuevos += 1
cands[dep] = dict(
veredicto=anterior.get("veredicto", "pendiente"), # NUNCA se pisa un juicio humano
sugerencia=sug, porque=porque,
provee=anterior.get("provee"), sugerencia=sug,
porque=anterior.get("porque") or porque,
perfiles=e["perfiles"], piden=e["piden"])
# Los que ya no aparecen no se borran: se marcan. Un candidato que desaparece puede ser progreso
# (se escribió la receta) o un cambio de nixpkgs, y conviene verlo en el `git diff`.
@@ -165,6 +174,15 @@ def aplicar():
+ "\n".join(nixismos) + ("\n" if nixismos else ""))
print(f"== {len(nixismos)} nix-ismos → {DESCARTE.relative_to(ROOT)} (los lee seed-graph.py)")
alias = {d: c["provee"] for d, c in cands.items()
if c.get("veredicto") == "provisto" and c.get("provee")}
ALIAS.write_text(
"# alias-triaje.txt — DERIVADO de frontera-triaje.toml por scripts/triaje.py --aplicar.\n"
"# `<nombre-en-nixpkgs> <receta-de-hammer-que-lo-provee>`. Lo lee seed-graph.py como MAPA:\n"
"# nixpkgs parte en varios paquetes lo que acá es uno solo.\n"
+ "".join(f"{d} {r}\n" for d, r in sorted(alias.items())))
print(f"== {len(alias)} alias → {ALIAS.relative_to(ROOT)} (los lee seed-graph.py como MAPA)")
huecos = {d: c for d, c in cands.items() if c.get("veredicto") == "hueco"}
if not huecos:
print("\n== 0 huecos confirmados: no hay raíces nuevas que agregar a targets.toml")