# Извлечение знаний из истории: как изменения становятся институциональной памятью

Canonical source: https://maguyva.ai/ru/blog/mining-workflow-closing-the-loop

License: text under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/); code samples under [MIT-0](https://opensource.org/license/mit-0); the Maguyva name, logos, brand assets and other code are not covered. Details: [maguyva.ai/license](https://maguyva.ai/license).

Date: 2026-02-03 · Author: Maguyva Team

> Git-коммиты превращаются в структурированные записи журнала изменений и записи архитектурных решений, а затем возвращаются к ИИ-агентам в виде запрашиваемой институциональной памяти.

> *Цифры в этом посте отражают состояние системы на момент публикации (февраль 2026). Актуальные цифры смотрите на нашей [странице команды](/ru/team).*

Каждая инженерная команда сталкивается с одной и той же проблемой: изменения происходят постоянно, а *причины* этих изменений забываются. Спустя полгода кто-то спрашивает: «почему мы выбрали DuckDB для этапов пайплайна?» — и ответ живёт только в голове того, кто принял это решение, если этот человек ещё вообще рядом.

Мы построили процесс майнинга, который замыкает этот цикл. Изменения проходят через git-коммиты, обрабатываются нашим конвейером майнинга, становятся структурированными записями журнала изменений и записями архитектурных решений, а затем возвращаются к нашим ИИ-агентам через запросы CLI. Результат: институциональная память, доступная и людям, и ИИ.

## Проблема: решения испаряются

Рассмотрим типичный сценарий. Разработчик коммитит:

```
feat(canonical): add DuckDB runtime for pipeline stages
```

Этот коммит представляет значимый архитектурный выбор. Команда оценила варианты, взвесила компромиссы и остановилась на DuckDB по конкретным причинам. Но весь этот контекст живёт в:

- Треде в Slack (вероятно, удалённом)
- Чьей-то памяти (определённо угасающей)
- Комментарии в коде (может быть, если повезёт)

Спустя три месяца новый участник команды спрашивает: «Стоит ли использовать DuckDB или SQLite для этого нового этапа?» Без институциональной памяти он либо изобретает велосипед заново, либо делает непоследовательный выбор.

## Цикл: от коммитов к контексту

Наш процесс майнинга превращает историю git в знание, пригодное для запросов:

```
Git Commits
    │
    ▼
┌─────────────────────┐
│  mine sync          │  ← Build index from git history
└─────────────────────┘
    │
    ▼
┌─────────────────────┐
│  mine candidates    │  ← Surface commits for review
└─────────────────────┘
    │
    ▼
┌─────────────────────┐
│  Classification     │  ← Human or LLM assessment
│  (changelog or ADR) │
└─────────────────────┘
    │
    ├──────────────────────┐
    ▼                      ▼
┌─────────────┐    ┌───────────────┐
│ Changelog   │    │ Decisions     │
│ Ledger      │    │ Registry      │
│ (JSONL)     │    │ (YAML files)  │
└─────────────┘    └───────────────┘
    │                      │
    ▼                      ▼
┌─────────────┐    ┌───────────────┐
│ CHANGELOG.md│    │ orkestra CLI  │
│ per package │    │ queries       │
└─────────────┘    └───────────────┘
    │                      │
    └──────────────────────┘
              │
              ▼
      ┌───────────────┐
      │ AI Agents     │
      │ (via CLI)     │
      └───────────────┘
```

Ключевая идея: и записи журнала изменений, и архитектурные решения проистекают из одной и той же истории git, обрабатываемой единым конвейером. Это гарантирует, что ничего не будет упущено.

## Как работает майнинг

### Шаг 1: синхронизация индекса

```bash
uv run orkestra mine sync
```

Эта команда сканирует историю git и строит индекс всех коммитов. Она извлекает структурированные сигналы из каждого коммита:

- Тип коммита по Conventional Commits (`feat`, `fix`, `chore`, `docs`)
- Область (какой пакет или зона)
- Маркеры несовместимых изменений
- Затронутые файлы и метрики сложности

### Шаг 2: проверка статуса покрытия

```bash
uv run orkestra mine status
```

Вот как выглядит наш текущий статус:

```
Mining Status
=============

Decisions
---------
  Coverage:        100.0%
    Processed:     15637  (of 15637)
    Extracted:       476
    Skipped:       15161

Changelog
---------
  Coverage:        100.0%
    Processed:     15637  (of 15637)
    Released:       6799
    Skipped:        8838
```

15 637 коммитов обработано. 476 стали архитектурными решениями. 6799 стали записями журнала изменений. Каждый коммит классифицирован.

### Шаг 3: получение кандидатов на ревью

```bash
uv run orkestra mine candidates --limit 50 --full
```

Это выявляет ещё не обработанные коммиты с полным контекстом для классификации:

```json
{
  "sha": "90571786d99166c0039ca2e80e4d9cd96184bd85",
  "date": "2026-01-26",
  "subject": "feat(canonical): add DuckDB runtime for pipeline stages",
  "signals": {
    "commit_type": "feat",
    "scope": "canonical",
    "breaking": false,
    "is_releasable_type": true,
    "domains_affected": ["pipeline", "data-architecture"]
  },
  "body": "Establishes DuckDB as canonical in-process analytical database...",
  "files_changed": ["packages/canonical/pipelines/stages/duckdb_runtime.py", "..."],
  "stats": {"files": 8, "insertions": 450, "deletions": 120}
}
```

Сигналы помогают направлять классификацию: `is_releasable_type: true` подсказывает, что это должно попасть в журнал изменений. Большое количество вставленных строк и инфраструктурные файлы намекают, что это может быть и архитектурным решением.

### Шаг 4: классификация коммитов

Здесь пути расходятся: записи журнала изменений и архитектурные решения.

**Для записей журнала изменений:**

```bash
uv run orkestra mine classify abc123 --changelog added
```

Это фиксирует, что коммит `abc123` должен появиться в журнале изменений в категории «Добавлено».

**Для архитектурных решений:**

Сначала получите настоящий идентификатор решения:

```bash
uv run orkestra registry decisions new --domain pipeline --dry-run
# Returns: DEC-PL-143
```

Затем классифицируйте с этим идентификатором:

```bash
uv run orkestra mine classify abc123 --decision DEC-PL-143
```

Это связывает коммит с записью решения, которая будет создана или обновлена.

**Для пакетной обработки (то, что мы реально делаем):**

```bash
# Generate classifications file with LLM assistance
uv run orkestra mine commit --input classifications.jsonl
```

Формат JSONL поддерживает оба домена за один проход:

```jsonl
{"sha":"abc123","domain":"changelog","action":"release","category":"added","summary":"Add DuckDB runtime for pipeline stages"}
{"sha":"abc123","domain":"decisions","action":"extract","decision_id":"DEC-PL-142"}
{"sha":"def456","domain":"changelog","action":"skip","reason":"Chore: dependency update"}
```

### Шаг 5: рендеринг вывода

```bash
uv run orkestra registry changelog render --package <pkg>
```

Это генерирует файлы `CHANGELOG.md` для каждого пакета на основе журнала записей (ledger). Журналы изменений — производные артефакты: удалите их, и они идеально восстановятся из исходного журнала записей.

## Структура записи решения

Извлечённые решения становятся YAML-файлами с богатыми метаданными:

```yaml
id: DEC-PL-142
title: Adopt DuckDB as Canonical Processing Runtime for Pipeline Stages
domain: pipeline
status: active
created: '2026-01-26'
summary: |
  Establishes DuckDB as the canonical in-process analytical database for pipeline
  stage transformations. Provides a shared runtime module that resolves settings
  from pipeline defaults with stage-level overrides.

context: |
  Pipeline stages performing data transformations each independently configured
  DuckDB connections. This led to inconsistent settings, duplicated configuration
  code, and no way to tune DuckDB globally for a pipeline run.

rationale:
  - DuckDB provides efficient in-process OLAP with zero configuration deployment
  - Centralized runtime module eliminates duplicated DuckDB setup across stages
  - Hierarchical settings enable global tuning with stage-level overrides
  - Memory limits and thread counts can be adjusted per-pipeline

impact:
  positive:
    - Consistent DuckDB configuration across all pipeline stages
    - Single point of control for memory/thread tuning
    - Reduced code duplication in conversion and export stages
  negative:
    - Adds dependency on shared runtime module
    - Stages must adopt new configuration pattern

source_commits:
  - sha: 90571786d99166c0039ca2e80e4d9cd96184bd85
    message: 'feat(canonical): add DuckDB runtime for pipeline stages'
    date: '2026-01-26'
    role: primary

files:
  - packages/canonical/pipelines/stages/duckdb_runtime.py
  - packages/canonical/pipelines/runner.py
  - packages/canonical/pipelines/stages/convert_hdx_admin_boundaries_to_geoparquet.py

related:
  - DEC-DA-014  # Data architecture decisions that influenced this
```

Каждое решение ссылается обратно на исходные коммиты. Каждое решение указывает, какие файлы оно затрагивает. Связи между решениями явные.

## Интеграция с CLI: запрос институциональной памяти

Вот где цикл замыкается. Агенты могут запрашивать решения через CLI:

```bash
# Search by topic
uv run orkestra registry decisions search --query "retry"
```

Возвращает решения про логику повторных попыток, обработку ошибок, паттерны восстановления.

```bash
# Get full details on a specific decision
uv run orkestra registry decisions info DEC-PL-142
```

Возвращает полную запись решения с контекстом, обоснованием и влиянием.

```bash
# List recent decisions for context
uv run orkestra registry decisions list --limit 15
```

Показывает, какие архитектурные решения были приняты недавно.

### Как агенты это используют

Базовые инструкции нашего оркестратора включают:

```markdown
**Essential CLI commands:**
- `orkestra registry decisions search "X"` — Find architectural decisions
```

Когда агента просят реализовать что-то связанное с DuckDB, он может сначала проверить:

```bash
uv run orkestra registry decisions search --query "DuckDB"
```

И обнаружить DEC-PL-142, узнав:
- почему мы выбрали DuckDB (context)
- как использовать его правильно (agent_guidance)
- какие файлы стоит посмотреть (files)
- какие связанные решения существуют (related)

Агент не изобретает велосипед заново. Он опирается на устоявшиеся паттерны.

## Тест трёх вопросов

Не каждый коммит заслуживает записи решения. Мы используем Тест трёх вопросов для фильтрации:

1. **Было ли это трудно сделать?** Требовало ли это значительного анализа, оценки компромиссов или споров?
2. **Дорого ли это менять?** Потребует ли отмена этого решения значительной переделки?
3. **Есть ли у этого влияние на всю систему?** Затрагивает ли это несколько пакетов или устанавливает паттерны, которым последуют другие?

Если коммит отвечает «да» хотя бы на один из этих вопросов, он — кандидат на извлечение решения. Наш типичный показатель: 1-4 решения на 100 коммитов (примерно 1-4%).

Для записей журнала изменений планка ниже: любое изменение, видимое пользователю (функции, исправления, улучшения), фиксируется. Внутренние рутинные задачи, обновления документации и рефакторинги обычно пропускаются. Наш типичный показатель: 30-50 записей журнала изменений на 100 коммитов.

## Хранение данных: журналы записей только для добавления

Система майнинга использует журналы записей JSONL только для добавления (append-only) для бесконфликтной работы нескольких агентов:

```
packages/orchestration/ai_assets/reference/changelog/
├── commits_processed.jsonl  # Classification ledger (both domains)
├── release_notes.jsonl      # Changelog entries
└── commits_index.yaml       # Derived index (gitignored)

packages/orchestration/ai_assets/reference/decisions/
├── registry.yaml            # Decision index
└── records/
    ├── DEC-AD-001.yaml
    ├── DEC-AD-002.yaml
    └── ...
```

Формат JSONL с `merge=union` в `.gitattributes` означает, что несколько агентов могут классифицировать коммиты одновременно без конфликтов слияния. Каждая строка независима.

## Контрольные проверки

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

```bash
uv run orkestra mine validate --quick
```

Это проверяет:
- корректность формата SHA
- соответствие формату идентификатора решения
- отсутствие дублирующихся записей для одного и того же SHA
- реальное существование решений, на которые есть ссылки

После классификации мы валидируем снова перед коммитом изменений.

## Почему это важно

Построенный нами контур обратной связи решает несколько проблем:

**Для новых участников команды:** вместо вопроса «почему мы сделали X?» они могут искать в реестре решений. Контекст сохранён.

**Для ИИ-агентов:** они не работают в вакууме. Они могут запрашивать институциональные знания перед тем, как давать рекомендации. Когда их просят добавить новый этап пайплайна, они могут обнаружить паттерн DuckDB и следовать ему.

**Для архитектурной согласованности:** решения явные и доступны для поиска. Когда кто-то предлагает подход, противоречащий существующему решению, система может выявить конфликт.

**Для генерации журнала изменений:** заметки к релизу — не аврал в последнюю минуту. Это побочный продукт непрерывной классификации в процессе разработки.

**Для онбординга:** новые агенты наследуют полный контекст кодовой базы. Они видят не только код — они видят решения, которые его сформировали.

## Текущее состояние

На сегодняшний день:
- **15 637 коммитов** обработано конвейером
- **476 архитектурных решений** извлечено и задокументировано
- **6799 записей журнала изменений** зафиксировано
- **100% покрытие** по обоим доменам

Каждый коммит с момента запуска системы классифицирован. Институциональная память полна и доступна для запросов.

## С чего начать

Если вы хотите реализовать нечто подобное:

1. **Начните с коммитов по Conventional Commits.** Конвейер майнинга работает лучше всего, когда коммиты имеют структурированные префиксы (`feat:`, `fix:`, `chore:`).

2. **Определите свои домены.** Мы используем домены вроде `pipeline`, `agent-design`, `observability`, `data-modeling`. Они организуют решения по областям.

3. **Выработайте привычку классификации.** Майнинг работает, когда команды регулярно классифицируют коммиты. Пакетная обработка с помощью LLM помогает масштабироваться.

4. **Сделайте решения доступными для запросов.** Ценность растёт, когда агенты могут искать решения через CLI. Структурируйте вывод для машинного потребления.

5. **Замкните цикл.** Решения должны влиять на будущую работу. Включайте ссылки на решения в инструкции агентов и чек-листы ревью кода.

Цель — не идеальная документация. Цель — сделать *причины* изменений понятными и людям, и ИИ, сегодня и спустя полгода. Когда изменения становятся институциональной памятью, команды опираются на устоявшиеся паттерны, а не изобретают их заново.

---

*Процесс майнинга — часть нашего движка оркестрации, а именно модуля контекстного движка в нашем пакете оркестрации.*
