architect/concept/FILESTORAGE.md

FileStorage — Концепция абстракции файловой системы

Версия: 1.0.0
Дата: 2026-02-17
Статус: concept
Тип: infrastructure-concept


КОНТЕКСТ

FileStorage — базовая абстракция платформы для работы с файлами.

Проблема: Код напрямую работает с файловой системой через open(), пути hardcoded, нет единого подхода.

Решение: Единый Storage Layer для всех операций с файлами.


ФИЛОСОФИЯ

FileStorage = Транспорт, не Генератор

┌─────────────────────────────────────────┐
│  FileStorage - это ГРУЗОВИК             │
│                                         │
│  НЕ генерирует содержимое              │
│  ТОЛЬКО перевозит готовое               │
└─────────────────────────────────────────┘

Аналогия:

Грузовик ≠ Создатель груза
Грузовик = Перевозчик груза

FileStorage ≠ Генератор текста
FileStorage = Записыватель текста

Принцип:
- FileStorage получает готовый текст
- FileStorage записывает как дали
- FileStorage не думает о содержимом


КАК СЕЙЧАС (as-is)

Проблема: Прямое обращение к ФС

# Проект А
with open("/opt/claude-workspace/projects/foo/CLAUDE.md", "w") as f:
    f.write(content)

# Проект Б
path = "/opt/claude-workspace/projects/bar/index.yaml"
with open(path, "r") as f:
    data = f.read()

# Проект В
import os
os.makedirs("/opt/claude-workspace/projects/baz/design")

Проблемы:

Проблема Последствие
Hardcode путей /opt/claude-workspace/... вшито в код
Дублирование Каждый проект пишет свой код работы с файлами
Нет правил Где хранить документы? Где данные? Каждый решает сам
Сложно тестировать Тесты работают с реальными файлами
Нет абстракции Невозможно изменить backend (S3, FTP)

КАК ДОЛЖНО БЫТЬ (to-be)

Решение: Storage Layer

КОД → STORAGE LAYER → ФАЙЛОВАЯ СИСТЕМА
      ↓                ↓
      FileStorage      WORKSPACE/DATASPACE
      GitStorage       Git Repository

Как работает:
- Весь код работает через Storage Layer
- Storage решает где хранить (WORKSPACE vs DATASPACE)
- Storage решает как хранить (Git или нет)
- Один интерфейс для всех проектов

Пример:

from library.storages.filesystem import FileStorage

fs = FileStorage()

# Все проекты используют одинаково
fs.write("projects/foo/CLAUDE.md", content)
fs.write("projects/bar/index.yaml", data)

# FileStorage сам определяет абсолютный путь
# FileStorage сам создаёт папки
# FileStorage сам выбирает WORKSPACE vs DATASPACE

АРХИТЕКТУРА

Уровни абстракции

┌────────────────────────────────────────────────┐
  L6: ИНТЕГРАЦИИ                                
  (DM, PM используют FileStorage)               
└───────────────────┬────────────────────────────┘
                    
┌────────────────────────────────────────────────┐
  L5: СЕРВИСЫ                                   
  (business logic)                              
└───────────────────┬────────────────────────────┘
                    
┌────────────────────────────────────────────────┐
  L4: КОМПОНЕНТЫ ( FileStorage здесь)          
  library/storages/filesystem.py                
└───────────────────┬────────────────────────────┘
                    
┌────────────────────────────────────────────────┐
  L3: ФУНКЦИИ                                   
  (атомарные операции)                          
└───────────────────┬────────────────────────────┘
                    
┌────────────────────────────────────────────────┐
  L2: ПРИМИТИВЫ                                 
  (Path, File)                                  
└────────────────────────────────────────────────┘

Иерархия Storage

library/storages/
├── base.py               BaseStorage (абстракция)
├── filesystem.py         FileStorage (локальная ФС)
├── git.py                GitStorage (версионирование)
├── s3.py                 S3Storage (облако) [будущее]
├── postgres/             PostgresStorage (БД)
└── cache/                CacheStorage (Redis)

BaseStorage:

class BaseStorage(ABC):
    """Базовый класс всех storage."""

    @abstractmethod
    def read(self, key: str) -> Any:
        pass

    @abstractmethod
    def write(self, key: str, value: Any) -> None:
        pass

    @abstractmethod
    def exists(self, key: str) -> bool:
        pass

FILESTORAGE: Интерфейс

Основные методы

class FileStorage(BaseStorage):
    """
    Абстракция работы с файлами.

    Автоматически выбирает:
    - WORKSPACE (/opt/claude-workspace) — код, документы
    - DATASPACE (/mnt/beget-s3) — данные, изображения
    """

    def read(self, path: str) -> str:
        """
        Прочитать файл.

        Args:
            path: Относительный путь (projects/foo/file.md)

        Returns:
            Содержимое файла
        """

    def write(self, path: str, content: str) -> None:
        """
        Записать файл.

        Args:
            path: Относительный путь
            content: ГОТОВЫЙ текст для записи

        Note:
            FileStorage НЕ генерирует content.
            FileStorage ТОЛЬКО записывает что дали.
        """

    def exists(self, path: str) -> bool:
        """Проверить существование файла."""

    def list(self, pattern: str) -> List[str]:
        """
        Список файлов по glob-паттерну.

        Args:
            pattern: Glob паттерн (projects/**/*.md)

        Returns:
            Список путей
        """

    def delete(self, path: str) -> None:
        """Удалить файл."""

    def copy(self, src: str, dst: str) -> None:
        """Копировать файл."""

    def move(self, src: str, dst: str) -> None:
        """Переместить файл."""

    def mkdir(self, path: str) -> None:
        """Создать папку (и родительские)."""

АВТОМАТИЧЕСКИЙ ВЫБОР ХРАНИЛИЩА

Логика выбора WORKSPACE vs DATASPACE

class FileStorage:

    WORKSPACE = Path("/opt/claude-workspace")
    DATASPACE = Path("/mnt/beget-s3")

    # Расширения для DATASPACE
    BINARY_EXTENSIONS = {
        '.xlsx', '.xls',      # Excel
        '.jpg', '.jpeg',      # Изображения
        '.png', '.gif',
        '.pdf', '.docx',      # Документы
        '.zip', '.tar.gz',    # Архивы
        '.mp4', '.mp3',       # Медиа
    }

    def _resolve_path(self, path: str) -> Path:
        """
        Определить где хранить файл.

        Правило:
        - Бинарные данные → DATASPACE
        - Текст, код → WORKSPACE
        """
        ext = Path(path).suffix.lower()

        if ext in self.BINARY_EXTENSIONS:
            return self.DATASPACE / path
        else:
            return self.WORKSPACE / path

Примеры:

Файл Где хранится Почему
projects/foo/CLAUDE.md WORKSPACE Текст, версионируется
projects/foo/index.yaml WORKSPACE Код, версионируется
projects/foo/data.xlsx DATASPACE Бинарные данные
projects/foo/logo.png DATASPACE Изображение
library/storages/fs.py WORKSPACE Код

КТО СОЗДАЁТ ТЕКСТ?

FileStorage НЕ генерирует содержание

# ═══════════════════════════════════════════
# FileStorage = ТРАНСПОРТ (не генератор)
# ═══════════════════════════════════════════

fs = FileStorage()
fs.write(path, content)
#              ↑
#         ОТКУДА content?

Текст создают:

1. Claude (AI) — уникальное содержание

# Claude генерирует В ПАМЯТИ:
content = """# foo

**Тип:** it-project

## Что это

Проект foo - система управления задачами для команды.
Включает трекинг задач, sprint planning, интеграцию с Git.
Поддерживает Kanban и Scrum методологии.

## Технологии

- Python 3.11
- FastAPI
- PostgreSQL
- React
"""
# ← ТЕКСТ СОЗДАН Claude (AI думал, анализировал)

# Передаёт готовый в FileStorage:
fs.write("projects/foo/CLAUDE.md", content)
#                                   ↑
#                          УЖЕ ГОТОВЫЙ ТЕКСТ

2. DM (шаблоны) — типовая структура

# DM подставляет переменные:
template = """id: {name}
type: {type}
status: active
created: {date}
"""

content = template.format(
    name="foo",
    type="it-project",
    date="2026-02-17"
)
# ← ТЕКСТ СОЗДАН DM (примитивная подстановка)

# Передаёт готовый в FileStorage:
fs.write("projects/foo/index.yaml", content)
#                                    ↑
#                           УЖЕ ГОТОВЫЙ ТЕКСТ

3. Комбинация (DM + Claude)

# Шаг 1: DM создаёт skeleton
skeleton = """# {name}

## Что это

<!-- AI: Опиши проект {name} -->

## Технологии

<!-- AI: Перечисли технологии -->
"""

content = skeleton.format(name="foo")
fs.write("projects/foo/CLAUDE.md", content)

# Шаг 2: Claude заполняет
new_content = """# foo

## Что это

Проект foo - система управления...

## Технологии

- Python 3.11
- FastAPI
"""

fs.write("projects/foo/CLAUDE.md", new_content)
#                                   ↑
#                    ПЕРЕЗАПИСЫВАЕТ готовым текстом

INTEGRATION: Как использует DM

Document Manager создаёт структуру

# system/dm/assembly.py

from library.storages.filesystem import FileStorage
from library.storages.git import GitStorage

class DocumentAssembler:

    def __init__(self):
        self.fs = FileStorage()  # ← Используем абстракцию
        self.git = GitStorage()

    def create_project(self, name: str, type: str):
        """
        Создать проект из шаблона.

        Returns:
            Инструкции для Claude (что заполнить)
        """

        # ═══════════════════════════════════
        # 1. Создаём простые файлы целиком
        # ═══════════════════════════════════

        index = f"""id: {name}
type: {type}
status: active
"""
        self.fs.write(f"projects/{name}/index.yaml", index)
        #                                            ↑
        #                                   ПЕРЕДАЁМ ГОТОВЫЙ


        # ═══════════════════════════════════
        # 2. Создаём skeleton для Claude
        # ═══════════════════════════════════

        skeleton = f"""# {name}

**Тип:** {type}

## Что это

<!-- AI: Опиши проект {name} -->

## Технологии

<!-- AI: Перечисли технологии для {type} -->
"""
        self.fs.write(f"projects/{name}/CLAUDE.md", skeleton)
        #                                            ↑
        #                                   ПЕРЕДАЁМ ГОТОВЫЙ


        # ═══════════════════════════════════
        # 3. Возвращаем инструкции Claude
        # ═══════════════════════════════════

        return {
            "skeleton_created": True,
            "files_to_fill": [
                {
                    "path": f"projects/{name}/CLAUDE.md",
                    "sections": [
                        {
                            "marker": "<!-- AI: Опиши проект {name} -->",
                            "prompt": f"Опиши проект {name} типа {type}"
                        },
                        {
                            "marker": "<!-- AI: Перечисли технологии -->",
                            "prompt": f"Технологии для {type}"
                        }
                    ]
                }
            ]
        }

FileStorage в DM:
- Получает готовый текст (из шаблона)
- Записывает в файл
- Создаёт папки автоматически
- Выбирает WORKSPACE/DATASPACE


ПРЕИМУЩЕСТВА

До FileStorage (сейчас)

# ❌ Hardcode путей
with open("/opt/claude-workspace/projects/foo/file.md", "w") as f:
    f.write(content)

# ❌ Ручное создание папок
os.makedirs("/opt/claude-workspace/projects/foo/design", exist_ok=True)

# ❌ Нет правил где хранить
# Документы в WORKSPACE? Данные в DATASPACE? Каждый решает сам

# ❌ Сложно тестировать
# Тесты работают с реальными файлами

# ❌ Код дублируется
# Каждый проект пишет свою работу с файлами

С FileStorage (станет)

# ✅ Относительные пути
fs.write("projects/foo/file.md", content)

# ✅ Папки автоматически
# FileStorage создаёт сам

# ✅ Правила встроены
# .md → WORKSPACE
# .xlsx → DATASPACE

# ✅ Легко тестировать
fs = MockFileStorage()  # Mock для тестов

# ✅ Переиспользование
# Один FileStorage для всех проектов

СРАВНЕНИЕ

Аспект БЕЗ FileStorage С FileStorage
Пути Абсолютные hardcoded Относительные
Создание папок Вручную makedirs Автоматически
WORKSPACE vs DATASPACE Каждый решает сам Автоматически по расширению
Переиспользование Код дублируется Один раз в library/
Тестирование Сложно (реальные файлы) Легко (моки)
Миграция Править во всех проектах Изменить 1 место
Backend Только локальная ФС Можно добавить S3, FTP

WORKFLOW: Claude + DM + FileStorage

Полный цикл создания проекта

┌────────────────────────────────────────────┐
│  ПОЛЬЗОВАТЕЛЬ                              │
│  "создай проект foo"                       │
└───────────────┬────────────────────────────┘
                ↓
┌────────────────────────────────────────────┐
│  CLAUDE                                    │
│  Bash("python system/dm/cli.py create")    │
└───────────────┬────────────────────────────┘
                ↓
┌────────────────────────────────────────────┐
│  DM                                        │
│  1. Генерирует текст из шаблона            │
│  2. Вызывает FileStorage                   │
│     fs.write(path, content)                │
└───────────────┬────────────────────────────┘
                ↓
┌────────────────────────────────────────────┐
│  FileStorage                               │
│  1. Определяет WORKSPACE vs DATASPACE      │
│  2. Создаёт папки                          │
│  3. Записывает файл                        │
└───────────────┬────────────────────────────┘
                ↓
┌────────────────────────────────────────────┐
│  ФАЙЛОВАЯ СИСТЕМА                          │
│  /opt/claude-workspace/projects/foo/...    │
└────────────────────────────────────────────┘

РАЗДЕЛЕНИЕ РОЛЕЙ

┌──────────────────────────────────────┐
│  CLAUDE (AI)                         │
│  • Генерирует СОДЕРЖАНИЕ             │
│  • Думает, анализирует               │
│  • Создаёт уникальный текст          │
└──────────────┬───────────────────────┘
               ↓ управляет
┌──────────────────────────────────────┐
│  DM (Python)                         │
│  • Создаёт СТРУКТУРУ                 │
│  • Шаблоны с подстановкой            │
│  • Определяет что нужно сгенерировать│
└──────────────┬───────────────────────┘
               ↓ использует
┌──────────────────────────────────────┐
│  FileStorage (Python)                │
│  • Записывает ГОТОВЫЙ текст          │
│  • WORKSPACE vs DATASPACE            │
│  • НЕ генерирует содержание          │
└──────────────┬───────────────────────┘
               ↓ работает с
┌──────────────────────────────────────┐
│  ФАЙЛОВАЯ СИСТЕМА                    │
│  /opt/claude-workspace/              │
│  /mnt/beget-s3/                      │
└──────────────────────────────────────┘

Каждый делает СВОЁ:
- Claude → содержание (AI)
- DM → структура (шаблоны)
- FileStorage → хранение (техника)


БУДУЩЕЕ РАЗВИТИЕ

Возможные расширения

library/storages/
├── filesystem.py         Локальная ФС (есть)
├── git.py                Git версионирование (есть)

├── s3.py                 AWS S3 (будущее)
├── ftp.py                FTP storage (будущее)
├── webdav.py             WebDAV (будущее)
└── dropbox.py            Dropbox API (будущее)

Преимущество абстракции:
- Код проектов не меняется
- Меняется только backend в FileStorage
- Можно комбинировать (локально + S3)


КЛЮЧЕВЫЕ ПРИНЦИПЫ

1. FileStorage = Транспорт

FileStorage НЕ генерирует текст
FileStorage ТОЛЬКО записывает готовый текст

2. Разделение ответственности

Генерация содержания → Claude / DM
Хранение файлов → FileStorage

3. Один интерфейс для всех

Все проекты используют FileStorage одинаково
Переиспользование вместо дублирования

4. Автоматизация правил

WORKSPACE vs DATASPACE → автоматически
Создание папок → автоматически
Права доступа → автоматически

5. Гибкость backend

Сегодня: локальная ФС
Завтра: S3, FTP, WebDAV
Код не меняется

СВЯЗИ

Архитектура

Реализация

Стандарты

Документация


Версия: 1.0.0
Дата: 2026-02-17
Статус: concept