tawasuyu

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

man-pages: cero llamadas al sistema documentadas en todo el corpus

El censo decía «mandoc LEE man; falta el CONTENIDO», que se lee como «no hay
páginas de manual». Medí antes de construir y era falso: el store ya tenía
4.710 páginas de sección 3 y 1.074 de la 1, porque cada paquete trae las
suyas — `man pass` y `man curl` funcionan desde siempre.

El hueco real era exacto y era otro:

    find /store/*/usr/share/man/man2 -type f | wc -l   ⇒  0
    open.2 read.2 fork.2 mmap.2 malloc.3 printf.3 signal.7 socket.7 ⇒ AUSENTES

CERO llamadas al sistema documentadas, más las funciones de libc y las páginas
de concepto. Eso lo publica el proyecto Linux man-pages y nadie más: las de
sección 3 que ya había son APIs de bibliotecas, y de hecho 3.118 de las 4.710
son de libxcb y libX11 — documentación de X11, que esta distro descartó.

Tres cosas que el INSTALL de upstream no dice y el GNUmakefile sí:

· make -R es OBLIGATORIO (guarda en la línea 11; sin él muere con «Please run
  make(1) with the -R option»). La guarda sólo salta por debajo de make
  4.4.999, así que el día que el lab suba seguirá siendo correcto.
· SHELL ::= bash con -Eeuo pipefail ⇒ bash es dep de BUILD, no sólo de lectura.
· `install` = `install-man install-bin`, y el `bin` son 12 herramientas para
  quien CONTRIBUYE al proyecto (diffman-git, git-bisect-rebase, grepc, pdfman…)
  con deps que esta receta no declara. Se usa `install-man`, y queda un
  centinela que falla si alguna vez vuelven a colarse ejecutables.

El guardián es funcional: cuenta las secciones, exige una por una las ocho
páginas que medí ausentes, y RENDERIZA open.2 y malloc.3 con mandoc buscando
contenido esperado. Para datos de texto «el fichero existe» es trivialmente
cierto y no prueba que se lean — esta distro no tiene groff, lee con mandoc,
que es otro programa y otras macros. Resultado: 3.153 páginas, 0 avisos.

Las secciones no estándar (man2const, man3type…) se instalan a propósito
aunque `man` todavía no las busque: tirarlas sería perder contenido, y
enseñarle a buscarlas es configuración del perfil, no del paquete de datos.

66fe516c8d30b0b74e43a185c2a7e3da00365e8a · ruwaq Sergio · (23 h ñawpaq) · tayta 63011db9b · kay commitpi sach'ata qhaway

Semántico sayk'uy

Mana ima sutichaypas t'ikrakurqanchu: qillqalla, yachachiylla utaq willaylla t'ikrakurqan.

1 qillqakuna · +144 −0

diff --git a/recipes/man-pages.toml b/recipes/man-pages.toml
new file mode 100644
index 00000000..34999eb2
--- /dev/null
+++ b/recipes/man-pages.toml
@@ -0,0 +1,144 @@
+# man-pages 6.20 — la documentación del sistema. Sin esto, `man open` no contesta nada.
+#
+# ══ EL HUECO, MEDIDO — Y EL CENSO LO DESCRIBÍA MAL ═════════════════════════════════════════════
+# La fila «páginas de manual» decía *«`mandoc` LEE man; falta el CONTENIDO»*, que se lee como «no
+# hay ninguna página». **Falso, y por eso valía medirlo antes de construir:** el store tiene 4.710
+# páginas de sección 3 y 1.074 de la 1 — cada paquete trae las suyas, y `man pass` o `man curl`
+# funcionan desde siempre.
+#
+# Lo que falta es exacto y es otra cosa:
+#
+#     find /store/*/usr/share/man/man2 -type f | wc -l   ⇒  0
+#     man open.2 · read.2 · fork.2 · mmap.2 · signal.7 · socket.7 · printf.3 · malloc.3 ⇒ AUSENTES
+#
+# **Cero páginas de sección 2 en todo el corpus**: ni una sola llamada al sistema documentada, ni
+# las funciones de libc, ni las páginas de concepto de la 7. Eso es justo lo que publica el proyecto
+# Linux man-pages y nadie más — las de sección 3 que ya había son APIs de bibliotecas (libxcb
+# aporta 2.311 y libX11 807; o sea que **3.118 de las 4.710 documentan X11, que esta distro
+# descartó**).
+#
+# Para una distro que se compila a sí misma desde fuente, no poder hacer `man mmap` es un hueco con
+# nombre. Y cuesta 1,9 MB de tarball.
+#
+# ══ ⚠ LAS SECCIONES NO ESTÁNDAR, QUE SON LA TRAMPA DE ESTE PAQUETE ════════════════════════════
+# man-pages moderno no instala sólo `man1..man9`: trae **`man2const`, `man2type`, `man3attr`,
+# `man3const`, `man3head`, `man3type`**. Son páginas reales y útiles (`man 3type size_t`,
+# `man 2const AT_FDCWD`), pero `man` **no las encuentra** si no se las nombra: el buscador recorre
+# los directorios `man<sección>` que conoce.
+#
+# ⇒ Acá se instalan igual —tirarlas sería perder contenido— y el guardián comprueba que estén, para
+# que el día que alguien configure `MANSECT`/`manpath` ya tenga qué encontrar. **No se intenta
+# arreglar la búsqueda desde esta receta**: eso es configuración de `mandoc`/`man.conf` y le toca al
+# perfil, no al paquete de datos. Dejarlo dicho vale más que resolverlo a medias y en el sitio
+# equivocado.
+#
+# ══ NO HAY COMPILACIÓN, Y AUN ASÍ EL GUARDIÁN TIENE QUE SER FUNCIONAL ══════════════════════════
+# Son ficheros de texto con macros `man(7)`. «Existe el fichero» es trivialmente cierto y no prueba
+# que sirva: una página puede estar ahí y **no renderizar** si usa macros que el formateador de esta
+# distro no implementa. Esta distro no trae `groff` — lee con `mandoc`, que es otro programa.
+#
+# ⇒ El guardián RENDERIZA con mandoc y busca texto esperado en la salida. Es la diferencia entre
+# «el paquete está» y «la documentación se puede leer».
+name    = "man-pages"
+version = "6.20"
+license = "GPL-2.0-or-later AND LGPL-2.0-or-later AND BSD-3-Clause AND MIT"
+
+[source]
+tarball = "https://mirrors.edge.kernel.org/pub/linux/docs/man-pages/man-pages-6.20.tar.xz"
+sha256  = "180f0d16a2142dd9671760ac0afeadcc25e861f695eb420293e1206a87ca083f"
+
+[build]
+compiler = "zig-cc"
+target   = "x86_64-linux-musl"
+link     = "dynamic"
+flags    = []
+
+[build.phases]
+# `make install prefix=… DESTDIR=…` es lo que documenta su propio INSTALL. No hay configure.
+#
+# ⚠ **DOS EXIGENCIAS DEL `GNUmakefile` QUE NO ESTÁN EN EL `INSTALL`**, y las dos se ven en sus
+# primeras veinte líneas:
+#
+#     SHELL       ::= bash                     ← no `sh`: pide bash explícitamente
+#     .SHELLFLAGS ::= -Eeuo pipefail -c
+#     ifneq (4.4.999, …$(MAKE_VERSION))
+#       ifneq (R,$(findstring R, $(firstword -$(MAKEFLAGS))))
+#         $(error Please run make(1) with the '-R' option)
+#
+# 1. **`-R`** (= `--no-builtin-variables`) es OBLIGATORIO con el make de este lab, y su ausencia
+#    mata el build en la línea 11 con un mensaje que al menos dice qué quiere:
+#        GNUmakefile:11: *** Please run make(1) with the '-R' option.  Stop.
+#    La guarda sólo salta por debajo de make 4.4.999 ⇒ el día que el lab suba de make, el `-R`
+#    pasa a ser inofensivo pero sigue siendo correcto. No se quita.
+# 2. **`bash` es dep de BUILD**, no sólo de lectura: el Makefile corre sus recetas con bash y
+#    `pipefail`. Sin él el fallo llega más tarde y más confuso que el de arriba.
+configure = "true"
+compile   = "true"
+install = '''
+set -e
+# ⚠ **`install-man`, NO `install`** — y la diferencia son 12 ejecutables de más.
+# `share/mk/install/_.mk:21` dice `install: install-man install-bin`, o sea que el objetivo pelado
+# instala también el `bin/` del PROYECTO: `diffman-git`, `git-bisect-rebase`, `grepc`, `pdfman`,
+# `sortman`, `mansectf`… Son herramientas para quien CONTRIBUYE a man-pages, no para quien usa la
+# distro, y entrarían con dependencias que esta receta no declara (git, perl, un `man -Tpdf`).
+# Un paquete de DATOS que mete doce scripts ajenos en `/usr/bin` es lastre con promesa rota.
+# ⇒ `install-man` es el objetivo propio de upstream para «sólo las páginas».
+make -R install-man prefix=/usr DESTDIR=/out
+
+# ── 1. las secciones ESTÁNDAR que eran el hueco ──────────────────────────────────────────────
+n2=$(find /out/usr/share/man/man2 -type f 2>/dev/null | wc -l)
+n3=$(find /out/usr/share/man/man3 -type f 2>/dev/null | wc -l)
+n7=$(find /out/usr/share/man/man7 -type f 2>/dev/null | wc -l)
+[ "$n2" -gt 400 ] || { echo "man-pages: sólo $n2 páginas de sección 2 — esperaba >400; las llamadas al sistema son el motivo de esta receta" >&2; exit 1; }
+[ "$n3" -gt 1500 ] || { echo "man-pages: sólo $n3 de sección 3 — esperaba >1500" >&2; exit 1; }
+[ "$n7" -gt 100 ]  || { echo "man-pages: sólo $n7 de sección 7 — esperaba >100" >&2; exit 1; }
+
+# ── 2. las páginas CONCRETAS que estaban ausentes y motivaron la receta ──────────────────────
+# Se nombran una por una a propósito: un recuento alto no prueba que esté LA que falta, y éstas
+# son las que se comprobaron ausentes antes de construir.
+for p in man2/open.2 man2/read.2 man2/fork.2 man2/mmap.2 man3/malloc.3 man3/printf.3 man7/signal.7 man7/socket.7; do
+  [ -f "/out/usr/share/man/$p" ] || { echo "man-pages: falta $p — era una de las que el censo midió AUSENTES" >&2; exit 1; }
+done
+
+# ── 3. las secciones NO ESTÁNDAR: que estén, aunque `man` aún no las busque ──────────────────
+for s in man2const man3type; do
+  c=$(find "/out/usr/share/man/$s" -type f 2>/dev/null | wc -l)
+  [ "$c" -gt 10 ] || { echo "man-pages: $s tiene $c ficheros — se instalan a propósito; ver la nota de la receta" >&2; exit 1; }
+done
+
+# ── 4. ⚠ GUARDIÁN FUNCIONAL: que mandoc la RENDERICE de verdad ───────────────────────────────
+# Esta distro no tiene groff: lee con mandoc. Una página puede existir y no renderizar.
+command -v mandoc >/dev/null || { echo "man-pages: no hay mandoc para comprobar el renderizado — el guardián no puede concluir" >&2; exit 1; }
+sal=$(mandoc -T ascii /out/usr/share/man/man2/open.2 2>/tmp/mandoc.err | head -60)
+printf '%s' "$sal" | grep -qi 'OPEN' || { echo "man-pages: mandoc no produjo nada reconocible para open.2" >&2; head -10 /tmp/mandoc.err >&2; exit 1; }
+printf '%s' "$sal" | grep -qi 'O_CREAT\|open a file\|file descriptor' \
+  || { echo "man-pages: open.2 renderiza pero sin el contenido esperado — ¿macros no soportadas?" >&2; printf '%s\n' "$sal" | head -20 >&2; exit 1; }
+# Y una de sección 3, que usa otro juego de macros (.SH/.TP con listas de argumentos):
+mandoc -T ascii /out/usr/share/man/man3/malloc.3 2>/dev/null | grep -qi 'malloc' \
+  || { echo "man-pages: malloc.3 no renderiza" >&2; exit 1; }
+# Los avisos de mandoc no se tratan como error: su -W por defecto se queja de estilo en páginas
+# perfectamente legibles, y convertir eso en fallo sería un guardián ruidoso que nadie respeta.
+av=$(wc -l < /tmp/mandoc.err 2>/dev/null || echo 0)
+
+# ── 5. que NO se hayan colado ejecutables ────────────────────────────────────────────────────
+# Centinela para el futuro: si upstream mueve algo de `install-bin` a `install-man`, o si alguien
+# cambia el objetivo de vuelta a `install`, esto lo caza en el acto en vez de dejarlo entrar en
+# silencio. Un paquete de datos no tiene nada que hacer en /usr/bin.
+if [ -e /out/usr/bin ] || [ -e /out/usr/sbin ]; then
+  echo "man-pages: se instalaron EJECUTABLES, y esto es sólo documentación:" >&2
+  ls /out/usr/bin /out/usr/sbin 2>/dev/null >&2
+  echo "⇒ ¿se cambió 'install-man' por 'install'? Ver la nota de la receta." >&2
+  exit 1
+fi
+
+tot=$(find /out/usr/share/man -type f 2>/dev/null | wc -l)
+echo "man-pages: $tot páginas ($n2 en sec.2, $n3 en sec.3, $n7 en sec.7) · open.2 y malloc.3 RENDERIZAN con mandoc · $av aviso(s) de estilo, no bloquean"
+'''
+
+[deps]
+# `make` + las herramientas que usa el install (`install`, `ln`, `sed`) + `mandoc` PARA EL
+# GUARDIÁN: sin él no se puede comprobar que las páginas se lean, y un guardián que no puede
+# concluir falla ruidosamente en vez de dar un falso verde.
+build = ["make", "bash", "coreutils", "sed", "mandoc", "findutils"]
+# Son datos: en runtime no ejecutan nada. Quien las LEE es `mandoc`, que ya viaja en `base` — no se
+# declara como runtime de este paquete porque la relación es la inversa (el lector usa los datos).