1# ADR 0009 — Código direccionado por contenido (estilo Unison): registrar la visión, no reescribir la unidad
2
3- **Estado:** propuesta (design-doc — registra una dirección, no compromete una reescritura)
4- **Fecha:** 2026-07-03
5- **Frontera:** SDD 15 §H3 (idea 3). Depende conceptualmente de [ADR pendiente H2] y del
6 determinismo wasm auditado en H2a (`tawasuyu/03_ukupacha/wawa/SDD-determinismo.md`).
7
8## Contexto
9
10takana y wawa **ya** direccionan por contenido, pero *cosas distintas*:
11
12- **takana** hashea el **artefacto compilado** y la **receta**. La identidad de un artefacto es
13 `ArtifactHash` sobre las entradas canónicas de la receta (`Recipe::hash_inputs`,
14 `crates/hammer-core/src/recipe.rs:370`): `source_id` (commit git o sha256 del tarball),
15 compilador, target, link, `zig_version`, contenido de los patches, flags, overrides de fases.
16 Grano **grueso**, lenguaje-**agnóstico**: encaja con "recetas sobre fuente upstream".
17- **wawa** hashea el **módulo wasm** y el **objeto** del grafo/almacén. Grano de módulo/objeto.
18
19La **idea 3** (Unison) empuja al límite: direccionar **funciones por el hash de su AST**. En
20Unison, el código no vive en archivos sino en una base content-addressed donde cada definición
21ES su hash; renombrar es metadata, actualizar es insertar una definición nueva (la vieja no se
22rompe: quien la referenciaba sigue apuntando a su hash). El sueño para un agente de IA: **no
23editar archivos que se rompen entre sí**, sino insertar definiciones en un espacio donde
24*nada se rompe por renombrar o actualizar*. Paquete de takana, módulo wasm de wawa y función
25de código **colapsarían en un solo espacio de nombres: el hash**.
26
27## Decisión
28
29**Registrar la visión y NO reescribir la unidad de compilación.** Concretamente:
30
311. **No** colapsar ahora artefacto/módulo/función en un solo tipo. takana sigue con grano de
32 artefacto; wawa con grano de módulo. La identidad content-addressed de cada uno queda intacta.
332. **Sí** construir el *puente barato*: **procedencia por-símbolo como metadata**, derivada de lo
34 que ya sabemos leer, SIN tocar `hash_inputs` ni la unidad de build. takana ya tiene un parser
35 ELF hand-rolled (`parse_elf_needed`, `crates/hammer-core/src/query.rs:298`) que extrae
36 `DT_NEEDED` (las libs dinámicas que un binario necesita) para la query `depends:`. Extenderlo
37 para emitir también los **símbolos exportados** (`.dynsym`) da, por artefacto, "qué provee y
38 qué necesita" — un grafo de símbolos content-addressed **descriptivo**, no normativo: es
39 metadata anexa a la receta/artefacto, no entra al hash de identidad (misma disciplina que el
40 bloque `evidence` de H1: describe, no identifica).
413. **Diferir** el grano fino real (función-por-hash) a **H3b**, un experimento aislado sobre
42 **wasm** (un `.wasm` por función pura del subconjunto determinista de H2), que es el
43 subconjunto de Unison que nuestro stack *ya* podría sostener (wasm + BLAKE3 + determinismo
44 H2a) **sin un lenguaje nuevo**. H3b es exploratorio y está gateado por H2 en verde.
45
46## Razones
47
48- **Es otro modelo de datos, no una extensión.** takana content-addressa el artefacto compilado
49 (grano grueso, lenguaje-agnóstico); Unison el AST de cada función (grano fino, exige un
50 lenguaje y toolchain propios). Colapsarlos pide reescribir la unidad de compilación entera —
51 eso es un proyecto, no una fase. El ADR lo dice para no fingir que es una feature incremental.
52- **El valor es real pero el costo es un proyecto.** El fin del *dependency-hell* para un agente
53 (insertar una definición nunca rompe a quien la usa) es exactamente lo que haría al bucle
54 agéntico de SDD 08 mucho más seguro. Pero comprometerse hoy a la reescritura del build sería
55 cambiar los cimientos por una apuesta no probada. Design-doc primero.
56- **El puente barato entrega valor sin apostar.** La procedencia por-símbolo (paso 2) es útil
57 ya: alimenta queries "¿qué artefacto exporta `foo`?", detección de colisiones de símbolos entre
58 paquetes, y una primera forma de "referencia por contenido" (un consumidor puede pinnear no el
59 paquete sino el *símbolo+hash* que usa). Todo reusando el parser ELF existente.
60- **Respeta la disciplina de identidad de takana.** Nada de esto mueve `ArtifactHash`: el
61 baseline de reproducibilidad (of_tree 9adefb82 / rust 7fa6cb4e) no se toca. La procedencia es
62 metadata, como la evidencia de H1.
63
64## Consecuencias
65
66- **Ahora (barato, sin apuesta) — IMPLEMENTADO (2026-07-03):** `parse_elf_needed` → `parse_elf_info`
67 (exports de `.dynsym` además de `DT_NEEDED`), expuesto como query **`exports:<artefacto>`**
68 (`crates/hammer-core/src/query.rs`). Validado end-to-end: 2873 símbolos extraídos de
69 `/lib/libc.so.6`. Fluye por el bus (`query expr`) sin cambios. Cero cambio en el build ni en
70 `hash_inputs`. Pendiente opcional: emitirlo como sidecar de metadata junto al artefacto sellado.
71- **Diferido (condicionado a verdes):** H3b (base content-addressed de funciones **wasm**), sólo
72 si H2b demuestra que el cómputo puro memoiza byte-idéntico. Si H3b se sostiene, *entonces* se
73 reabre la pregunta de colapsar los tres espacios — con evidencia, no con fe.
74- **La frontera de confianza no se mueve.** Igual que en H1/H2c: la IA no se auto-promueve;
75 un símbolo/función ajena direccionada por hash se **verifica reproduciéndola** en el primer uso
76 dudoso (modelo de SDD 09 aplicado al grano fino). No se confía en el resultado ajeno; se confía
77 en poder recomputarlo.
78- **No se promete** "una distro donde paquete = función = proceso" hasta que H3b lo demuestre
79 sobre wasm. Es la idea más disruptiva y la menos madura del SDD 15; se trata como tal.
80
81## Alternativas consideradas
82
831. **Adoptar Unison/su runtime tal cual.** Rechazada: arrastra un lenguaje y toolchain propios;
84 takana es lenguaje-agnóstico por diseño (ADR 0002/0003, recetas sobre fuente upstream). Sería
85 cambiar la tesis del proyecto.
862. **Reescribir takana para content-addressar AST de Rust.** Rechazada ahora: acopla la identidad
87 del artefacto a un lenguaje concreto y a un parser de AST frágil; rompe "recetas sobre fuente
88 upstream en cualquier lenguaje". Reevaluable sólo si H3b da señal fuerte.
893. **No registrar nada (esperar).** Rechazada: la visión orienta decisiones de diseño cercanas
90 (p.ej. mantener la procedencia como metadata fuera del hash desde ya deja la puerta abierta sin
91 costo). Registrarla barato es mejor que redescubrirla.
92
93## Referencias
94
95- SDD 15 §H3 (`docs/15-frontier-ai-native.md`) — la idea 3 y por qué es design-doc.
96- H2a — determinismo wasm (`tawasuyu/03_ukupacha/wawa/SDD-determinismo.md`): el grano fino wasm
97 de H3b depende de este verde.
98- `Recipe::hash_inputs` (`crates/hammer-core/src/recipe.rs:370`) — la identidad que NO se toca.
99- `parse_elf_needed` (`crates/hammer-core/src/query.rs:298`) — el parser a extender para la
100 procedencia por-símbolo (el puente barato).
101- ADR 0002 (alpine-first) / 0003 (zig-cc): la tesis lenguaje-agnóstica que Unison tensiona.
0009-content-addressed-code.md
ADR 0009 — Código direccionado por contenido (estilo Unison): registrar la visión, no reescribir la unidad
- Estado: propuesta (design-doc — registra una dirección, no compromete una reescritura)
- Fecha: 2026-07-03
- Frontera: SDD 15 §H3 (idea 3). Depende conceptualmente de [ADR pendiente H2] y del
determinismo wasm auditado en H2a (
tawasuyu/03_ukupacha/wawa/SDD-determinismo.md).
Contexto
takana y wawa ya direccionan por contenido, pero cosas distintas:
- takana hashea el artefacto compilado y la receta. La identidad de un artefacto es
ArtifactHash sobre las entradas canónicas de la receta (Recipe::hash_inputs,
crates/hammer-core/src/recipe.rs:370): source_id (commit git o sha256 del tarball),
compilador, target, link, zig_version, contenido de los patches, flags, overrides de fases.
Grano grueso, lenguaje-agnóstico: encaja con "recetas sobre fuente upstream".
- wawa hashea el módulo wasm y el objeto del grafo/almacén. Grano de módulo/objeto.
La idea 3 (Unison) empuja al límite: direccionar funciones por el hash de su AST. En
Unison, el código no vive en archivos sino en una base content-addressed donde cada definición
ES su hash; renombrar es metadata, actualizar es insertar una definición nueva (la vieja no se
rompe: quien la referenciaba sigue apuntando a su hash). El sueño para un agente de IA: no
editar archivos que se rompen entre sí, sino insertar definiciones en un espacio donde
nada se rompe por renombrar o actualizar. Paquete de takana, módulo wasm de wawa y función
de código colapsarían en un solo espacio de nombres: el hash.
Decisión
Registrar la visión y NO reescribir la unidad de compilación. Concretamente:
- No colapsar ahora artefacto/módulo/función en un solo tipo. takana sigue con grano de
artefacto; wawa con grano de módulo. La identidad content-addressed de cada uno queda intacta.
- Sí construir el puente barato: procedencia por-símbolo como metadata, derivada de lo
que ya sabemos leer, SIN tocar
hash_inputs ni la unidad de build. takana ya tiene un parser
ELF hand-rolled (parse_elf_needed, crates/hammer-core/src/query.rs:298) que extrae
DT_NEEDED (las libs dinámicas que un binario necesita) para la query depends:. Extenderlo
para emitir también los símbolos exportados (.dynsym) da, por artefacto, "qué provee y
qué necesita" — un grafo de símbolos content-addressed descriptivo, no normativo: es
metadata anexa a la receta/artefacto, no entra al hash de identidad (misma disciplina que el
bloque evidence de H1: describe, no identifica).
- Diferir el grano fino real (función-por-hash) a H3b, un experimento aislado sobre
wasm (un
.wasm por función pura del subconjunto determinista de H2), que es el
subconjunto de Unison que nuestro stack ya podría sostener (wasm + BLAKE3 + determinismo
H2a) sin un lenguaje nuevo. H3b es exploratorio y está gateado por H2 en verde.
Razones
- Es otro modelo de datos, no una extensión. takana content-addressa el artefacto compilado
(grano grueso, lenguaje-agnóstico); Unison el AST de cada función (grano fino, exige un
lenguaje y toolchain propios). Colapsarlos pide reescribir la unidad de compilación entera —
eso es un proyecto, no una fase. El ADR lo dice para no fingir que es una feature incremental.
- El valor es real pero el costo es un proyecto. El fin del dependency-hell para un agente
(insertar una definición nunca rompe a quien la usa) es exactamente lo que haría al bucle
agéntico de SDD 08 mucho más seguro. Pero comprometerse hoy a la reescritura del build sería
cambiar los cimientos por una apuesta no probada. Design-doc primero.
- El puente barato entrega valor sin apostar. La procedencia por-símbolo (paso 2) es útil
ya: alimenta queries "¿qué artefacto exporta
foo?", detección de colisiones de símbolos entre
paquetes, y una primera forma de "referencia por contenido" (un consumidor puede pinnear no el
paquete sino el símbolo+hash que usa). Todo reusando el parser ELF existente.
- Respeta la disciplina de identidad de takana. Nada de esto mueve
ArtifactHash: el
baseline de reproducibilidad (of_tree 9adefb82 / rust 7fa6cb4e) no se toca. La procedencia es
metadata, como la evidencia de H1.
Consecuencias
- Ahora (barato, sin apuesta) — IMPLEMENTADO (2026-07-03):
parse_elf_needed → parse_elf_info
(exports de .dynsym además de DT_NEEDED), expuesto como query exports:<artefacto>
(crates/hammer-core/src/query.rs). Validado end-to-end: 2873 símbolos extraídos de
/lib/libc.so.6. Fluye por el bus (query expr) sin cambios. Cero cambio en el build ni en
hash_inputs. Pendiente opcional: emitirlo como sidecar de metadata junto al artefacto sellado.
- Diferido (condicionado a verdes): H3b (base content-addressed de funciones wasm), sólo
si H2b demuestra que el cómputo puro memoiza byte-idéntico. Si H3b se sostiene, entonces se
reabre la pregunta de colapsar los tres espacios — con evidencia, no con fe.
- La frontera de confianza no se mueve. Igual que en H1/H2c: la IA no se auto-promueve;
un símbolo/función ajena direccionada por hash se verifica reproduciéndola en el primer uso
dudoso (modelo de SDD 09 aplicado al grano fino). No se confía en el resultado ajeno; se confía
en poder recomputarlo.
- No se promete "una distro donde paquete = función = proceso" hasta que H3b lo demuestre
sobre wasm. Es la idea más disruptiva y la menos madura del SDD 15; se trata como tal.
Alternativas consideradas
- Adoptar Unison/su runtime tal cual. Rechazada: arrastra un lenguaje y toolchain propios;
takana es lenguaje-agnóstico por diseño (ADR 0002/0003, recetas sobre fuente upstream). Sería
cambiar la tesis del proyecto.
- Reescribir takana para content-addressar AST de Rust. Rechazada ahora: acopla la identidad
del artefacto a un lenguaje concreto y a un parser de AST frágil; rompe "recetas sobre fuente
upstream en cualquier lenguaje". Reevaluable sólo si H3b da señal fuerte.
- No registrar nada (esperar). Rechazada: la visión orienta decisiones de diseño cercanas
(p.ej. mantener la procedencia como metadata fuera del hash desde ya deja la puerta abierta sin
costo). Registrarla barato es mejor que redescubrirla.
Referencias
- SDD 15 §H3 (
docs/15-frontier-ai-native.md) — la idea 3 y por qué es design-doc.
- H2a — determinismo wasm (
tawasuyu/03_ukupacha/wawa/SDD-determinismo.md): el grano fino wasm
de H3b depende de este verde.
Recipe::hash_inputs (crates/hammer-core/src/recipe.rs:370) — la identidad que NO se toca.
parse_elf_needed (crates/hammer-core/src/query.rs:298) — el parser a extender para la
procedencia por-símbolo (el puente barato).
- ADR 0002 (alpine-first) / 0003 (zig-cc): la tesis lenguaje-agnóstica que Unison tensiona.