harkaq: el clasificador nunca propone runtime base como declarable (fix de raíz de busybox)
El bug que declaró `busybox` en 29 recetas y rompió binutils: harkaq-suggest veía `/bin/busybox` denegado, encontraba `recipes/busybox.toml` en el store y decía "declarar dep: busybox" — sin mirar que la política YA lo concede (`ro /bin/busybox`: el sandbox corre `sh -c` y /bin/sh→busybox ⇒ es CONTRATO, no dep). Fix: harkaq-suggest ahora lee los paths CONCEDIDOS de la política (`ro`/`rw`/`list`), no sólo los `# expect`. Si un path está concedido ⇒ categoría RUNTIME BASE: no se declara, aunque el store lo provea. Las 4 clasificaciones verificadas tras el cambio: /bin/busybox → RUNTIME BASE (ya concedido; NO declarar) ← el fix /usr/bin/make → DECLARABLE (declarar dep: make) /usr/lib/libstdc++.so → IRREDUCIBLE (nadie lo provee) /usr/bin/gcc en broot → DEUDA DE COMPILADOR (compiler=gcc) /usr/bin/gcc en zlib → sin deuda (sonda esperada; zlib compila con zig) Con esto puesto, busybox JAMÁS se habría declarado. Cierra el TODO que dejó el revert: la campaña automática ya no puede cimentar contrato como dependencia. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -101,11 +101,22 @@ def main():
|
||||
usa_gcc = receta_toml and compiler_de(receta_toml) == "gcc"
|
||||
|
||||
esperadas = set()
|
||||
# RUNTIME BASE: lo que la política ya CONCEDE (`ro`/`rw`/`list`). Si un path está acá, NO es
|
||||
# deuda declarable aunque el store lo provea — es contrato del sandbox.
|
||||
#
|
||||
# Este bug costó caro: `/bin/busybox` está concedido (el sandbox corre `sh -c` y /bin/sh→
|
||||
# busybox), pero como `recipes/busybox.toml` existe, el clasificador propuso "declarar dep:
|
||||
# busybox" y la cosecha lo declaró en 29 recetas. Declararlo apila el busybox de hammer sobre
|
||||
# el de Alpine y ROMPE el build (binutils: "cannot run C compiled programs"). Además va contra
|
||||
# la Etapa C, que reemplaza busybox por uutils. Medir bien y accionar mal.
|
||||
concedidos = set()
|
||||
with open(politica) as f:
|
||||
for l in f:
|
||||
l = l.strip()
|
||||
if l.startswith("# expect "):
|
||||
esperadas.add(l[len("# expect "):].strip())
|
||||
elif l[:3] in ("ro ", "rw ") or l.startswith("list "):
|
||||
concedidos.add(l.split(None, 1)[1].strip())
|
||||
# Si la receta compila con gcc, los frontends NO se perdonan: son la deuda de compilador.
|
||||
if usa_gcc:
|
||||
esperadas -= FRONTENDS_GCC
|
||||
@@ -117,11 +128,15 @@ def main():
|
||||
|
||||
idx = indice_del_store(store)
|
||||
recetas = catalogo(recipes_dir)
|
||||
declarable, irreducible, compilador = {}, [], []
|
||||
declarable, irreducible, compilador, base = {}, [], [], []
|
||||
for p in deuda:
|
||||
if usa_gcc and p in FRONTENDS_GCC:
|
||||
compilador.append(p)
|
||||
continue
|
||||
# ¿Ya concedido por la política? ⇒ runtime base, NO se declara (ver arriba: busybox).
|
||||
if p in concedidos or any(p.startswith(c.rstrip("/") + "/") for c in concedidos if c != "/"):
|
||||
base.append(p)
|
||||
continue
|
||||
provs = idx.get(p)
|
||||
if provs:
|
||||
# El store es autoritativo: sabe qué ficheros aporta cada artefacto.
|
||||
@@ -144,6 +159,10 @@ def main():
|
||||
else:
|
||||
irreducible.append(p)
|
||||
|
||||
if base:
|
||||
print("RUNTIME BASE — ya concedido por la política; NO declarar (es contrato del sandbox):")
|
||||
for p in base:
|
||||
print(f" {p}")
|
||||
if compilador:
|
||||
print("DEUDA DE COMPILADOR (matar-gcc) — la receta usa el gcc de Alpine (compiler=gcc):")
|
||||
for p in compilador:
|
||||
|
||||
Reference in New Issue
Block a user