# Руководство разработчика Abulafia

Этот документ объясняет, как расширять Abulafia: добавлять навыки, workflows,
агентов, story-сценарии, журнальные досье и команды интерактивной консоли.

Смежные документы:

- [Архитектура](ARCHITECTURE.md)
- [Справочник навыков и агентов](SKILLS_REFERENCE.md)
- [Руководство пользователя](USER_MANUAL.md)
- [Установка и запуск](INSTALL_AND_RUN.md)

## 1. Подготовка окружения

Требования для разработки:

- Node.js от 20.19 до 24.x;
- npm;
- Git;
- PowerShell на Windows или совместимая оболочка на Linux/macOS.

```powershell
git clone https://github.com/Enicast/Abulafia.git
cd .\Abulafia
npm install
npm run typecheck
npm test
```

Запуск из исходников:

```powershell
npm run dev
```

Проверка собранной версии:

```powershell
npm run build
npm run start:dist -- --version
```

## 2. Карта исходников

| Путь | Назначение |
| --- | --- |
| `src/cli.ts` | Разбор аргументов и маршрутизация команд CLI. |
| `src/pi/` | Подготовка и запуск интерактивного Pi runtime. |
| `src/model/` | Каталог моделей, 302AI overlay, авторизация и выбор модели. |
| `src/workflows/story-runner.ts` | Локальный runner и evaluator для A01-A10/S01-S11. |
| `src/bootstrap/sync.ts` | Синхронизация встроенных агентов, тем и файлов в профиль пользователя. |
| `prompts/` | Модельные workflow-команды. |
| `skills/` | Контракты навыков в формате `SKILL.md`. |
| `.abulafia/agents/` | Спецификации базовых и story-агентов. |
| `.abulafia/SYSTEM.md` | Базовый системный контракт интерактивной модели. |
| `extensions/` | Инструменты, slash-команды и компоненты TUI. |
| `knowledge/journals/` | База Journal-Yuga, индекс и накопительные досье. |
| `tests/` | Тесты Node Test Runner. |
| `scripts/` | Сборка, упаковка, установка CLI и Windows installer. |

## 3. Skill, workflow и agent: различия

### Skill

Skill отвечает на вопрос: **по каким правилам выполнять тип задачи**. Это
Markdown-контракт с frontmatter. Он не является отдельным процессом и сам по
себе не запускается.

### Workflow

Workflow отвечает на вопрос: **какую последовательность действий выполнить**.
Файл из `prompts/` становится slash-командой интерактивной консоли; при
`topLevelCli: true` он также доступен как команда `abulafia <name>`.

### Agent

Agent отвечает на вопрос: **какая роль, инструменты и формат результата нужны
исполнителю**. Файл в `.abulafia/agents/` используется как контракт subagent или
story-персоны. Наличие файла агента не означает, что при любой одноименной
команде автоматически создается отдельный модельный процесс.

### Extension

Extension является исполняемым TypeScript-кодом. Он может зарегистрировать
инструмент, slash-команду, компонент интерфейса или обработчик события.

## 4. Как добавить общий skill

Создайте каталог `skills/<skill-id>/` и файл `SKILL.md`:

```markdown
---
name: source-triangulation
description: Проверяет важное утверждение по нескольким независимым источникам.
allowed-tools: web_search, fetch_content, read, write
---

# Source Triangulation

## When to use

Используй навык для проверки спорных или меняющихся фактов.

## Procedure

1. Сформулируй проверяемое утверждение.
2. Найди первичный источник.
3. Найди независимое подтверждение.
4. Зафиксируй расхождения и уровень уверенности.

## Output contract

Сохрани результат в `outputs/<slug>-triangulation.md`.
```

Требования:

- `name` уникален и совпадает с именем каталога;
- `description` объясняет триггер и результат;
- процедура содержит наблюдаемые шаги;
- формат результата и правила деградации определены явно;
- не указывайте инструмент, которого нет в runtime.

После добавления обновите [SKILLS_REFERENCE.md](SKILLS_REFERENCE.md) и тесты.

## 5. Как добавить workflow-команду

Создайте `prompts/triangulate.md`:

```markdown
---
description: Проверить утверждение по независимым источникам.
args: <claim>
section: Research Workflows
topLevelCli: true
---

Verify the following claim using the `source-triangulation` skill: $@

Write the plan to `outputs/.plans/<slug>.md` and the final artifact to
`outputs/<slug>-triangulation.md`.
```

Вызов внутри TUI:

```text
/triangulate <утверждение>
```

Вызов из PowerShell при `topLevelCli: true`:

```powershell
abulafia triangulate "проверяемое утверждение"
```

Workflow исполняется моделью. Он должен задавать проверяемые артефакты и не
заканчиваться только сообщением в чате.

## 6. Как добавить агента

Создайте `.abulafia/agents/source-verifier.md`:

```markdown
---
name: source-verifier
description: Независимо проверяет утверждения и ссылки.
thinking: high
tools: read, write, web_search, fetch_content
output: verification.md
defaultProgress: true
---

You are the source verification agent.

Apply the `source-triangulation` skill. Separate verified facts, inferences,
conflicts, and unresolved claims. Never invent a citation.
```

При старте встроенные агенты синхронизируются в пользовательский профиль.
Изменения в уже измененном пользователем файле не должны молча перезаписывать
его версию; это поведение контролирует `src/bootstrap/sync.ts`.

## 7. Как добавить story-сценарий

Каждая story состоит минимум из четырех частей:

1. Skill-контракт `skills/story-<id>-<name>/SKILL.md`.
2. Agent-контракт `.abulafia/agents/story-<id>-<name>.md`.
3. Запись в `STORY_DEFINITIONS` файла `src/workflows/story-runner.ts`.
4. Тесты, проверяющие регистрацию, артефакт и ожидаемое поведение.

Пример записи:

```ts
{
  id: "S12",
  agent: "story-s12-example",
  skill: "story-s12-example",
  output: "S12-example.md",
  family: "journal-yuga",
}
```

Для Journal-Yuga новый агент обязан применять `journal-yuga-common`, сохранять
состояние инстанса и соблюдать порядок поиска журналов.

### Модельный и локальный запуск story

Эти пути намеренно различаются:

| Вызов | Исполнитель |
| --- | --- |
| `/story S01 ...` в TUI | Модель выполняет `prompts/story.md` и применяет agent/skill-контракты. |
| `/story-local S01 ...` в TUI | TypeScript runner выполняет локальный сценарий без модели. |
| `abulafia story S01 ...` | Модельный `/story` workflow через Pi runtime. |
| `abulafia story-local S01 ...` | Локальный TypeScript smoke-runner без модели. |
| `abulafia evaluate-stories ...` | Оценивает уже созданные артефакты, но не выполняет story заново. |

Не подменяйте модельный анализ шаблонной локальной генерацией. Если локальный
runner не может выполнить новый сценарий содержательно, он должен вернуть
явный частичный или заблокированный результат.

## 8. Состояние Journal-Yuga

Все S-story используют каталог конкретного запуска:

```text
outputs/journal-yuga-runs/<slug>/
```

Минимальный набор:

- `state.yaml`;
- `intake.md`;
- `acceptance-criteria.md`;
- `decision-log.md`;
- `journal-search-log.md`;
- основной story-артефакт;
- `story-run-report.md`.

Пока критерии приемки не выяснены, модель остается на intake-этапе. Фраза
`хватит вопросов` завершает уточнение: неизвестные поля становятся допущениями,
а работа продолжается.

## 9. Как добавить журнал

### 9.1 Основная база

`knowledge/journals/journal_yuga_venue_database.md` является первым локальным
источником для подбора площадки. Добавляйте журналы в принятом в этом файле
формате и не удаляйте ранее накопленные факты без причины.

### 9.2 Досье

Скопируйте структуру `knowledge/journals/_template.md` в новый файл:

```text
knowledge/journals/<stable-id>.md
```

В YAML-frontmatter укажите стабильный `id`, название, географию, язык,
индексацию и дату последней проверки. Отделяйте:

- проверенный факт;
- вывод для конкретной статьи;
- то, что еще нужно проверить.

Наблюдения добавляются в конец истории и не перезаписывают предыдущие записи.

### 9.3 Курированный индекс

Добавьте запись в `knowledge/journals/index.yaml`. Он служит расширяемым
резервным каталогом, а не заменой основной venue database.

Порядок поиска фиксирован:

1. `journal_yuga_venue_database.md`;
2. локальные Markdown-досье;
3. `index.yaml`;
4. интернет, если локальных сведений недостаточно.

## 10. Как добавить extension-команду

Регистрация slash-команды:

```ts
pi.registerCommand("example", {
  description: "Краткое описание команды",
  handler: async (args, ctx) => {
    ctx.ui.notify(`Получено: ${args}`, "info");
  },
});
```

Регистрация model-callable инструмента:

```ts
pi.registerTool({
  name: "example_lookup",
  label: "Example lookup",
  description: "Возвращает данные по идентификатору.",
  parameters: Type.Object({ id: Type.String() }),
  execute: async (_toolCallId, params) => ({
    content: [{ type: "text", text: JSON.stringify({ id: params.id }) }],
    details: {},
  }),
});
```

Правила:

- имя инструмента должно точно совпадать с именем, указанным в контрактах;
- параметры описываются структурной схемой, а не разбираются из случайной
  строки;
- длинный вывод сокращается до ширины TUI;
- ошибка возвращается один раз в понятном виде, без потока `{}`;
- extension не должен показывать скрытые chain-of-thought рассуждения модели.

## 11. Модели и 302AI

Провайдер и модели регистрируются в `src/model/registry.ts`. Для добавления или
изменения модели необходимо согласовать:

- API model ID;
- отображаемое имя;
- API endpoint;
- совместимость протокола;
- окно контекста;
- предел выходных токенов;
- поддержку reasoning/tool calls;
- тесты каталога и фактический smoke-запрос.

Не храните API key в репозитории, `.env.example`, логах или документации.
Команда `abulafia model login 302ai` сохраняет ключ в пользовательском
состоянии, а не в проекте.

## 12. Тестирование

Минимум перед завершением изменения:

```powershell
npm run typecheck
npm test
npm run build
git diff --check
```

Для изменений story дополнительно проверьте:

```powershell
npm run dev -- story S01 .\demo\journal-yuga-console\article.md "подобрать журналы, хватит вопросов"
npm run dev -- evaluate-stories S01 .\outputs\journal-yuga-runs\article
```

Для модельного пути запустите TUI и выполните `/story`, затем убедитесь, что
модель действительно читает источники и формирует содержательный артефакт.

## 13. Сборка и выпуск

Собрать npm/dist-версию:

```powershell
npm run build
npm pack --dry-run
```

### Первая публикация в npm

Публичное имя пакета — `abulafia`. Scope `@companion-ai` принадлежит исходному
проекту и не должен использоваться форком Enicast.

Для первой публикации пакет ещё не существует в npm, поэтому trusted publisher
настроить заранее нельзя. Создайте в npm granular access token с правом
публикации и добавьте его в GitHub:

1. Откройте `Enicast/Abulafia -> Settings -> Secrets and variables -> Actions`.
2. Создайте repository secret `NPM_TOKEN` со значением npm-токена.
3. Перезапустите workflow `Publish and Release` или отправьте новый коммит в
   `main`.
4. После появления `abulafia` на npm настройте для пакета Trusted Publisher:
   GitHub owner `Enicast`, repository `Abulafia`, workflow `publish.yml`.

Workflow использует `NPM_TOKEN` для начальной публикации и OIDC trusted
publishing для последующих выпусков. Если пакет ещё отсутствует и секрет не
задан, preflight завершается с явным сообщением вместо неинформативного `E404`.

Собрать Windows installer:

```powershell
npm run build:windows-installer
```

Ожидаемый результат:

```text
dist/installer/Abulafia-Setup-<version>-x64.exe
```

Перед публикацией:

1. Проверьте `npm test`, `typecheck` и сборку.
2. Проверьте содержимое `npm pack --dry-run`.
3. Выполните поиск секретов и локальных абсолютных путей.
4. Проверьте установку на чистом профиле Windows.
5. Проверьте `abulafia --version`, `abulafia doctor` и запуск TUI.

## 14. Чек-лист изменения

- Контракт задачи определен в skill или workflow.
- Агент имеет только необходимые инструменты.
- Результат сохраняется в предсказуемый файл.
- Для долгой работы видны этап и фактические действия, но не скрытые мысли.
- Ошибка дает понятный блокирующий статус.
- Story state можно продолжить после перезапуска.
- Новые скиллы описаны в `SKILLS_REFERENCE.md`.
- Пользовательская команда описана в `USER_MANUAL.md`.
- Архитектурное изменение отражено в `ARCHITECTURE.md`.
- Добавлены тесты и выполнена сборка.
