# Tipo: ParseResult / ResourceNode / NodeType

Fuente conceptual: OpenViking `openviking/parse/base.py` (AGPL-3.0)
Reimplementar desde cero. No copiar codigo.

## Tipos a implementar

### 1. NodeType (enum)

- **Dominio:** core
- **Lang:** Python
- **Algebraic:** sum
- **Definicion:**
  ```python
  class NodeType(Enum):
      ROOT = "root"
      SECTION = "section"
  ```
- **Descripcion:** Tipos de nodo en un arbol de documento parseado. Solo ROOT y SECTION — todo el contenido detallado (parrafos, code blocks, tablas, listas) permanece como markdown dentro del campo content del nodo.
- **Notas:** Diseno intencionalmente simple. Evita decomposicion fina de nodos (no hay PARAGRAPH, CODE_BLOCK, TABLE, etc.) — el contenido se preserva en formato markdown.

### 2. ResourceNode (product)

- **Dominio:** core
- **Lang:** Python
- **Algebraic:** product
- **Definicion:**
  ```python
  @dataclass
  class ResourceNode:
      type: NodeType
      title: str | None = None
      level: int = 0                          # 0=root, 1=top section, etc.
      content: str = ""                       # markdown content de este nodo
      children: list["ResourceNode"] = field(default_factory=list)
      meta: dict[str, Any] = field(default_factory=dict)
  ```
- **Metodos:**
  - `add_child(child: ResourceNode) -> None`
  - `get_text(include_children: bool = True) -> str` — contenido concatenado recursivo
  - `get_abstract(max_length: int = 256) -> str` — resumen corto (title o primeros N chars)
  - `get_overview(max_length: int = 4000) -> str` — overview con lista de children
  - `to_dict() -> dict` — serializacion recursiva
  - `from_dict(data: dict) -> ResourceNode` — deserializacion (classmethod)
- **Descripcion:** Nodo en un arbol jerarquico de documento. Preserva la estructura natural del documento (secciones, subsecciones) sin perder contenido. Cada nodo puede tener hijos (subsecciones) y metadata.
- **Uso:** Resultado intermedio de parsing. Los parsers (markdown, pdf, html, docx) producen arboles de ResourceNode.

### 3. ParseResult (product)

- **Dominio:** core
- **Lang:** Python
- **Algebraic:** product
- **Definicion:**
  ```python
  @dataclass
  class ParseResult:
      root: ResourceNode
      source_path: str | None = None
      source_format: str | None = None        # "pdf", "markdown", "html", "docx", etc.
      parser_name: str | None = None           # "PDFParser", "MarkdownParser", etc.
      parser_version: str | None = None
      parse_time: float | None = None          # segundos
      parse_timestamp: datetime | None = None
      meta: dict[str, Any] = field(default_factory=dict)
      warnings: list[str] = field(default_factory=list)
  ```
- **Metodos:**
  - `success -> bool` (property) — True si no hay warnings
  - `get_all_nodes() -> list[ResourceNode]` — flatten recursivo del arbol
  - `get_sections(min_level=0, max_level=10) -> list[ResourceNode]` — filtrar secciones por nivel
- **Descripcion:** Resultado completo de parsear un documento. Contiene el arbol de nodos, metadata del proceso, y warnings. Es el tipo de retorno unificado de todos los parsers.
- **Helper:**
  ```python
  def create_parse_result(root, source_path=None, source_format=None, 
                          parser_name=None, parse_time=None, meta=None, 
                          warnings=None) -> ParseResult
  ```
