diff --git a/crates/hammer-core/src/kernel/contract.rs b/crates/hammer-core/src/kernel/contract.rs index 2fdb3e4d..47350024 100644 --- a/crates/hammer-core/src/kernel/contract.rs +++ b/crates/hammer-core/src/kernel/contract.rs @@ -413,7 +413,17 @@ profile = "anfitrion" ); } for cap in &c.capabilities { - assert!(!cap.symbols.is_empty(), "{} no declara símbolos", cap.id); + // Una capacidad SIN símbolos es legítima sólo si es de INTERFAZ: algo que el kernel da + // siempre a partir de cierta versión y que ningún `CONFIG_*` enciende ni apaga (pidfd + // desde 5.3). Entra al contrato igual, porque el contrato es la lista de lo que se USA + // —no la de lo que puede faltar— y es la línea que lo dice si mañana baja el mínimo de + // kernel. Pero entonces TIENE que nombrar la interfaz: sin símbolos ni interfaz, la + // capacidad no afirma nada comprobable y lo más probable es que sea un campo a medias. + assert!( + !cap.symbols.is_empty() || !cap.interface.is_empty(), + "{} no declara símbolos NI interfaz: no afirma nada comprobable", + cap.id + ); assert!(!cap.consumer.trim().is_empty(), "{} no declara consumidor", cap.id); } }