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…

TOML 1572Shell 203Rust 109Markdown 993728 Sutichaykuna

⎇ 4a68dfe76149bfca9dfb0a3320407b3123070f53 docs/05-journal.md Markdown · 86 siq'ikuna · 4.1 KB Ñawpa willay ch'uya

Scaffold inicial: workspace Rust + SDDs completos 8bf162304 · sergio ·

1# SDD 05 — Diario de mutaciones
2
3Este es el insight central de `hammer`: **el diario es tu configuración del sistema — sin ser
4declarativa.** No declaras tu sistema en un archivo de texto antes de vivirlo; vives el sistema
5imperativamente, y el propio sistema deriva, *a posteriori*, un mapa de tu desviación respecto
6a la base limpia construida por el laboratorio.
7
8Esto rompe la falsa dicotomía declarativo vs imperativo, y resuelve dos problemas a la vez:
9
10- El de Arch/Gentoo: con los meses se pudren en archivos huérfanos porque el gestor pierde el
11  rastro de lo que el usuario hizo a mano.
12- El de Nix: para evitar lo anterior, te ata las manos (todo debe declararse antes).
13
14## 1. El mecanismo
15
16Un daemon ultraligero (`hammerd`) usa **`fanotify`** a nivel de kernel para registrar
17**exclusivamente las mutaciones** sobre los directorios del sistema (`/bin`, `/sbin`, `/lib`,
18`/etc`). No bloquea ninguna acción. Te deja destruir, mover y crear archivos a tu antojo. Pero
19anota, en silencio, un diario de modificaciones.
20
21> `fanotify` sobre `inotify`: cobertura a nivel de superbloque/mount, eventos de modificación
22> con info de PID/UID, y menor coste que vigilar recursivamente cada subdirectorio.
23
24## 2. Qué registra (y qué no)
25
26**Registra** mutaciones del FHS gestionado:
27
28- creación / reemplazo / borrado de archivos en `/bin`, `/sbin`, `/lib`, `/etc`,
29- qué los originó (PID, UID, y si fue una hidratación de `hammer`, el `artifact_hash`),
30- ediciones de archivos de config en `/etc`.
31
32**No registra:**
33
34- actividad efímera en `/tmp`, `/run`, `/proc`, `/sys`, `/dev`,
35- lecturas/ejecuciones (sólo mutaciones),
36- nada dentro de un overlay activo (el ruido del experimento no entra; sólo el `commit`).
37
38## 3. Formato del diario
39
40Log **append-only de texto plano** (JSON-líneas), legible con `cat`/`grep`/`jq`. Cada línea es
41un evento atómico. (Los timestamps los provee el daemon; el formato no impone reloj de
42construcción.)
43
44```jsonl
45{"ts":"2026-06-06T18:40:01Z","op":"replace","path":"/bin/grep","by":{"uid":1000,"pid":4821},"artifact":"b3:9f2a…","note":"hydrate grep@perl-default"}
46{"ts":"2026-06-06T18:41:12Z","op":"edit","path":"/etc/network.conf","by":{"uid":1000,"pid":4990},"diff_hash":"b3:7c1d…"}
47{"ts":"2026-06-06T18:42:03Z","op":"manual-replace","path":"/bin/ls","by":{"uid":1000,"pid":5102},"artifact":null,"note":"usuario pisó ls a mano"}
48```
49
50`artifact: null` + `op: manual-replace` ⇒ el usuario reemplazó algo a mano fuera del flujo de
51`hammer`. Eso no es un error; es información. El diario distingue "mutación trazable" (vino de
52una receta/artefacto conocido) de "mutación opaca" (pisada manual), sin prohibir ninguna.
53
54## 4. Exportar: del diario al `.swm`
55
56`hammer export` lee el diario, lo recorta al delta relevante respecto a una **base** conocida,
57y produce un manifiesto `.swm` ([SDD 06](06-swm-format.md)):
58
59- **base** = el conjunto de commits fijados + versión de distro de los que partiste.
60- **mutations** = las mutaciones trazables convertidas a recetas (`source_patch`) y las
61  ediciones de config (`config_edit`), más reglas de init si aplican.
62- Las mutaciones **opacas** (pisadas manuales sin artefacto) se reportan como advertencia: no
63  se pueden compartir como receta reproducible. `hammer` te dice exactamente cuáles y por qué.
64
65Así, **exportar el diario = exportar tu distro**, pero sólo la parte que es reproducible y
66verificable. Lo que pisaste a ciegas, lo sabes y decides qué hacer con ello.
67
68## 5. Replicar en otra máquina
69
70No copias una config abstracta: exportas el diario de tus acciones humanas sobre el metal. La
71otra máquina, partiendo de la misma base, **reproduce** las recetas y aplica las ediciones.
72Tu sistema se replica desde su historia, no desde una declaración.
73
74## 6. Interfaz
75
76```rust
77// hammerd / hammer-core
78pub struct Journal { path: PathBuf }
79impl Journal {
80    pub fn record(&self, ev: MutationEvent) -> Result<()>;
81    pub fn since(&self, base: &BaseRef) -> Result<Vec<MutationEvent>>;
82    pub fn export_swm(&self, base: &BaseRef) -> Result<(Swm, Vec<OpaqueWarning>)>;
83}
84```
85
86CLI: `hammer journal` (ver/seguir el diario) · `hammer export [--base <ref>] > my.swm`.

05-journal.md

SDD 05 — Diario de mutaciones

Este es el insight central de hammer: el diario es tu configuración del sistema — sin ser declarativa. No declaras tu sistema en un archivo de texto antes de vivirlo; vives el sistema imperativamente, y el propio sistema deriva, a posteriori, un mapa de tu desviación respecto a la base limpia construida por el laboratorio.

Esto rompe la falsa dicotomía declarativo vs imperativo, y resuelve dos problemas a la vez:

1. El mecanismo

Un daemon ultraligero (hammerd) usa fanotify a nivel de kernel para registrar exclusivamente las mutaciones sobre los directorios del sistema (/bin, /sbin, /lib, /etc). No bloquea ninguna acción. Te deja destruir, mover y crear archivos a tu antojo. Pero anota, en silencio, un diario de modificaciones.

fanotify sobre inotify: cobertura a nivel de superbloque/mount, eventos de modificación con info de PID/UID, y menor coste que vigilar recursivamente cada subdirectorio.

2. Qué registra (y qué no)

Registra mutaciones del FHS gestionado:

No registra:

3. Formato del diario

Log append-only de texto plano (JSON-líneas), legible con cat/grep/jq. Cada línea es un evento atómico. (Los timestamps los provee el daemon; el formato no impone reloj de construcción.)

{"ts":"2026-06-06T18:40:01Z","op":"replace","path":"/bin/grep","by":{"uid":1000,"pid":4821},"artifact":"b3:9f2a…","note":"hydrate grep@perl-default"}
{"ts":"2026-06-06T18:41:12Z","op":"edit","path":"/etc/network.conf","by":{"uid":1000,"pid":4990},"diff_hash":"b3:7c1d…"}
{"ts":"2026-06-06T18:42:03Z","op":"manual-replace","path":"/bin/ls","by":{"uid":1000,"pid":5102},"artifact":null,"note":"usuario pisó ls a mano"}

artifact: null + op: manual-replace ⇒ el usuario reemplazó algo a mano fuera del flujo de hammer. Eso no es un error; es información. El diario distingue "mutación trazable" (vino de una receta/artefacto conocido) de "mutación opaca" (pisada manual), sin prohibir ninguna.

4. Exportar: del diario al .swm

hammer export lee el diario, lo recorta al delta relevante respecto a una base conocida, y produce un manifiesto .swm (SDD 06):

Así, exportar el diario = exportar tu distro, pero sólo la parte que es reproducible y verificable. Lo que pisaste a ciegas, lo sabes y decides qué hacer con ello.

5. Replicar en otra máquina

No copias una config abstracta: exportas el diario de tus acciones humanas sobre el metal. La otra máquina, partiendo de la misma base, reproduce las recetas y aplica las ediciones. Tu sistema se replica desde su historia, no desde una declaración.

6. Interfaz

// hammerd / hammer-core
pub struct Journal { path: PathBuf }
impl Journal {
    pub fn record(&self, ev: MutationEvent) -> Result<()>;
    pub fn since(&self, base: &BaseRef) -> Result<Vec<MutationEvent>>;
    pub fn export_swm(&self, base: &BaseRef) -> Result<(Swm, Vec<OpaqueWarning>)>;
}

CLI: hammer journal (ver/seguir el diario) · hammer export [--base <ref>] > my.swm.