architect/arh/standards/structure-old/TREE_REPRESENTATION.md

ДРЕВОВИДНОЕ ПРЕДСТАВЛЕНИЕ ИЕРАРХИИ

Версия: 1.0.0
Дата: 2025-12-22
Уровень: L2 (Стандарт)
Статус: CANONICAL


ОБЗОР

Представление всей системной иерархии в виде дерева:
- Простое дерево (single parent)
- Граф зависимостей (multiple parents)
- Бинарное дерево (для алгоритмов)


1. ПРОСТОЕ ИЕРАРХИЧЕСКОЕ ДЕРЕВО

Базовая структура

NODE {
  id: UUID,
  name: STRING,
  type: NODE_TYPE,
  parent: UUID | null,
  children: [UUID],
  level: INTEGER,
  path: STRING,          // Полный путь от корня
  metadata: MAP
}

Инварианты простого дерева

1. У каждого узла ровно один родитель (кроме корня)
2. Корень не имеет родителя (parent = null)
3. Листья не имеют детей (children = [])
4. Нет циклов
5. Уровень ребенка = уровень родителя + 1

2. ПОЛНОЕ ДЕРЕВО СИСТЕМЫ

Дерево сущностей платформы

UNIVERSE ()

└─── WORKSPACE (L0)
        id: root
        path: /
     
     ├─── architect/ (L1, Информационная)
            id: arch-001
            path: /architect
            type: knowledge_base
            role: INFORMATIONAL
         
         ├─── theory/ (документы)
             ├─── MERKABA.md
             ├─── QUESTIONS.md
             └─── SYSTEMS.md
         
         ├─── concept/ (документы)
             ├─── PLATFORM.md
             └─── ROLES.md
         
         └─── standards/ (документы)
              ├─── PRINCIPLES.md
              ├─── structure/
                  ├─── ENTITY_HIERARCHY.md
                  ├─── ENTITY_CATALOG.md
                  └─── UNIVERSAL_SCHEMA.md
              └─── types/
     
     ├─── infra/ (L1, Обеспечивающая)
            id: infra-001
            path: /infra
            role: SUPPORTING
         
         ├─── @beget-kondurov.server/ (L3, Модуль)
                id: server-001
                type: server
                status: production
             
             └─── solution/
                  └─── configs/
         
         ├─── @dev-pro.server/ (L3)
         └─── @router.network/ (L3)
     
     ├─── system/ (L1, Обеспечивающая)
            id: sys-001
            path: /system
            role: SUPPORTING
         
         ├─── @hub.service/ (L3, Сервис)
                type: storage_service
                provides: S3-compatible storage
             
             └─── solution/
                  └─── minio/
         
         ├─── @orchestrator.service/ (L3)
         └─── @monitor.service/ (L3)
     
     └─── projects/ (контейнер)
          
          ├─── pirotehnika/ (L1, Целевая)
                 id: piro-001
                 path: /projects/pirotehnika
                 type: business
                 role: TARGET
                 questions: 9
              
              ├─── [ФАЙЛЫ]
                  ├─── CLAUDE.md
                  ├─── index.yaml
                  └─── PROJECT.md (9 вопросов)
              
              ├─── design/
                  ├─── STRATEGY.md
                  └─── BUSINESS_MODEL.md
              
              ├─── management/
                  ├─── STATUS.md
                  └─── TODO.md
              
              ├─── _shared/ (данные)
                  └─── data/
              
              ├─── retail/ (L2, Направление, Целевая)
                     id: piro-retail-001
                     path: /projects/pirotehnika/retail
                     role: main
                     questions: 9
                  
                  ├─── [ФАЙЛЫ]
                      ├─── CLAUDE.md
                      └─── index.yaml
                  
                  ├─── @pirotehnika.spb.ru/ (L3, Модуль, Целевая)
                         id: piro-site-001
                         path: /projects/pirotehnika/retail/@pirotehnika.spb.ru
                         type: site
                         status: production
                      
                      ├─── [ФАЙЛЫ]
                          ├─── CLAUDE.md
                          └─── index.yaml
                      
                      ├─── solution/ (КОД)
                          ├─── src/
                          ├─── config/
                          └─── README.md
                      
                      └─── management/
                           └─── TODO.md
                                
                                ├─── ЗАДАЧА #1 (L4)
                                    id: task-001
                                    title: "Добавить фильтр"
                                    status: in_progress
                                
                                ├─── ЗАДАЧА #2 (L4)
                                └─── ЗАДАЧА #3 (L4)
                  
                  ├─── @admin.app/ (L3)
                  └─── _data/ (данные направления)
              
              ├─── ozon/ (L2, Направление, Целевая)
                     role: satellite
                     parent: retail
                  
                  └─── @ozon.api/ (L3, Модуль, Обеспечивающая)
                          type: api
                          questions: 7
                       
                       └─── solution/
              
              ├─── data/ (L2, Направление, Информационная)
                     role: service
                     questions: 5
                  
                  └─── nocodb/
                       ├─── schema.sql
                       └─── scripts/
              
              └─── services/ (L2, Направление, Обеспечивающая)
                      role: service
                      questions: 7
                   
                   └─── @pim.service/ (L3, Модуль, Обеспечивающая)
                           type: service
                           status: production
                        
                        ├─── solution/
                            ├─── app/
                            ├─── scripts/
                                ├─── sync_all_fields_to_1c.py
                                └─── scrape_producer_sites.py
                            └─── config/
                                 └─── pim_1c_mapping.yaml
                        
                        └─── management/
          
          ├─── lideravto/ (L1, Целевая)
              └─── ...
          
          └─── content-factory/ (L1, Целевая)
               └─── ...

3. ПРЕДСТАВЛЕНИЕ В ВИДЕ СПИСКА СМЕЖНОСТИ

Структура данных

tree = {
    "root": {
        "id": "root",
        "name": "WORKSPACE",
        "type": "workspace",
        "level": 0,
        "parent": None,
        "children": ["arch-001", "infra-001", "sys-001", "projects"],
        "path": "/",
        "metadata": {}
    },

    "arch-001": {
        "id": "arch-001",
        "name": "architect",
        "type": "knowledge_base",
        "level": 1,
        "parent": "root",
        "children": ["arch-theory", "arch-concept", "arch-standards"],
        "path": "/architect",
        "metadata": {
            "role": "INFORMATIONAL",
            "questions": 5
        }
    },

    "piro-001": {
        "id": "piro-001",
        "name": "pirotehnika",
        "type": "business",
        "level": 1,
        "parent": "projects",
        "children": ["piro-retail-001", "piro-ozon-001", "piro-data", "piro-services"],
        "path": "/projects/pirotehnika",
        "metadata": {
            "role": "TARGET",
            "questions": 9,
            "status": "active"
        }
    },

    "piro-retail-001": {
        "id": "piro-retail-001",
        "name": "retail",
        "type": "direction",
        "level": 2,
        "parent": "piro-001",
        "children": ["piro-site-001", "piro-admin-001"],
        "path": "/projects/pirotehnika/retail",
        "metadata": {
            "role": "TARGET",
            "questions": 9,
            "direction_role": "main"
        }
    },

    "piro-site-001": {
        "id": "piro-site-001",
        "name": "@pirotehnika.spb.ru",
        "type": "module",
        "level": 3,
        "parent": "piro-retail-001",
        "children": ["task-001", "task-002", "task-003"],
        "path": "/projects/pirotehnika/retail/@pirotehnika.spb.ru",
        "metadata": {
            "role": "TARGET",
            "questions": 9,
            "module_type": "site",
            "status": "production"
        }
    },

    "task-001": {
        "id": "task-001",
        "name": "Добавить фильтр по цене",
        "type": "task",
        "level": 4,
        "parent": "piro-site-001",
        "children": [],
        "path": "/projects/pirotehnika/retail/@pirotehnika.spb.ru/TODO.md#task-001",
        "metadata": {
            "status": "in_progress",
            "priority": "P0",
            "assignee": "owner"
        }
    }
}

4. ОПЕРАЦИИ НАД ДЕРЕВОМ

4.1. Навигация

# Получить родителя
def get_parent(node_id: str) -> Node:
    node = tree[node_id]
    return tree[node.parent] if node.parent else None

# Получить детей
def get_children(node_id: str) -> List[Node]:
    node = tree[node_id]
    return [tree[child_id] for child_id in node.children]

# Получить путь до корня
def get_path_to_root(node_id: str) -> List[Node]:
    path = []
    current = node_id
    while current:
        node = tree[current]
        path.append(node)
        current = node.parent
    return list(reversed(path))

# Получить всех потомков (рекурсивно)
def get_descendants(node_id: str) -> List[Node]:
    descendants = []
    node = tree[node_id]

    for child_id in node.children:
        descendants.append(tree[child_id])
        descendants.extend(get_descendants(child_id))

    return descendants

# Получить глубину поддерева
def get_depth(node_id: str) -> int:
    node = tree[node_id]
    if not node.children:
        return 0

    return 1 + max(get_depth(child_id) for child_id in node.children)

# Получить все узлы уровня L
def get_nodes_at_level(level: int) -> List[Node]:
    return [node for node in tree.values() if node.level == level]

4.2. Поиск

# Поиск по имени
def find_by_name(name: str) -> List[Node]:
    return [node for node in tree.values() if name in node.name]

# Поиск по типу
def find_by_type(node_type: str) -> List[Node]:
    return [node for node in tree.values() if node.type == node_type]

# Поиск по пути
def find_by_path(path: str) -> Node:
    for node in tree.values():
        if node.path == path:
            return node
    return None

# Поиск по метаданным
def find_by_metadata(key: str, value: Any) -> List[Node]:
    return [node for node in tree.values()
            if node.metadata.get(key) == value]

4.3. Обход дерева

# DFS (Depth-First Search) - обход в глубину
def dfs(node_id: str, visit_fn: Callable):
    node = tree[node_id]
    visit_fn(node)

    for child_id in node.children:
        dfs(child_id, visit_fn)

# BFS (Breadth-First Search) - обход в ширину
def bfs(node_id: str, visit_fn: Callable):
    queue = [node_id]

    while queue:
        current_id = queue.pop(0)
        node = tree[current_id]
        visit_fn(node)

        queue.extend(node.children)

# Пример: вывести все узлы
def print_tree(node_id: str, indent: int = 0):
    node = tree[node_id]
    print("  " * indent + f"└─ {node.name} ({node.type}, L{node.level})")

    for child_id in node.children:
        print_tree(child_id, indent + 1)

5. БИНАРНОЕ ПРЕДСТАВЛЕНИЕ

Для алгоритмов требующих бинарное дерево (2 ребенка max).

5.1. Преобразование N-арного дерева в бинарное

Метод: Left-Child Right-Sibling (LCRS)

N-арное дерево:
        A
     /  |  \
    B   C   D
   / \      |
  E   F     G

Бинарное дерево (LCRS):
        A
       /
      B
     / \
    E   C
     \   \
      F   D
          /
         G

Правило:
- Левый ребенок (left) = первый ребенок узла
- Правый ребенок (right) = следующий сосед (sibling)

5.2. Структура бинарного узла

class BinaryNode:
    def __init__(self, value, left=None, right=None):
        self.value = value      # Данные узла
        self.left = left        # Первый ребенок
        self.right = right      # Следующий сосед

    def __repr__(self):
        return f"Node({self.value})"

5.3. Конвертация

def to_binary_tree(node_id: str) -> BinaryNode:
    """Конвертировать N-арное дерево в бинарное (LCRS)"""
    node = tree[node_id]
    binary = BinaryNode(node)

    if not node.children:
        return binary

    # Первый ребенок → left
    binary.left = to_binary_tree(node.children[0])

    # Остальные дети → цепочка через right
    current = binary.left
    for child_id in node.children[1:]:
        current.right = to_binary_tree(child_id)
        current = current.right

    return binary

5.4. Пример преобразования

Исходное дерево:
WORKSPACE
├── architect
│   ├── theory
│   ├── concept
│   └── standards
├── infra
└── projects
    └── pirotehnika
        ├── retail
        └── ozon

Бинарное дерево (LCRS):
WORKSPACE (left=architect, right=null)
    ├── left: architect (left=theory, right=infra)
    │   ├── left: theory (left=null, right=concept)
    │   │   └── right: concept (left=null, right=standards)
    │   │       └── right: standards (left=null, right=null)
    │   └── right: infra (left=null, right=projects)
    │       └── right: projects (left=pirotehnika, right=null)
    │           └── left: pirotehnika (left=retail, right=null)
    │               └── left: retail (left=null, right=ozon)
    │                   └── right: ozon (left=null, right=null)

6. ГРАФ ЗАВИСИМОСТЕЙ (Multi-Parent)

В реальности узлы могут зависеть друг от друга, создавая DAG (Directed Acyclic Graph).

6.1. Структура узла с зависимостями

node = {
    "id": "piro-site-001",
    "name": "@pirotehnika.spb.ru",

    # Иерархическая связь (один родитель)
    "parent": "piro-retail-001",
    "children": [],

    # Функциональные зависимости (много родителей)
    "depends_on": [
        "piro-pim-001",       # PIM сервис
        "infra-beget-001",    # Сервер
        "sys-hub-001"         # Hub для медиа
    ],

    # Кому предоставляет сервисы
    "provides_to": [],

    # Что использует (ресурсы)
    "uses": [
        "piro-shared-data",   # Общие данные
        "piro-assets"         # Ассеты
    ]
}

6.2. Полный граф зависимостей

Иерархия (родитель-ребенок):
    pirotehnika
    └── retail
        └── @site

Функциональные зависимости:
    @site depends_on @pim.service
    @site depends_on @beget.server
    @site uses _shared/

    @pim.service provides_to @site
    @pim.service provides_to @ozon.api

    @ozon.api depends_on @pim.service

Граф (все связи):
    pirotehnika (L1)
    
    ├─[contains]─→ retail (L2)
                  
                  ├─[contains]─→ @site (L3)
                                
                                ├─[depends_on]─→ @pim.service (L3)
                                ├─[depends_on]─→ @beget.server (L3)
                                └─[uses]────────→ _shared/
                  
                  └─[contains]─→ @ozon.api (L3)
                                 └─[depends_on]─→ @pim.service
    
    └─[contains]─→ services (L2)
                   └─[contains]─→ @pim.service (L3)
                                  ├─[provides_to]─→ @site
                                  └─[provides_to]─→ @ozon.api

6.3. Топологическая сортировка

Для определения порядка сборки/деплоя по зависимостям:

def topological_sort(graph: Dict) -> List[str]:
    """Топологическая сортировка DAG"""
    # Подсчёт входящих рёбер
    in_degree = {node: 0 for node in graph}
    for node in graph:
        for dep in graph[node].get('depends_on', []):
            in_degree[dep] += 1

    # Очередь узлов без зависимостей
    queue = [node for node in graph if in_degree[node] == 0]
    result = []

    while queue:
        node = queue.pop(0)
        result.append(node)

        # Уменьшить счётчик для зависимых
        for dep in graph[node].get('depends_on', []):
            in_degree[dep] -= 1
            if in_degree[dep] == 0:
                queue.append(dep)

    # Проверка на циклы
    if len(result) != len(graph):
        raise Exception("Граф содержит циклы!")

    return result

# Результат: порядок деплоя
# [@beget.server, @pim.service, @site, @ozon.api]

7. СЕРИАЛИЗАЦИЯ И ХРАНЕНИЕ

7.1. JSON представление

{
  "tree_version": "1.0",
  "root_id": "root",
  "nodes": {
    "root": {
      "id": "root",
      "name": "WORKSPACE",
      "type": "workspace",
      "level": 0,
      "parent": null,
      "children": ["arch-001", "infra-001", "projects"],
      "path": "/",
      "metadata": {}
    },
    "piro-001": {
      "id": "piro-001",
      "name": "pirotehnika",
      "type": "business",
      "level": 1,
      "parent": "projects",
      "children": ["piro-retail-001", "piro-services"],
      "path": "/projects/pirotehnika",
      "metadata": {
        "role": "TARGET",
        "questions": 9,
        "status": "active"
      }
    }
  },
  "edges": [
    {
      "type": "contains",
      "source": "root",
      "target": "arch-001"
    },
    {
      "type": "depends_on",
      "source": "piro-site-001",
      "target": "piro-pim-001"
    }
  ]
}

7.2. SQL схема

CREATE TABLE nodes (
    id UUID PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    type VARCHAR(50) NOT NULL,
    level INTEGER NOT NULL,
    parent_id UUID REFERENCES nodes(id),
    path TEXT NOT NULL,
    metadata JSONB,
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE edges (
    id UUID PRIMARY KEY,
    type VARCHAR(50) NOT NULL,
    source_id UUID REFERENCES nodes(id),
    target_id UUID REFERENCES nodes(id),
    properties JSONB,
    created_at TIMESTAMP DEFAULT NOW()
);

-- Индексы
CREATE INDEX idx_nodes_parent ON nodes(parent_id);
CREATE INDEX idx_nodes_level ON nodes(level);
CREATE INDEX idx_nodes_type ON nodes(type);
CREATE INDEX idx_nodes_path ON nodes(path);
CREATE INDEX idx_edges_source ON edges(source_id);
CREATE INDEX idx_edges_target ON edges(target_id);
CREATE INDEX idx_edges_type ON edges(type);

8. ВИЗУАЛИЗАЦИЯ

8.1. ASCII Tree

WORKSPACE

├─┬ architect (L1)
 ├── theory/
 ├── concept/
 └── standards/

├─┬ infra (L1)
 ├── @beget.server (L3)
 └── @dev-pro.server (L3)

└─┬ projects
  
  └─┬ pirotehnika (L1)
    
    ├─┬ retail (L2)
     ├─┬ @site (L3)
      ├── #task-1 (L4)
      └── #task-2 (L4)
     └── @admin (L3)
    
    └─┬ services (L2)
      └─┬ @pim.service (L3)
        └── #task-5 (L4)

8.2. Graphviz DOT

digraph system_tree {
    rankdir=TB;
    node [shape=box];

    // Nodes
    workspace [label="WORKSPACE\n(L0)"];
    architect [label="architect\n(L1, INFO)"];
    pirotehnika [label="pirotehnika\n(L1, TARGET)"];
    retail [label="retail\n(L2, main)"];
    site [label="@site\n(L3, site)"];
    pim [label="@pim.service\n(L3, service)"];

    // Hierarchy edges
    workspace -> architect [label="contains"];
    workspace -> pirotehnika [label="contains"];
    pirotehnika -> retail [label="contains"];
    retail -> site [label="contains"];
    pirotehnika -> pim [label="contains"];

    // Dependency edges
    site -> pim [label="depends_on", style=dashed, color=blue];
}

СВЯЗИ С ДРУГИМИ ДОКУМЕНТАМИ


Версия: 1.0.0
Создано: 2025-12-22
Автор: Claude Sonnet 4.5
Статус: CANONICAL