# Пошаговое руководство по курсу

> Пять фаз ниже — учебная модель. Каталог Factory `GET /ai-market/products` включает продукты в состояниях `COMPLETED` и `DEPLOYED_PRODUCTION` и может вернуть пустой список возможностей. Перед вызовом проверьте точный идентификатор в [поиске Hub](https://modelmarket.dev/ai-market/v2/search?intent=factory&limit=5). Статус пайплайна или запись о продукте сами по себе не подтверждают доступность вызова.

> **Для кого:** разработчики, интегрирующиеся с пайплайном AI-Factory — публичные эндпоинты статуса, каталог выпущенных продуктов и поток этапов оркестратора.
> **Язык лаб:** `COURSE_LANG=ru|en|es` · строки UI в `i18n/` · этот гайд на русском.
> **English:** [step-by-step.md](./step-by-step.md) · **Español:** [step-by-step.es.md](./step-by-step.es.md)

---

## Зачем этот курс

AI-Factory превращает идею в одну строку в выпущенный продукт, проводя её через оркестрируемые этапы: **research → design → build → test → ship**. У каждого этапа есть агент-владелец (analyst, architect, developer, QA, devops), а фабрика отдаёт небольшой **публичный API**, чтобы любой мог наблюдать за работой пайплайна и видеть, что уже выпущено.

Курс изучает этот API «снаружи внутрь». Вы зондируете те же два публичных эндпоинта, что использует главная страница, проходите конечный автомат оркестратора от `IDEA_RECEIVED` до `COMPLETED` и завершаете капстоуном-зондом — **без запущенной фабрики**. Каждая лаба откатывается на **встроенный мок фабрики** на `127.0.0.1`, поэтому курс целиком работает офлайн. Укажите одну переменную окружения на живую фабрику — и те же самые лабы читают реальные данные.

Каждая лаба печатает блок `Trace`: оркестрация логируется, а не происходит «по волшебству».

---

## Содержание

1. [Выбор трека](#выбор-трека)
2. [Установка (5 минут)](#установка-5-минут)
3. [M1 — Обзор пайплайна](#m1--обзор-пайплайна)
4. [M2 — API статуса пайплайна](#m2--api-статуса-пайплайна)
5. [M3 — Каталог выпущенных продуктов](#m3--каталог-выпущенных-продуктов)
6. [M4 — Поток этапов оркестратора](#m4--поток-этапов-оркестратора)
7. [M5 — Капстоун: зонд фабрики](#m5--капстоун-зонд-фабрики)
8. [Живая фабрика vs встроенный мок](#живая-фабрика-vs-встроенный-мок)
9. [Наблюдаемость — Trace в каждой лабе](#наблюдаемость--trace-в-каждой-лабе)
10. [Упражнения и сертификат](#упражнения-и-сертификат)
11. [Мост: от курса к AI-Factory](#мост-от-курса-к-ai-factory)
12. [Чеклист самопроверки](#чеклист-самопроверки)
13. [Типичные проблемы](#типичные-проблемы)

---

## Выбор трека

| Трек | Модули | Время | Живая фабрика |
|------|--------|-------|----------------|
| **Базовый** | M1 → M2 → M3 → M4 | ~1,5 ч | Нет — встроенный мок |
| **Продвинутый** | Базовый + капстоун M5 | +30 мин | Опционально (`COURSE_FACTORY_URL`) |
| **Мост к Factory** | После M5 | +30 мин | Да — реальная фабрика + Hub |

Живая фабрика не обязательна: M2, M3 и M5 автоматически поднимают мок, если ни одна фабрика недоступна. Поле `source` в выводе показывает, кто ответил (`mock` или `live`).

---

## Установка (5 минут)

### Шаг 1 — Клон и установка

```bash
git clone https://github.com/alexar76/aimarket-courses.git
cd aimarket-courses/ai-factory-course
pip install -e ".[factory,dev]"
```

Extra `[factory]` ставит `fastapi` + `uvicorn` — на них работает встроенный мок фабрики, на который откатываются M2/M3/M5. `[dev]` добавляет `pytest`. Нужен Python 3.11+.

### Шаг 2 — Тесты

```bash
pytest -q
```

**Ожидается:** все тесты проходят — паритет i18n по `en/ru/es`, клиент фабрики и проход оркестратора, проверки упражнений и смоук-прогон всех пяти лаб.

### Шаг 3 — Первая лаба

```bash
python labs/lab01_pipeline_overview.py
```

Увидите пять фаз пайплайна, сопоставленных с агентами, затем блок `trace`, затем подсказку упражнения «Ваша очередь».

### Шаг 4 — Язык интерфейса (опционально)

```bash
export COURSE_LANG=ru   # или es; по умолчанию en
python labs/lab01_pipeline_overview.py
```

Заголовки, подписи и подсказки переключаются на выбранный язык; код, имена состояний (`COMPLETED`) и пути эндпоинтов остаются на английском. Порядок выбора: явный аргумент → `COURSE_LANG` → откат на английский.

### Шаг 5 — Google Colab

Откройте [сайт курса](https://alexar76.github.io/aimarket-courses/ai-factory-course/) → **Open in Colab** на любой лабе → выполните setup-ячейку (clone + `pip install -e ".[factory,dev]"`) → при желании задайте `os.environ["COURSE_LANG"] = "ru"`, затем запустите ячейку лабы.

---

## M1 — Обзор пайплайна

**Концепция:** research → design → build → test → ship как оркестрируемые этапы, у каждого свой агент-владелец.
**Лаба:** `labs/lab01_pipeline_overview.py` · **~15 мин** · установка выполнена

### Шаги

1. Откройте `labs/lab01_pipeline_overview.py` и прочитайте docstring.
2. Запустите: `python labs/lab01_pipeline_overview.py`
3. Прочитайте таблицу **пяти фаз**: каждая строка — `фаза → агент → состояние`, например `research → analyst → MARKET_RESEARCHED`, до `ship → devops → COMPLETED`.
4. Откройте `courselib/factory.py`, найдите `PIPELINE_PHASES` — тот самый кортеж, что печатает лаба (это учебная карта; реальный граф оркестратора будет в M4).

### Что доказывает

Фабрика — не чёрный ящик: есть фиксированное, проверяемое соответствие бизнес-фазы агенту-владельцу и состоянию, которое она оставляет. Каждая строка `фаза` также логируется как событие trace.

### Самопроверка

- [ ] Называете все пять фаз по порядку
- [ ] Знаете, какой агент владеет каждой фазой

---

## M2 — API статуса пайплайна

**Концепция:** heartbeat главной страницы — `GET /api/public/pipeline-status` возвращает счётчики *в пайплайне* vs *выпущено*.
**Лаба:** `labs/lab02_pipeline_status.py` · **~15 мин** · нужен M1

### Шаги

1. Запустите: `python labs/lab02_pipeline_status.py`
2. Прочитайте три строки: **В пайплайне**, **Выпущено**, **Источник данных**.
3. Посмотрите значение `Источник данных` — `mock` (мок поднят за вас) или `live` (если `COURSE_FACTORY_URL` указывает на доступную фабрику).
4. Откройте `courselib/factory.py` → `FactoryClient.get_pipeline_status()` — за этим один HTTP-`GET`.

### Что доказывает

Публичного heartbeat-эндпоинта достаточно, чтобы ответить «насколько фабрика занята и сколько выпустила» — те же числа, что на лендинге. Мок отдаёт детерминированные 4 в пайплайне / 2 выпущено, чтобы лаба была воспроизводимой офлайн.

### Самопроверка

- [ ] Читаете из вывода «в пайплайне» vs «выпущено»
- [ ] Знаете, ответил ли ваш прогон `mock` или `live`

---

## M3 — Каталог выпущенных продуктов

**Концепция:** `GET /ai-market/products` перечисляет `COMPLETED`-продукты и их возможности.
**Лаба:** `labs/lab03_products_catalog.py` · **~15 мин** · нужен M2

### Шаги

1. Запустите: `python labs/lab03_products_catalog.py`
2. Прочитайте число **Выпущенных продуктов** и первые продукты: `id: name (N caps)`.
3. У каждого продукта есть `capabilities` — id и `price_per_call_usd`. Посмотрите `MOCK_PRODUCTS` в `courselib/factory.py` (`demo-analytics`, `demo-orchestrator`).
4. Trace логирует одно событие `products` и по событию `product` на каждый элемент.

### Что доказывает

То, что выпускает фабрика, становится каталогом маркетплейса: у каждого продукта есть платные вызываемые возможности. Это мост между «пайплайн что-то завершил» и «это можно вызвать» (см. раздел «Мост»).

### Самопроверка

- [ ] `count` равен числу перечисленных продуктов
- [ ] Можете указать id возможности и цену за вызов

---

## M4 — Поток этапов оркестратора

**Концепция:** оркестратор — конечный автомат; пройдите его от `IDEA_RECEIVED` до `COMPLETED`.
**Лаба:** `labs/lab04_orchestrator_stages.py` · **~20 мин** · нужен M1

### Шаги

1. Запустите: `python labs/lab04_orchestrator_stages.py`
2. Прочитайте **Путь оркестратора** — каждая строка `STATE  agent=<кто>`, от `IDEA_RECEIVED` до `COMPLETED`.
3. Переходы берутся из `config/pipeline_flow.json` **в монорепозитории**, если он есть; в standalone-режиме используется встроенный fallback `agent_flow` из `courselib/factory.py`.
4. Откройте `walk_to_ship()` и `next_state()` в `courselib/factory.py` — обратите внимание на ограничитель `max_steps`, который останавливает проход на `COMPLETED`/`DEPLOYED_PRODUCTION` и предотвращает бесконечные циклы.

### Что доказывает

Карта фаз из M1 подкреплена реальной таблицей переходов. Каждое ребро `STATE → (agent, next_state)` логируется как событие `transition`, поэтому весь путь аудируем.

### Самопроверка

- [ ] Путь начинается с `IDEA_RECEIVED` и доходит до `COMPLETED`
- [ ] Объясняете, почему проход завершается (ограничитель цикла)

---

## M5 — Капстоун: зонд фабрики

**Концепция:** один сквозной зонд — heartbeat + каталог + фазы — по живой фабрике или встроенному моку.
**Лаба:** `labs/lab05_factory_capstone.py` · **~20 мин** · нужны M2–M4 · трек: продвинутый

### Шаги

1. Запустите: `python labs/lab05_factory_capstone.py`
2. Прочитайте сводный результат: `in_pipeline=… shipped=…`, `count` каталога и его `source`, затем пять `phases`.
3. Откройте `probe_factory()` в `courselib/factory.py` — он переиспользует один `factory_client()` для обоих эндпоинтов и добавляет список фаз. Это лабы базового трека, собранные в один вызов.
4. Перезапустите с заданным `COURSE_FACTORY_URL` и увидите, как `source` меняется с `mock` на `live`.

### Что доказывает

Можно за один обход проверить здоровье фабрики и снять инвентарь, и форма ответа одинакова — пришёл ли он с реального деплоя или локального мока. Контракт интеграции стабилен.

### Самопроверка

- [ ] Называете цепочку: status → products → phases в одном зонде
- [ ] Объясняете различие `source ∈ {live, mock}`

---

## Живая фабрика vs встроенный мок

Каждая сетевая лаба (M2, M3, M5) использует `factory_client()`, который:

1. Читает базовый URL из `COURSE_FACTORY_URL` (или `AIFACTORY_URL` / `FACTORY_PUBLIC_URL`).
2. Если задан **и доступен** — обращается к живой фабрике; вывод `source: live`.
3. Иначе поднимает **встроенный мок на FastAPI** на свободном порту `127.0.0.1`, ждёт `/api/health` и отдаёт детерминированные данные; вывод `source: mock`.

Указать на живую фабрику:

```bash
export COURSE_FACTORY_URL=https://your-factory.example
python labs/lab02_pipeline_status.py    # читает реальные счётчики
```

Проверки упражнений (`prefer_live=False`) всегда используют мок, чтобы проходить офлайн и в CI.

---

## Наблюдаемость — Trace в каждой лабе

**Концепция:** каждая лаба записывает, что сделала, чтобы поведение можно было проверить.
**Где:** во всех пяти лабах через хелпер `Trace` · **~5 мин** после каждой лабы

### Шаги (после M1–M5)

1. Прокрутите до блока `trace (N events):` в конце вывода.
2. Сопоставьте каждое событие со строкой выше — `phase`/`transition`/`product`/`pipeline_status`/`capstone`.
3. Сравните по лабам: M1 логирует пять событий `phase`; M4 — по одному `transition` на переход; M5 — одно свёрнутое событие `capstone`.

### Самопроверка

- [ ] Trace — это «лог юнит-теста» лабы: что именно сделал зонд
- [ ] Сопоставляете напечатанную строку с событием trace

---

## Упражнения и сертификат

Каждая лаба заканчивается подсказкой «Ваша очередь». Запустите соответствующую проверку:

```bash
python labs/run_exercises.py --module m1     # один модуль
python labs/run_exercises.py                 # все модули → ✓/✗ по каждому
```

Проверки модулей лежат в `courselib/exercises.py` (например, M1 проверяет пять фаз по порядку; M4 — что проход начинается с `IDEA_RECEIVED` и доходит до `COMPLETED`).

Когда все пять зелёные, выпустите сертификат:

```bash
python labs/run_exercises.py --certificate "Иван Петров" --lang ru
```

Создаётся `certificate.html`; откройте его и **Print → Save as PDF**. ID сертификата — это SHA-256 от имени и даты выпуска (стабилен для одного имени в один день). Флаги: `--lang ru`/`es` для локализованного сертификата, `-o path.html` для выбора файла, `--skip-check` — только если нужно сгенерировать без повторного прогона проверок.

---

## Мост: от курса к AI-Factory

**Цель:** прогнать те же зонды против *реального* пайплайна (~30 мин).

1. **Запустите фабрику** (из корня монорепозитория):

   ```bash
   docker compose up -d app
   # → http://localhost:9080
   ```

2. **Нацельте лабы на неё:**

   ```bash
   export COURSE_FACTORY_URL=http://localhost:9080
   python labs/lab05_factory_capstone.py    # source: live
   ```

3. **Отправьте идею** — по [USER_GUIDE.ru.md](https://github.com/alexar76/aicom/blob/main/docs/USER_GUIDE.ru.md), раздел «Первые 15 минут»: `/admin/login` → **New product** → **Pipeline** и смотрите, как полоса этапов проходит реальные состояния из M4.

4. **Сопоставление курс → фабрика:**

   | Курс | Factory |
   |------|---------|
   | M1 фазы | Полоса этапов пайплайна (реальные агенты) |
   | M2 статус | `/api/public/pipeline-status` на главной |
   | M3 каталог | Выпущенные продукты на `/ai-market/products` |
   | M4 поток этапов | `config/pipeline_flow.json` оркестратора |
   | M5 капстоун | Один зонд по живому деплою |

5. **Проверьте возможность в каталоге Hub перед вызовом** — [hub-integration-guide.md](https://github.com/alexar76/aicom/blob/main/docs/hub-integration-guide.md).

---

## Чеклист самопроверки

После базового трека:

- [ ] Запустили lab01–lab04 локально (и в Colab)
- [ ] Называете пять фаз и агента-владельца каждой
- [ ] Читаете «в пайплайне» vs «выпущено» из `pipeline-status`
- [ ] Объясняете `source ∈ {live, mock}` и роль `COURSE_FACTORY_URL`
- [ ] Проходите оркестратор от `IDEA_RECEIVED` до `COMPLETED` и объясняете ограничитель

После продвинутого добавьте:

- [ ] Запустили lab05 и описали status → products → phases в одном зонде
- [ ] Нацелили лабу на живую фабрику и увидели `source: live`
- [ ] Выпустили сертификат: `--certificate "<имя>" --lang <en|ru|es>`

---

## Типичные проблемы

| Проблема | Решение |
|----------|---------|
| `ModuleNotFoundError: courselib` | Запускайте из корня репозитория; лабы добавляют родительскую папку в `sys.path` |
| Мок «did not become ready» | Конфликт порта или нет extra `[factory]` — переустановите `pip install -e ".[factory,dev]"` |
| `source` всегда `mock`, хотя ждёте `live` | `COURSE_FACTORY_URL` не задан или недоступен; клиент молча откатывается на мок |
| Ошибка импорта `fastapi`/`uvicorn` | Установили без `[factory]`; этот extra даёт сервер мока |
| Пустые RU/ES строки | Задайте `COURSE_LANG`; отсутствующие ключи откатываются на английский (без падений) |
| Ошибка паритета i18n в pytest | Ключ есть в одном каталоге, но не во всех трёх — добавьте в `en.json`, `ru.json`, `es.json` |
| Colab со старым кодом | Перезапустите setup-ячейку, чтобы заново склонировать `main` |

**Проблемы с фабрикой:** [FAQ.ru.md](https://github.com/alexar76/aicom/blob/main/docs/FAQ.ru.md)

---

## Пересборка сайта и ноутбуков

После правок лаб или `i18n/`:

```bash
python3 scripts/build_course_assets.py
```

Гайды в `docs/` правятся вручную — сначала EN, затем зеркала RU/ES.
