El flujo GEUL es una secuencia de paquetes que comienza y termina con un Meta Node, constituyendo un documento GEUL completo.

Características principales

  • Límites explícitos: STREAM_START / STREAM_END (Meta Node)
  • Alcance de TID: Válido solo dentro del flujo
  • Referencia directa: Solo se pueden referenciar TIDs ya declarados
  • Big Endian: Network Byte Order

Estructura del flujo

┌─────────────────────────────────────┐
│          STREAM_START               │  ← Obligatorio (Meta Node)
│          (declaración de ancho TID) │     0xC000 (TID de 16 bits)
├─────────────────────────────────────┤
│          Metadatos (opcional)       │
│          - VERSION    (0xC014)      │
│          - CREATED_AT (0xC008)      │
│          - CREATOR    (0xC010)      │
├─────────────────────────────────────┤
│          Paquetes del cuerpo        │
│          - Entity Node              │
│          - Quantity Node            │
│          - Verb Edge                │
│          - Triple Edge              │
│          - Event6 Edge              │
│          - Clause Edge              │
│          - Context Edge             │
│          - Group Edge               │
│          - Faber Edge               │
├─────────────────────────────────────┤
│          STREAM_END                 │  ← Opcional (recomendado)
└─────────────────────────────────────┘

El flujo mínimo es STREAM_START(1 palabra) + STREAM_END(1 palabra) = 2 palabras (4 bytes); incluso un flujo vacío es válido.

Principios de asignación de TID

ReglaDescripción
ObligatoriedadCada Edge/Node en el flujo tiene un TID
UnicidadLos TIDs son únicos dentro del flujo
AlcanceLos TIDs solo son válidos dentro de su flujo
Dirección directaSolo se pueden referenciar TIDs ya declarados en el momento de la referencia

Posición de TID

TipoPosición del TIDPosición de referencia
Meta NodeNo tieneNo tiene
Entity NodeÚltima palabraNo tiene
Quantity NodeÚltima palabraNo tiene
Tiny Verb EdgeNo tieneNo tiene (inline)
Verb EdgeÁrea de HeaderDespués del Payload
Triple EdgeÁrea de HeaderDespués del Payload
Event6 EdgeÁrea de HeaderDespués del Payload
Clause EdgeÁrea de HeaderDespués del Payload
Context EdgeÁrea de HeaderDespués del Payload
Group Edge2da palabra3ra+ palabra

Los Nodes solo se definen a sí mismos, por lo que el TID va al final; los Edges referencian otros TIDs, por lo que el TID va antes que las referencias.

TIDs reservados

TIDUso
0x0000Marcador de terminación (Group Edge, etc.)
0xFFFFReservado (base de 16 bits)

Reglas de orden de paquetes

Orden declaración-referencia

Correcto:
  [Entity: Juan, TID=0x0001]
  [Entity: María, TID=0x0002]
  [Verb Edge: encontrarse, Subject=0x0001, Object=0x0002]

Incorrecto:
  [Verb Edge: encontrarse, Subject=0x0001, Object=0x0002]  ← 0x0001 no declarado
  [Entity: Juan, TID=0x0001]
  [Entity: María, TID=0x0002]

Orden recomendado

1. STREAM_START
2. Metadatos (VERSION, CREATED_AT, CREATOR)
3. Entity Nodes (declaración de entidades)
4. Quantity Nodes (cantidades/literales)
5. Group Edges (definición de grupos)
6. Tiny Verb Edges (predicados inline)
7. Verb Edges (predicados generales)
8. Triple Edges (propiedades/relaciones)
9. Event6 Edges (eventos)
10. Clause Edges (relaciones discursivas)
11. Context Edges (contexto)
12. Faber Edges (código/AST)
13. STREAM_END

Es solo el orden recomendado; se pueden organizar libremente mientras se respete la regla de declaración-referencia.

Prohibición de referencias circulares

Las referencias circulares de tipo A → B → A no son posibles. Si se necesitan relaciones circulares, se expresan con Edges separados.

Posible:
  [Entity A, TID=0x0001]
  [Entity B, TID=0x0002]
  [Edge: A→B, TID=0x0003]
  [Edge: B→A, TID=0x0004]

Ejemplo de flujo

“Juan se encontró con María”

1. STREAM_START (TID 16 bits)
   0xC0 0x00

2. Entity: Juan (TID=0x0001)
   [Paquete Entity...] 0x00 0x01

3. Entity: María (TID=0x0002)
   [Paquete Entity...] 0x00 0x02

4. Verb Edge: meet (TID=0x0100)
   Subject: 0x0001
   Object: 0x0002

5. STREAM_END
   0xC0 0x04

“Juan y María se encontraron en el colegio”

1. STREAM_START
   0xC0 0x00

2. Entity: Juan (TID=0x0001)
3. Entity: María (TID=0x0002)
4. Entity: Colegio (TID=0x0003)

5. Group Edge: AND (TID=0x0010)
   Miembros: 0x0001, 0x0002, 0x0000 (terminación)

6. Verb Edge: meet (TID=0x0100)
   Subject: 0x0010 (grupo)
   Location: 0x0003

7. STREAM_END
   0xC0 0x04

Validación de flujo

Validación obligatoria

ElementoVerificación
Inicio¿Comienza con STREAM_START?
Unicidad de TID¿No hay TIDs duplicados?
Validez de referencia¿Todos los TIDs referenciados están declarados?
Dirección directa¿Los TIDs estaban declarados en el momento de la referencia?

Código de validación

def validate_stream(packets: list) -> dict:
    """Validación del flujo"""
    errors = []
    declared_tids = set()

    # Validación de inicio
    if not packets or packets[0].type != "STREAM_START":
        errors.append("El flujo no comienza con STREAM_START")

    for packet in packets:
        # Validación de unicidad de TID
        if packet.tid is not None:
            if packet.tid in declared_tids:
                errors.append(f"TID duplicado: {packet.tid}")
            declared_tids.add(packet.tid)

        # Validación de referencias
        for ref_tid in packet.references:
            if ref_tid not in declared_tids:
                errors.append(f"Referencia a TID no declarado: {ref_tid}")

    return {
        "valid": len(errors) == 0,
        "errors": errors,
        "tid_count": len(declared_tids)
    }

Flujos múltiples

Cada flujo es independiente, y el alcance de TID está separado por flujo. El TID=0x0001 del Flujo A y el TID=0x0001 del Flujo B son entidades diferentes.

Las referencias cruzadas entre flujos (Cross-reference) no están soportadas actualmente; se podrán extender en el futuro con la introducción de IDs de flujo y mecanismos de Import/Export.