chore: monorepo inicial con arje + minga + yahweh absorbidos
Workspace en 4 ejes (core/modules/apps/shared):
- core/: 24 crates de arje (Init systemd-compatible: ente-card, ente-zero,
ente-kernel, ente-bus, ente-cas, ente-soma, ente-wasm, ente-snapshot,
ente-brain, ente-echo, ente-policy-provider, + 12 crates *-compat)
- modules/semantic_dht/: 5 crates de minga (minga-core con AST/CAS/MST,
minga-p2p con libp2p Kad, minga-store, minga-vfs, minga-cli)
- modules/ui_engine/: 11 crates de yahweh (libs/{core,theme,bus,providers},
widgets/{tree,splitter,tabs,tiled,container_core,text_input})
- apps/: 5 crates de yahweh (file_explorer, database_explorer, text_viewer,
image_viewer, yahweh-shell)
- shared_wit/protocol.wit: handshake/lifecycle inicial
Cargo.toml unificado: thiserror bumped a 2 (transparente para arje), tokio
"full", paths intra-workspace de yahweh redirigidos a su nueva ubicación.
cargo check --workspace: 0 errores, 17 warnings (dead code preexistente).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
# ============================================================================
|
||||
# rule.k — REFERENCE ONLY. NOT LOADED.
|
||||
#
|
||||
# La gramática autoritativa de Rule vive en Rust:
|
||||
# crates/ente-brain/src/rules.rs
|
||||
# El loader (crates/ente-brain/src/loader.rs) sólo acepta JSON / JSONL.
|
||||
#
|
||||
# Conservado como notas de diseño humano-legibles del shape Rule:
|
||||
# Triplet [Sujeto + Evento + Acción(Objeto)]. Cada regla es una sinapsis:
|
||||
# cuando ocurre `when`, el motor ejecuta `then` para los Entes que cumplen
|
||||
# `scope`. El motor las indexa por discriminante de EventKind para lookup
|
||||
# en O(1). Las reglas son inmutables tras carga (Arc<Rule>).
|
||||
#
|
||||
# Si cambias el shape en Rust, sincroniza este archivo a mano (o
|
||||
# reemplázalo por JSON Schema generado vía `schemars`).
|
||||
# ============================================================================
|
||||
|
||||
schema Rule:
|
||||
"""Una sinapsis del fractal. Determinista, sin estado entre disparos."""
|
||||
id: str # Ulid 26 chars
|
||||
priority: int = 5 # 0..255, mayor = se ejecuta primero
|
||||
when: EventPattern
|
||||
then: [Action]
|
||||
scope: Scope = Scope {} # qué Entes son sujetos válidos
|
||||
|
||||
check:
|
||||
len(id) == 26, "id debe ser Ulid"
|
||||
priority >= 0 and priority <= 255, "priority fuera de rango"
|
||||
len(then) > 0, "regla sin acciones"
|
||||
|
||||
|
||||
# ---------- Subject: alcance del sujeto ----------
|
||||
|
||||
schema Scope:
|
||||
"""Match del sujeto. None en todos los campos = match cualquier Ente."""
|
||||
subject_id?: str # Ulid exacto
|
||||
subject_label?: str # label exacto
|
||||
subject_has_cap?: Capability # Ente que declara esta capacidad
|
||||
|
||||
check:
|
||||
subject_id is None or len(subject_id) == 26, "subject_id no es Ulid"
|
||||
|
||||
|
||||
# ---------- Event: qué dispara la regla ----------
|
||||
|
||||
# EventPattern es tagged union recursivo.
|
||||
#
|
||||
# Atómicos:
|
||||
# Single — match un evento por kind
|
||||
# Sequence — N eventos consecutivos dentro de within_ms
|
||||
#
|
||||
# Compuestos (recursivos):
|
||||
# Either — OR sobre sub-patterns
|
||||
# All — AND sobre sub-patterns (mismo event/history)
|
||||
schema EventPattern:
|
||||
type: "Single" | "Sequence" | "Either" | "All"
|
||||
kind?: EventKind # Single
|
||||
kinds?: [EventKind] # Sequence
|
||||
within_ms?: int = 0
|
||||
patterns?: [EventPattern] # Either / All (recursivo)
|
||||
|
||||
check:
|
||||
type != "Single" or kind is not None, "Single requiere kind"
|
||||
type != "Sequence" or (kinds is not None and len(kinds) > 0), \
|
||||
"Sequence requiere kinds no vacío"
|
||||
type != "Either" or (patterns is not None and len(patterns) > 0), \
|
||||
"Either requiere patterns no vacío"
|
||||
type != "All" or (patterns is not None and len(patterns) > 0), \
|
||||
"All requiere patterns no vacío"
|
||||
within_ms is None or within_ms >= 0, "within_ms negativo"
|
||||
|
||||
|
||||
# EventKind con tag interno + payload opcional según tag.
|
||||
schema EventKind:
|
||||
tag: "EnteSpawned" | "EnteDied" | "BusAnnounce" | "BusInvoke" | "BusInvokeOf" | "DeviceAdded" | "DeviceRemoved" | "Custom"
|
||||
cap?: Capability # para BusInvokeOf
|
||||
custom?: str # para Custom
|
||||
|
||||
check:
|
||||
tag != "BusInvokeOf" or cap is not None, "BusInvokeOf requiere cap"
|
||||
tag != "Custom" or custom is not None, "Custom requiere custom string"
|
||||
|
||||
|
||||
# ---------- Action: qué hacer ----------
|
||||
|
||||
schema Action:
|
||||
"""Una acción ejecutable por el motor. Tagged union con kind."""
|
||||
kind: "Log" | "Notify" | "Spawn" | "Invoke" | "Inhibit"
|
||||
# Log
|
||||
level?: "trace" | "debug" | "info" | "warn" | "error"
|
||||
message?: str
|
||||
# Notify
|
||||
target_id?: str # Ulid
|
||||
# Spawn
|
||||
card_blob?: str # base64-encoded EntityCard JSON
|
||||
# Invoke
|
||||
target_cap?: Capability
|
||||
blob_b64?: str
|
||||
# Inhibit
|
||||
reason?: str
|
||||
|
||||
check:
|
||||
kind != "Log" or message is not None, "Log requiere message"
|
||||
kind != "Notify" or (target_id is not None and message is not None), \
|
||||
"Notify requiere target_id + message"
|
||||
kind != "Spawn" or card_blob is not None, "Spawn requiere card_blob"
|
||||
kind != "Invoke" or target_cap is not None, "Invoke requiere target_cap"
|
||||
kind != "Inhibit" or reason is not None, "Inhibit requiere reason"
|
||||
|
||||
|
||||
# ---------- Capability: re-export desde card.k para evitar inclusión circular ----------
|
||||
|
||||
# En uso real: `import ..ente_card.schema.card` y referencia Capability.
|
||||
# Aquí declaramos una versión alineada para auto-contención del esquema.
|
||||
schema Capability:
|
||||
kind: "FilesystemRoot" | "KernelNetlink" | "Endpoint" | "LegacyLogind" | "Device" | "Spawn" | "Journal"
|
||||
netlink_family?: "Uevent" | "Route" | "Generic" | "Audit"
|
||||
endpoint_interface?: str
|
||||
endpoint_version?: int
|
||||
device_class?: "Block" | "Tty" | "Input" | "Drm" | "Net" | "Hidraw"
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Ejemplo de regla cristalizada (auto-generada por el observador)
|
||||
# ============================================================================
|
||||
|
||||
example_rule = Rule {
|
||||
id = "01KQQ100000000000000000000"
|
||||
priority = 5
|
||||
when = EventPattern {
|
||||
type = "Single"
|
||||
kind = EventKind {tag = "EnteSpawned"}
|
||||
}
|
||||
scope = Scope {
|
||||
subject_label = "demo-echo"
|
||||
}
|
||||
then = [
|
||||
Action {
|
||||
kind = "Log"
|
||||
level = "info"
|
||||
message = "demo-echo encarnado, observando para crystallization"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Ejemplo de regla compuesta: cuando un Ente se anuncia y luego es invocado
|
||||
# en menos de 500ms, log estructurado para auditoría.
|
||||
example_sequence = Rule {
|
||||
id = "01KQQ200000000000000000000"
|
||||
priority = 7
|
||||
when = EventPattern {
|
||||
type = "Sequence"
|
||||
kinds = [
|
||||
EventKind {tag = "BusAnnounce"}
|
||||
EventKind {tag = "BusInvoke"}
|
||||
]
|
||||
within_ms = 500
|
||||
}
|
||||
scope = Scope {}
|
||||
then = [
|
||||
Action {
|
||||
kind = "Log"
|
||||
level = "info"
|
||||
message = "patrón Announce→Invoke detectado <500ms"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user