docs(agents): вернуть в репозиторий постановки A42-A56 и отчёт A30

Тринадцать файлов существовали только на диске ПК владельца, в рабочей
копии, отставшей от origin/main на 122 коммита. Их реализация и тесты
давно влиты: tests/test_a42_provider_connect.py,
test_a49_subagents_skills_memory.py, test_a51_hub_controls_hermes.py,
test_a52_local_models_supervisor_dual.py, test_a55_account_connection.py,
test_a56_context_compression.py и другие. Постановок, объясняющих, что
эти тесты обязаны доказывать, в репозитории не было.

Правило записано в agents/AGENTS.md: задание живёт в репозитории, а не в
переписке и не в личных папках на диске.

A48, A50 и A54 не переносятся: они уже есть на origin под другими именами,
содержимое совпадает с точностью до перевода строки в конце файла.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hermes Team 2026-09-03 18:16:35 +07:00
parent 93da1b22fd
commit 8b67f0dadb
13 changed files with 2029 additions and 0 deletions

View file

@ -0,0 +1,114 @@
# Отчёт независимого оркестратора: Release Gate ветки `codex/workflow-canvas` (A30)
## Дата проведения
2026-08-26
## Объект аудита
- **Ветка:** `codex/workflow-canvas`
- **Цель:** Независимая проверка реализации задания A30 («Главный экран "Обзор" — граф workflow, файлы агентов, LIVE»).
---
## 1. Сводка Git и состояние репозитория
- **`START_HEAD` (базовый коммит / merge-base с `main`):** `d6ec34d482a4e00a2017c7b53e934a82df0cc5ad`
- **`FINAL_HEAD` (коммит ветки A30):** `0c19738e29683c215352ea9de1b68a0a2e95b1f8` (`feat(web): add workflow canvas and live agent workspace`)
- **`origin/main`:** `c35bc4868d62cfa7abb7a1a4c1c17eca51eb6ce5`
- **Состояние рабочей директории (`git status`):**
- Нестажированные изменения в бинарниках и установщике (`installer/HermesHubSetup.cs`, `launcher/HermesHub.exe`, `launcher/HermesHubWeb.exe`).
- Нестажированный фикс CORS в `src/antigravity_provider/router/web/server.py` (перенесённый из `c35bc48` на `main`).
- Неотслеживаемые задания в inbox (`agents/inbox/2026-08-25-A32-remove-desktop.md`, `agents/inbox/2026-08-26-antigravity-release-gate-a30.md`).
---
## 2. Результаты детерминированных проверок
### 2.1. Линтер `ruff check .`
- **Результат:** `All checks passed!` (0 ошибок, 0 предупреждений).
### 2.2. Полный регрессионный сьют `pytest tests/ -v`
- **Результат:** **458 passed, 2 skipped, 3 deselected, 1 failed** (всего 461 тест).
- **Время прогона:** 86.74 сек.
### 2.3. Скрипт `scripts/release_gate.py`
- **Результат:** `[RELEASE GATE: FAILED] One or more checks failed. Release blocked.`
- **Причина:** Падение теста обратной совместимости `tests/test_web_parity_a21.py::test_web_client_html_and_js_7_views_parity`.
---
## 3. Реестр найденных дефектов
| ID | Приоритет | Компонент | Описание дефекта и минимальное воспроизведение |
| :--- | :--- | :--- | :--- |
| **DEF-01** | **P1** | `tests/test_web_parity_a21.py:133` | **Устаревшая проверка селектора в тестах регрессии.** Тест проверяет наличие старого контейнера `overview-route-diagram` в `index.html`. В рамках A30 главный экран «Обзор» был полностью перестроен в Workflow Canvas (`workflow-canvas`, `workflow-main-layout`), и старый селектор был правомерно удалён из разметки, но тест не был обновлён под новый layout A30. <br>**Воспроизведение:** `pytest tests/test_web_parity_a21.py -k test_web_client_html_and_js_7_views_parity`. |
| **DEF-02** | **P2** | `server.py` / `git` | **Отставание ветки от `origin/main`.** Ветка `codex/workflow-canvas` ответвлена от `d6ec34d` и не включает коммит безопасности `c35bc48` (`fix(security): любой сайт во вкладке рядом мог управлять хабом`). Перед финальным слиянием в `main` требуется rebase / merge с актуальным `main`. |
---
## 4. Результаты проверки подсистем A30
### P0-1. Модель агента и Agent File
- **Статус:** **PASS**
- Сервис `WorkflowService` в [`workflow_service.py`](file:///c:/Users/Ochenstarik/Agent_projects/hermes-hub/src/antigravity_provider/router/workflow_service.py) реализует полное управление жизненным циклом агентов: `create_agent`, `update_agent`, `delete_agent`.
- Роли роутера автоматически мигрируют в сущности агентов.
- Файлы агентов создаются физически на диске в `agents/{role}.md` (например, `agents/orchestrator.md`, `agents/coder-primary.md`) и содержат реальный Markdown.
- Удаление агента, задействованного в ребрах графа, требует явного подтверждения (`confirmation_required: True`), предотвращая повреждение графа.
- Проверено тестами: `test_router_roles_migrate_to_agents_and_create_real_files`, `test_create_update_file_and_restart_persistence`, `test_delete_requires_explicit_confirmation_when_referenced`.
### P0-2. Граф workflow (Canvas, EDIT/LIVE, Циклы)
- **Статус:** **PASS**
- Граф реализован на чистом SVG + HTML5 (без npm, без react, без сторонних зависимостей сборки) в [`workflow.js`](file:///c:/Users/Ochenstarik/Agent_projects/hermes-hub/src/antigravity_provider/router/web/static/workflow.js) и [`workflow.css`](file:///c:/Users/Ochenstarik/Agent_projects/hermes-hub/src/antigravity_provider/router/web/static/workflow.css).
- **Режимы:** Чёткое переключение между `LIVE` (мониторинг исполнения) и `EDIT` (редактирование графа, соединение портов).
- **Редактор ребра:** Модальное окно позволяет задавать условия переходов (`SUCCESS`, `REVIEW_PASSED`, `REVIEW_FAILED`) и подписи.
- **Поддержка циклов:** Циклические маршруты (`Кодер 1 → Ревьюер → Кодер 1`) поддержаны и валидируются.
- **Защита от бесконечного зацикливания:** Параметр `max_iterations` отображается на экране (например, `Итерация: 2 / 5`), сохраняется в конфигурации и принудительно останавливает цикл с генерацией явного события `WORKFLOW_MAX_ITERATIONS`.
- **Элементы управления:** Мини-карта, масштабирование (`- 100% + ⛶`), легенда состояний узлов и рёбер.
### P0-3. LIVE-мониторинг, события и обработка ошибок
- **Статус:** **PASS**
- Поддержаны 5 состояний агента: `Ожидает` (серый), `Работает` (синий), `Проверяет` (жёлтый), `Ошибка` (красный), `Завершено` (зелёный).
- Тексты реальных ошибок провайдеров (например, `No authentication token found for Codex profile 'codex-orch'`) доходят до статуса запуска и списка событий.
- Прерванный перезапуском прогон корректно помечается статусом `interrupted` с записью события `WORKFLOW_INTERRUPTED`.
- Проверено тестами: `test_live_cycle_stops_with_explicit_iteration_limit_event`, `test_interrupted_run_is_reported_not_silently_completed`, `test_provider_error_text_reaches_run_and_events`.
### P0-4. Честность данных (Zero Fake / Zero Mock)
- **Статус:** **PASS**
- Поиск по кодовой базе показал полное отсутствие захардкоженных демонстрационных чисел из макета (`12`, `3.42 с`, `1.42M`, `94.2%`, `42`, `account-01...`).
- Все 5 оперативных KPI-показателей на экране «Обзор» берутся из реальных источников:
1. *Активные задачи:* `workflow.run.status` (0 или 1).
2. *Агенты онлайн:* `readiness.roles_ready_count / readiness.total_roles` из сервиса `readiness`.
3. *Среднее время ответа:* `telemetry.global.latency_p50_ms` (при отсутствии вызовов: `Н/Д: за 24 часа нет измеренных вызовов`).
4. *Использование токенов:* `telemetry.global.total_tokens` (при отсутствии: `Н/Д: провайдеры не вернули usage`).
5. *Успешность задач:* отношение `successful_calls / total_calls` (при отсутствии: `Н/Д: за 24 часа нет завершённых вызовов`).
- Состояния загрузки (`workflow.is_loading`) явно отделены от отсутствия данных.
### P0-5. Неприкосновенность десктопного UI
- **Статус:** **PASS**
- Проверка `git diff --stat d6ec34d 0c19738 -- src/antigravity_provider/router/ui` подтвердила **0 изменений** в каталоге `router/ui/**`.
---
## 5. Проверка артефактов и скриншотов
Все 5 обязательных скриншотов присутствуют в каталоге `docs/screenshots/a30/` и проверены:
1. [`overview-live.png`](file:///c:/Users/Ochenstarik/Agent_projects/hermes-hub/docs/screenshots/a30/overview-live.png) — Главный экран в режиме LIVE с 6 агентами, честными статусами «Н/Д» и мини-картой.
2. [`overview-edit-inspector.png`](file:///c:/Users/Ochenstarik/Agent_projects/hermes-hub/docs/screenshots/a30/overview-edit-inspector.png) — Режим EDIT с выбранным узлом «Кодер 1», портами соединения и панелью инспектора (вкладки Основное, Модель, Инструкции, Инструменты, Память).
3. [`edge-editor.png`](file:///c:/Users/Ochenstarik/Agent_projects/hermes-hub/docs/screenshots/a30/edge-editor.png) — Модальное окно создания/редактирования ребра (`coder-primary` → `reviewer`, условие `SUCCESS`).
4. [`agent-file-editor.png`](file:///c:/Users/Ochenstarik/Agent_projects/hermes-hub/docs/screenshots/a30/agent-file-editor.png) — Редактор файла агента `agents/coder-primary.md` с реальным содержимым.
5. [`overview-live-provider-error.png`](file:///c:/Users/Ochenstarik/Agent_projects/hermes-hub/docs/screenshots/a30/overview-live-provider-error.png) — Отображение реальной ошибки провайдера в узле «Главный оркестратор» (красный статус) и в журнале событий LIVE.
---
## 6. Пропущенные проверки
- **Пропущенных проверок нет.** Все 10 пунктов регламента выполнены в полном объёме.
---
## 7. Итоговый вердикт Release Gate
> **ВЕРДИКТ: `BLOCKED` (Требуется исправление 1 теста и Rebase)**
**Обоснование:**
1. Функциональная реализация A30 (`WorkflowService`, Canvas, Agent Files, LIVE/EDIT, Cycle limits, Data honesty) выполнена качественно и полностью соответствует ТЗ.
2. Автоматический Release Gate заблокирован из-за дефекта **DEF-01** (устаревший ассерт `overview-route-diagram` в `tests/test_web_parity_a21.py:133`), дающего 1 падение из 461 теста.
3. Ветка требует rebase на актуальный `origin/main` (включение фикса безопасности CORS **DEF-02**) и обновления теста `test_web_parity_a21.py` на селектор `workflow-canvas`.

View file

@ -0,0 +1,62 @@
# Передача Antigravity: A31 и A32
## Цель
Последовательно выполнить A31 и A32. Не объединять их в один огромный непроверяемый коммит.
Полные технические задания:
1. `agents/inbox/2026-08-25-A31-preflight-state-batching-pii.md`
2. `agents/inbox/2026-08-25-A32-remove-desktop.md`
## Текущее состояние на момент передачи
- `origin/main`: `c35bc48`
- A28: `origin/antigravity/subagents-role-registry``b149a6a`
- A29: `origin/antigravity/design-system-routing``a8c37ca`
- A30: `codex/workflow-canvas``32bf2c9`
- A28, A29 и A30 пока не являются предками `origin/main` и не являются предками друг друга.
- A31 и A32 ещё не реализованы.
Рабочая директория владельца содержит незакоммиченные сборочные артефакты. Их не забирать, не очищать и не перезаписывать. Работать в отдельном чистом worktree/клоне.
## Задача 1: подготовить интеграционную базу
До A31 и A32 собрать A28, A29 и A30 поверх актуального `origin/main` в отдельной интеграционной ветке. Конфликты разрешать по смыслу, сохраняя одновременно:
- реестр ролей и субагентов A28;
- дизайн-систему и routing drag-and-drop A29;
- workflow canvas, Agent Files и LIVE/EDIT A30;
- security fix `c35bc48`.
После интеграции выполнить `ruff check .`, полный `pytest tests/ -v` и `python scripts/release_gate.py`. Известный устаревший ассерт A30 на `overview-route-diagram` должен быть заменён проверкой актуального `workflow-canvas`, а не обходиться skip/xfailed.
Не начинать A31, пока интеграционная база не закоммичена, не отправлена в `origin` и release gate не зелёный. В отчёте дать SHA всех взятых голов и итоговый SHA интеграционной ветки.
## Задача 2: A31
Создать отдельную ветку от проверенной интеграционной базы и полностью выполнить `2026-08-25-A31-preflight-state-batching-pii.md`.
Обязателен порядок из задания: реализация Flash, затем независимый аудит Pro. Не заявлять выполнение проверок, которые фактически не запускались. Особенно приложить доказательства для намеренно сломанного preflight, восстановления workflow после перезапуска, отсутствия секретов в состоянии, failover занятого локального сервера, получения лимитов модели без выдуманных чисел и различимого маскирования почт.
Сдать отдельный `FINAL_COMMIT_SHA`, ветку в `origin`, чистый `git status` и точный итог тестов.
## Задача 3: A32
Начинать только после принятия A31. Создать отдельную ветку от принятого результата A31 и полностью выполнить `2026-08-25-A32-remove-desktop.md`.
Первый шаг — таблица паритета десктопа и веба. Если обнаружена функция без веб-эквивалента, остановить удаление и честно перечислить пробелы. При полном паритете удалить десктоп, его launcher, зависимости и старый ярлык строго по заданию.
Обязательны реальные проверки чистой Windows-установки, обновления поверх старой версии с десктопом и Linux-установщика. Учётные данные, настройки и цепочки ролей при обновлении должны сохраниться. Реальный пропуск любой платформенной проверки отметить как пропуск, а не PASS.
Сдать отдельный `FINAL_COMMIT_SHA`, ветку в `origin`, чистый `git status` и точный итог тестов.
## Запреты
- Не работать в грязной директории владельца.
- Не пушить реализацию напрямую в `main`.
- Не создавать тег `v0.1.1`.
- Не смешивать A31 и A32 в одной ветке или одном коммите.
- Не удалять десктоп до доказанного веб-паритета.
- Не подменять живые проверки моками и не выдумывать результаты платформенных прогонов.

View file

@ -0,0 +1,166 @@
# Задание A42: подключение провайдеров — OpenRouter, NVIDIA, Ollama, квота Codex
## Дата поступления
2026-08-31
## База
`origin/main` (`ff303b5`) — туда уже слиты правки ревьюера по вебу и A41 (чистая первая установка).
```
git fetch origin --prune
git checkout -b antigravity/a42-provider-connect origin/main
```
В `main` напрямую не пушить.
## Порядок исполнения
Два прохода: **Flash** реализует, **Pro** проводит аудит. Пункт **P0-5** написан для аудитора.
Это задание **по коду**. Вёрстка и холст — отдельное задание A43, туда не залезать.
---
## Задача
Владелец сообщает: «опенроутер не подключается, нвидиа не подключаются, кодекс выдаёт ошибку по квоте, хотя квоты полные, оллама не выдаёт облачные модели».
Причины найдены ревьюером и проверены по коду. Заново их выяснять не нужно — нужно чинить.
## Что проверено ревьюером
### OpenRouter и NVIDIA реализованы наполовину
```
adapters/__init__.py OpenRouterAdapter и NvidiaAdapter в реестре есть
web/static/index.html:163 пункты в списке провайдеров есть
app.js:2482 шаг мастера с полем API-ключа и Base URL есть
action_handler.py:574 add_account сохраняет ТОЛЬКО для
(local, local-llm, llama.cpp, ollama, vllm)
и только при непустом base_url
action_handler.py:588 для всех остальных возвращается ok=True с текстом
«Навигация» — и не сохраняется ничего
```
То есть мастер докладывает об успехе и **не сохраняет ничего**. Аккаунт не появляется, потому что его никто не создал.
Дальше по цепочке пусто тоже:
```
auto_assigner.py:129 слоты объявлены для ollama; openrouter и nvidia отсутствуют
auto_assigner.py:219 роли по умолчанию — то же самое
router_config.py в конфигурации по умолчанию нет ни одного из трёх
model_discovery_service.py:216 _probe_provider не имеет ветки ни для
openrouter, ни для nvidia, и возвращает None
```
### Ollama обнаруживает не то
`model_discovery_service.py:325` заводит `ollama` в одну ветку с `local`, `llama.cpp`, `vllm`. Эта ветка:
1. перебирает **зашитые** идентификаторы `local-1` и `local-2` — профиль `ollama-1` не смотрит вообще;
2. читает учётные данные провайдера `local`, а не `ollama`;
3. по умолчанию идёт на `http://127.0.0.1:8081/v1` — это порт llama.cpp, а не Ollama (11434);
4. дёргает `/v1/models` и ничего не знает про облачные модели Ollama.
Скриншот владельца: «Список моделей ещё не получен от провайдера ollama» при подключённом `ollama-1`.
Та же болезнь рядом: ветка Codex перебирает зашитые `codex-orch`, `codex-worker-1`, `codex-worker-2`. После A26 идентификаторы выдаются автоматически (`codex-4`, `codex-5`), и такой профиль обнаружение пропустит.
### «Квота исчерпана» при полной квоте
На скриншоте у Codex значок «Квота исчерпана», а Session и Weekly показывают `Н/Д`. То есть **вердикт об исчерпании выносится там, где квота не измерена вовсе**.
```
unified_health.py:467 ветка: max_cd > 0 либо overall_state == QUOTA_EXHAUSTED
→ health_state = STATUS_QUOTA_EXHAUSTED
unified_health.py:470 ветка RATE_LIMITED идёт НИЖЕ
```
`max_cd` берётся из `frec.reset_at > now` — это **окно отката после ошибки**, а не остаток квоты. Отсюда два разных дефекта:
1. Любой откат показывается как исчерпание квоты, хотя квота может быть полной.
2. Ветка `RATE_LIMITED` практически мертва: при активном лимите запросов `reset_at` всегда в будущем, поэтому строка 467 срабатывает раньше и лимит запросов выдаёт себя за исчерпанную квоту.
И третье, в `health_tracker.py:483`: при пустом имени модели или значении `default` исчерпанным помечается **весь аккаунт** (`record.overall_state`). Hermes имя модели передаёт не всегда.
Классификатор в `codex_adapter.py:132` ловит подстроку `quota` в любом месте текста ошибки — проверить, не попадают ли туда сообщения, к квоте не относящиеся.
---
## P0-1. OpenRouter и NVIDIA подключаются по-настоящему
1. **`add_account` сохраняет профиль** для `openrouter`, `nvidia`, `nvidia-nim`: создаёт определение профиля, пишет учётные данные (ключ и адрес), назначает роль — по образцу существующей локальной ветки.
2. **Слоты и роли по умолчанию** для обоих провайдеров в `AutoAssigner`, как сделано для `ollama`.
3. **Адреса по умолчанию**: `https://openrouter.ai/api/v1` и `https://integrate.api.nvidia.com/v1`; владелец может переопределить в мастере.
4. **Ветка с мнимым успехом не должна остаться ловушкой.** Провайдер, для которого сохранение не реализовано, обязан получать честный отказ с причиной, а не `ok: True`. Это главное требование пункта: молчаливый успех стоил владельцу нескольких попыток подключения.
## P0-2. Обнаружение моделей для трёх провайдеров
1. **OpenRouter**: запрос списка моделей по адресу профиля с его ключом.
2. **NVIDIA**: то же самое.
3. **Ollama — отдельная ветка**, не общая с llama.cpp:
- адрес берётся из **самого профиля**, а не из зашитых `local-1`/`local-2`;
- учётные данные читаются для провайдера `ollama`;
- по умолчанию `http://127.0.0.1:11434`;
- локальные модели — через нативный `/api/tags`;
- **облачные модели Ollama** — отдельный источник, требующий ключа. Выяснить по действующей документации Ollama способ и адрес; **не выдумывать эндпоинт**. Если способ не подтверждён — так и написать в отчёте, а в интерфейсе показать `Н/Д` с причиной.
4. **Зашитые идентификаторы профилей убрать везде**, включая ветку Codex: перебирать профили провайдера из конфигурации. После A26 идентификаторы выдаются автоматически, и любой зашитый список рано или поздно промахнётся.
5. **Ошибка обнаружения показывается с текстом ответа сервера.** Сейчас `_probe_provider` возвращает `None` и когда ветки нет, и когда сервер отказал — владелец не может отличить одно от другого.
## P0-3. Квота говорит только то, что измерено
1. **Откат после ошибки — это не исчерпание квоты.** Разделить состояния: исчерпание объявлять по измеренному остатку, откат показывать как откат с причиной и временем окончания.
2. **Порядок веток исправить**: лимит запросов не должен выдавать себя за исчерпанную квоту.
3. **Ошибка без имени модели не помечает весь аккаунт.** Помечать конкретное семейство; общий вердикт — только при подтверждении.
4. **Ярлык называет источник.** «Квота исчерпана» — когда есть измерение. Иначе «Откат до HH:MM после ошибки: текст».
5. **Классификатор Codex** проверить на ложные срабатывания подстроки `quota`.
## P0-4. Проверка исполнением
Заглушек недостаточно, но и ключей владельца у исполнителя нет. Поэтому:
1. **Сохранение профиля** проверить с заведомо неверным ключом: профиль обязан создаться, а проверка подключения — вернуть внятную ошибку авторизации, а не тишину.
2. **Ollama** проверить на живом сервере: локальные модели через `/api/tags` обязаны появиться в списке.
3. **Квота**: смоделировать откат после ошибки и убедиться, что интерфейс не пишет «квота исчерпана» при неизмеренной квоте.
4. **Отказ вместо мнимого успеха** проверить отдельно.
## P0-5. Аудит вторым проходом
1. **Искать оставшиеся зашитые идентификаторы профилей** по всему коду — это повторяющийся класс дефекта.
2. **Проверить, что мнимых успехов не осталось**: действие, ничего не сохранившее, не возвращает `ok: True`.
3. **Эндпоинт облачных моделей Ollama** сверить с документацией. Выдуманный адрес — дефект того же рода, что выдуманные метрики в A38.
4. **Побочные изменения** объяснить.
5. **Пропущенный пункт назвать пропущенным.**
---
## Ограничения
- Ключи владельца не запрашивать и в репозиторий не класть.
- Каталог `~/.hermes/agy_profiles/` не трогать.
- Вёрстку и холст не менять — это A43.
- Версию `0.1.1` не поднимать.
- Правило честности без исключений: неизмеренное показывать как `Н/Д` с причиной.
## Критерии приёмки
1. Ветка в `origin`, `git status` чист.
2. OpenRouter и NVIDIA подключаются: профиль создаётся, учётные данные сохраняются, аккаунт виден в списке; проверено.
3. Действие, ничего не сохранившее, возвращает отказ с причиной; проверено.
4. Обнаружение моделей работает для openrouter, nvidia и ollama; для Ollama проверено на живом сервере.
5. Зашитых идентификаторов профилей в обнаружении не осталось.
6. Ошибка обнаружения доходит до интерфейса с текстом.
7. Откат после ошибки не показывается как исчерпание квоты; лимит запросов показывается как лимит запросов.
8. Ошибка без имени модели не помечает весь аккаунт.
9. `ruff check .` чисто; релизный гейт не ухудшен.
10. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`. На `origin/main` сейчас **491 passed**.
## Главное
Два провайдера нельзя подключить вовсе, и мастер при этом рапортует об успехе — владелец несколько раз повторял заведомо безрезультатное действие. Третий подключается, но опрашивается по чужому адресу и чужому имени профиля. А Codex объявляется исчерпанным по квоте в тот момент, когда квота не измерена ни разу. Общее у всех четырёх — интерфейс утверждает то, чего не проверял.
## Порядок сдачи
Передать точный `FINAL_COMMIT_SHA`.

View file

@ -0,0 +1,130 @@
# Задание A43: интерфейс по макетам и работающий холст
## Дата поступления
2026-08-31
## База
`origin/main` (`ff303b5`) — туда уже слиты правки ревьюера по вебу и A41 (чистая первая установка).
```
git fetch origin --prune
git checkout -b antigravity/a43-frontend-canvas origin/main
```
В `main` напрямую не пушить.
## Порядок исполнения
Два прохода: **Flash** реализует, **Pro** проводит аудит. Пункт **P0-5** написан для аудитора.
Это задание **по интерфейсу**. Провайдеры, обнаружение моделей и квоты — задание A42, туда не залезать. Пересечение файлов: `app.js` и `workflow.js` правит только это задание; A42 работает в Python.
Исполнитель работает на машине владельца (Windows), где хаб запущен и есть живой снапшот с подключёнными аккаунтами. Это принципиально: макет надо сверять с работающим интерфейсом, а не с воображаемым.
---
## Задача
Владелец: «криво отрисовано», «окно интерактивно ужасно, посмотри как сделано у n8n», «вообще весь интерфейс не соответствует фронтенду, просто посмотри как отрисовано в макете».
## Что уже сделано ревьюером — не переделывать
В базовой ветке уже исправлено, проверено и закоммичено:
```
app.js экран маршрутизации читал currentSnapshot.profiles — такого ключа
в снапшоте нет (поле называется all_profiles). Отсюда пустая колонка
аккаунтов, счётчик «0 аккаунтов» и иконки-заглушки в цепочках.
app.js убрана полоса квоты с зашитым width:80%, одинаковая у всех аккаунтов
workflow.css подписи связей центрируются (не было text-anchor) и получили обводку
workflow.js список моделей берётся из discovered_models провайдера, а не из
preferred_models профиля; настроенная модель всегда есть в списке
```
Последнее чинило скрытую подмену: если модели агента не было в списке, ни один вариант не выбирался, показывался первый, и сохранение записывало агенту не ту модель.
## Про генераторы интерфейса
Владелец спрашивал про `github.com/abi/screenshot-to-code`. Ревьюер проверил и **не рекомендует**: инструмент выдаёт самостоятельную страницу на Tailwind без данных, а клиент здесь без сборки и без npm, всё держится на привязке к `/api/snapshot` (решение зафиксировано в `docs/web-api/CONTRACT.md` §1). Переподключать сгенерированную страницу к снапшоту, действиям и опросу состояния дороже, чем сверстать по макету.
Опираться на макеты из `Desktop/фронтенд/` напрямую.
---
## P0-1. Холст ведёт себя как холст
Сейчас `workflow.css:28` задаёт `.workflow-canvas` фиксированную высоту 430 px и `overflow:hidden`, а обработчики мыши висят только на узлах и портах (`workflow.js:171`). Колесо не обрабатывается, полотно не двигается. Всё, что выехало за 430 px, недостижимо — узел не вернуть, связь не увидеть.
Требуется поведение, привычное по n8n:
1. **Панорамирование полотна** — перетаскиванием пустого места и средней кнопкой.
2. **Масштаб колесом** с курсором как центром, а не только кнопками.
3. **Холст тянется по высоте окна**, а не заперт в 430 px.
4. **Вписать в экран** — кнопка уже есть (`fitWorkflowGraph`), она должна учитывать панорамирование.
5. **Узел нельзя утащить в недосягаемость**: либо границы, либо «вписать» всегда возвращает всё в поле зрения.
Связи и узлы считаются в одной системе координат — это ревьюер проверил, ошибки там нет. При добавлении панорамирования **сохранить это свойство**: смещение обязано применяться к обоим слоям одинаково, иначе связи отклеятся от узлов.
## P0-2. Экраны соответствуют макетам
Пройти по макетам из `Desktop/фронтенд/` и привести экраны в соответствие: сетка, отступы, типографика, состояния карточек, расположение панелей.
1. **Расхождения перечислить списком** до начала работы — что именно не совпадает на каждом экране. Список приложить к отчёту.
2. **Скриншот до и после** по каждому экрану. Это единственный способ показать владельцу результат: он сравнивает глазами.
3. **Три темы остаются рабочими** — светлая, средняя, тёмная. Средняя была реализована в стилях, но отсутствовала в списке выбора; проверить, что все три переключаются.
4. **Ничего не ломать в данных.** Экран берёт данные из снапшота; если макет требует поля, которого в снапшоте нет, — показать `Н/Д` с причиной и назвать это в отчёте, а не придумать значение.
## P0-3. Пустые состояния и честность
1. **Пустое — это пустое, а не ошибка.** Нет подключённых аккаунтов — экран говорит об этом и предлагает подключить, а не показывает ноль как поломку.
2. **Загрузка отличается от отсутствия.** «Список моделей ещё не получен» и «моделей нет» — разные сообщения.
3. **Ни одного зашитого числа в интерфейсе.** Полоса с `width:80%` уже убрана; поискать оставшиеся такие же. Любой процент, столбик или счётчик обязан приходить из снапшота.
## P0-4. Проверка исполнением
Прогнать тесты недостаточно — дефекты этого задания видны только глазами.
1. **Открыть хаб** и пройти все экраны на живом снапшоте владельца.
2. **Холст**: подвигать полотно, покрутить колесо, утащить узел за край и вернуть кнопкой «вписать».
3. **Инспектор агента**: убедиться, что показанная модель совпадает с настроенной, а список содержит модели провайдера.
4. **Маршрутизация**: колонка аккаунтов заполнена, счётчик совпадает с числом подключённых, перетаскивание работает.
5. **Три темы** переключить и посмотреть каждый экран.
## P0-5. Аудит вторым проходом
1. **Сверить скриншоты с макетами**, а не с описанием работы. Совпадение проверяется глазами, а не отчётом исполнителя.
2. **Связи не отклеились от узлов** ни на одном масштабе и смещении — проверить на нескольких значениях.
3. **Зашитые числа** искать целенаправленно по всему клиенту.
4. **Проверить, что данные не потерялись**: экраны, которые работали, продолжают работать.
5. **Побочные изменения** объяснить.
6. **Пропущенный пункт назвать пропущенным.**
---
## Ограничения
- **Без сборки, без npm, без фреймворка** — решение зафиксировано в `docs/web-api/CONTRACT.md` §1. Tailwind, React и генераторы страниц не вносить.
- Python не трогать: провайдеры и квоты — задание A42.
- Учётные данные и `~/.hermes/agy_profiles/` не трогать.
- Версию `0.1.1` не поднимать.
- Правило честности без исключений.
## Критерии приёмки
1. Ветка в `origin`, `git status` чист.
2. Холст панорамируется и масштабируется колесом; высота не заперта; связи держатся за узлы на любом масштабе и смещении — проверено.
3. Расхождения с макетами перечислены списком; по каждому экрану приложены скриншоты до и после.
4. Три темы работают на всех экранах.
5. Пустые состояния показываются как пустые, загрузка отличается от отсутствия.
6. Зашитых чисел в интерфейсе не осталось.
7. Экран маршрутизации, инспектор агента и список аккаунтов проверены на живом снапшоте.
8. `ruff check .` чисто; релизный гейт не ухудшен.
9. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`. На `origin/main` сейчас **491 passed**.
## Главное
Владелец смотрит на готовый макет и на работающую программу и видит разные вещи. Плюс холст, из которого узел можно утащить за край и не вернуть. Задание закрывает ровно это: чтобы экран совпадал с макетом, а граф вёл себя как граф, к которому владелец привык в n8n.
## Порядок сдачи
Передать точный `FINAL_COMMIT_SHA`.

View file

@ -0,0 +1,198 @@
# Задание A44: вернуть кодер в строй, поставить llama-swap, поправить отчёт A40
## Дата поступления
2026-08-31
## База
Ветка A40 (`origin/antigravity/a40-benchmark-redo`, `d545252`) — правки отчёта ложатся туда же, где он живёт.
```
git fetch origin --prune
git checkout -b antigravity/a44-restore-server origin/antigravity/a40-benchmark-redo
git merge origin/main # ветка A40 отстала: в main уже A41 и правки ревьюера
```
В `main` напрямую не пушить.
## Порядок исполнения
Два прохода: **Flash** исполняет, **Pro** проводит аудит. Пункт **P0-5** написан для аудитора.
Задание **по коду и серверу**. Вёрстка — A43, провайдеры — A42, туда не залезать.
---
## Что признано и переделке не подлежит
Ревьюер проверил A40 исполнением на сервере. Проверка таблицы пройдена:
```
все семь файлов GGUF существуют по указанным путям
размеры совпадают с отчётом ДО БАЙТА (stat -c %s по каждому)
sha256 первых 64 МБ granite-4.2 пересчитана независимо — совпала:
f155ab58fe3ff46c4daa7d65633347da343143771238ddf63ecba25b8e10a06d
DeepSeek-Coder-V2-Lite и Phi-4, выдуманные в A38, действительно скачаны
и измерены; прежние числа отозваны
```
Это хорошая работа, и требование P0-1 из A40 выполнено. Стенд, набор задач и таблицу **не переделывать**.
Претензии ниже касаются состояния сервера и двух столбцов отчёта.
---
## Что сломано — проверено ревьюером
### Кодер владельца не запущен как служба
```
systemctl is-active qwen-coder → inactive
systemctl show qwen-coder SubState → dead
порт 8081 при этом отвечает: его обслуживает процесс, поднятый ВРУЧНУЮ
PID 2713480, ELAPSED 07:50 на момент проверки
/home/ochenstarik/llama.cpp/build/bin/llama-server -m .../Qwen3.8-27B-Q4_K_M.gguf
```
Перезагрузка сервера или падение процесса — и локального кодера нет. Владелец пользуется этой машиной ежедневно.
### Контекст урезан вшестеро против штатного
```
/etc/systemd/system/qwen-coder.service ExecStart ... -c 196608
фактически запущено -c 32768
```
У Hermes порог **64К контекста**: при 32768 модель не проходит отбор, и локальный кодер бесполезен. Это ровно та проблема, ради которой делалось A39.
### Отсюда же расхождение скоростей в отчёте
Отчёт даёт Qwen3.8-27B **30,31 ток/с**. Независимый замер ревьюера на штатной конфигурации давал **13,6 ток/с**. Разницу объясняет контекст: замеры шли на 32К, служба владельца работает на 192К.
В строке «Условия измерений» перечислены квантование, `-ngl 99`, `--flash-attn on`, `--cache-type-k/v q8_0`, `--parallel 1`, `--temp 0.2` — и **размер контекста не указан вовсе**. Без него числа нельзя соотнести с реальной установкой владельца, а именно ради этого отчёт и делался.
### Столбец VRAM измеряет не то
```
отчёт: Qwen3 4B Instruct 2507 → 24 894 МиБ
живой замер того же процесса:
nvidia-smi --query-compute-apps=pid,used_memory
1570163 5 440 МиБ llama-server ... Qwen3-4B ...
```
В отчёт попала **общая занятость карты** вместе с соседней резидентной моделью, а не потребление самого процесса. Отсюда абсурд: 4B «занимает» 24 894 МиБ, а 27B — 24 696 МиБ. Для планирования «сколько моделей поместится» столбец непригоден, а владелец задаёт именно этот вопрос.
### llama-swap не установлен
```
command -v llama-swap → не найден
systemctl is-active llama-swap → inactive
```
Установка llama-swap была критерием приёмки 2 в A38 и не выполнена ни там, ни здесь.
### Мусор от прерванной закачки
```
/srv/ai/models/nemotron-3.5-30b 511 МБ
```
Отчёт честно говорит, что модель не проверена. Но огрызок остался лежать.
---
## P0-1. Кодер возвращается в штатное состояние
Это первое по важности: сейчас у владельца сломан рабочий инструмент.
1. Ручной процесс на 8081 остановить.
2. `qwen-coder` поднять **штатно, через systemd**, с контекстом `196608` из юнита.
3. Убедиться, что после `systemctl restart` служба поднимается сама и порт отвечает.
4. **Проверить включение в автозапуск** (`systemctl is-enabled`): служба обязана пережить перезагрузку.
5. `qwen-compressor` на 8082 проверить тем же порядком.
Юнит-файлы **не переписывать** без нужды: это машина владельца, он правит их сам. Если правка всё же необходима — обосновать в отчёте отдельным пунктом.
## P0-2. llama-swap
1. Поставить `mostlygeek/llama-swap` (Go, MIT) **рядом** с работающими службами, не ломая их.
2. В конфигурацию внести все модели, лежащие в `/srv/ai/models/`, каждую отдельной записью со своими параметрами запуска.
3. Таймаут выгрузки настраивается.
4. **Проверить замером `nvidia-smi`, что выгрузка действительно освобождает видеопамять** — по документации не принимать.
5. **Откат одной командой** описать и проверить: если llama-swap мешает, `qwen-coder` и `qwen-compressor` возвращаются в прежний вид.
6. Штатные порты 8081 и 8082 остаются за службами владельца. llama-swap слушает свой порт и в работу Hermes не вмешивается, пока владелец не переключит.
Обоснование, почему это стоит делать: суммарно четыре интересующие владельца модели занимают 25,5 ГиБ, а на сервере **45 ГБ уже занято страничным кэшем при 62 ГБ всего**. Модели помещаются в оперативную память целиком, поэтому переключение между ними — копирование по PCIe, а не чтение с диска на 187 МБ/с. Это снимает главное возражение против свопа.
## P0-3. Две правки отчёта
Таблицу не трогать, кроме следующего.
1. **Размер контекста внести в условия измерений.** Если замеры шли на 32768 — так и написать. Числа, снятые на 32К, не выдавать за характеристику установки владельца, работающей на 192К.
2. **Столбец VRAM пересчитать на потребление процесса**, а не карты: `nvidia-smi --query-compute-apps=pid,used_memory`. Если пересчёт требует повторных запусков — либо перезамерить, либо честно пометить столбец как неизмеренный и убрать числа. Оставлять заведомо неверные значения нельзя.
3. **Добавить строку про порог Hermes**: какие из моделей держат 64К контекста и с какой скоростью. Это тот вопрос, ради которого владелец сравнение и заказывал.
## P0-4. Ответ на вопрос владельца
Владелец спрашивает, можно ли держать несколько лёгких моделей сразу: Qwen2.5-Coder-14B, Qwen3-4B-Instruct-2507, DeepSeek-Coder-V2-Lite, Granite-4.2-8B.
Арифметика ревьюера по проверенным размерам файлов:
```
Qwen2.5-Coder-14B 8 571 МиБ
DeepSeek-V2-Lite 9 884 МиБ
Granite-4.2-8B 5 283 МиБ
Qwen3-4B-2507 2 382 МиБ
──────────
только веса 26 120 МиБ из 32 768
остаётся 6 648 МиБ на четыре контекста и буферы
```
Замеренная надбавка у живых процессов на 32К — от 1 154 МиБ до 3 058 МиБ на экземпляр.
Требуется **проверить это замером**, а не расчётом: поднять три модели без DeepSeek одновременно и снять `nvidia-smi` по процессам; затем попробовать четыре. Дать владельцу таблицу «сколько моделей и с каким контекстом помещается» с настоящими числами.
## P0-5. Аудит вторым проходом
1. **Перезагрузить сервер** (согласовав окно с владельцем) и убедиться, что кодер и компрессор поднялись сами. Это единственная настоящая проверка пункта P0-1.
2. **Убедиться, что контекст 196608**, а не 32768: запросить у сервера и сверить.
3. **Проверить, что llama-swap не мешает** штатным службам: обе работают, порты отвечают.
4. **Сверить пересчитанный столбец VRAM** с `--query-compute-apps` независимо.
5. **Убедиться, что в отчёте не осталось чисел без указания условий**, при которых они сняты.
6. **Побочные изменения** объяснить.
7. **Пропущенный пункт назвать пропущенным.**
---
## Ограничения
- Сервер рабочий. Окно для перезагрузки согласовать с владельцем.
- Учётные данные и `~/.hermes/agy_profiles/` не трогать.
- Конфигурацию хаба не менять.
- Юнит-файлы владельца без обоснования не переписывать.
- Место на диске контролировать: свободно 257 ГБ.
- Версию `0.1.1` не поднимать, тег не создавать.
- Правило честности без исключений.
## Критерии приёмки
1. Ветка в `origin`, `git status` чист.
2. `qwen-coder` работает через systemd с контекстом 196608, включён в автозапуск, пережил перезагрузку — вывод приложен.
3. `qwen-compressor` проверен тем же порядком.
4. llama-swap установлен, содержит все модели из `/srv/ai/models/`, выгрузка освобождает видеопамять — подтверждено `nvidia-smi`; откат описан и проверен.
5. Штатные службы llama-swap не сломал.
6. В условиях измерений отчёта указан размер контекста.
7. Столбец VRAM показывает потребление процесса либо честно помечен неизмеренным.
8. В отчёте есть ответ, какие модели держат 64К и с какой скоростью.
9. Замерено и приложено, сколько моделей помещается одновременно и с каким контекстом.
10. Огрызок `nemotron-3.5-30b` убран либо докачан; выбор объяснён.
11. `ruff check .` чисто; релизный гейт не ухудшен.
12. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`. После слияния с `origin/main` ожидается **491 passed**.
## Главное
Замеры в A40 сделаны честно, и это заметный шаг после A38. Но ради них у владельца остановили кодер, запустили его вручную с контекстом вшестеро меньше штатного и в таком виде оставили — а при 32К модель не проходит порог Hermes и в работе бесполезна. Сначала вернуть инструмент в строй, потом договорить в отчёте то, что осталось недосказанным: при каком контексте сняты числа и сколько памяти занимает каждая модель на самом деле.
## Порядок сдачи
Передать точный `FINAL_COMMIT_SHA`.

View file

@ -0,0 +1,150 @@
# Задание A45: три новых кандидата в локальные кодеры
## Дата поступления
2026-08-31
## База
`origin/main` (`ff303b5`).
```
git fetch origin --prune
git checkout -b antigravity/a45-moe-candidates origin/main
```
В `main` напрямую не пушить.
## Порядок исполнения
Два прохода: **Flash** исполняет замеры, **Pro** проводит аудит. Пункт **P0-5** написан для аудитора.
**Выполнять после A44.** Причина не в приоритетах, а в железе: видеокарта одна, и оба задания её занимают. A44 первым делом останавливает ручной процесс на 8081 и возвращает кодер под systemd — начинать замеры до этого значит мешать друг другу и получить искажённые тайминги.
**Файлы A44 не трогать.** `benchmarks/BENCHMARK_REPORT.md` и `benchmarks/benchmark_results.json` правит A44; здесь пишется отдельный отчёт (см. P0-4). Стенд `benchmarks/benchmark_suite.py` используется как есть, без правок.
---
## Задача
Владелец нашёл на huggingface.co новые модели и спрашивает, есть ли что-то интересное. Ревьюер отобрал три кандидата и проверил их пригодность к этому железу. Нужно измерить.
## Что проверено ревьюером — заново не выяснять
Размеры получены через API репозиториев HuggingFace, а не из карточек моделей.
| Порядок | Репозиторий | Файл | Размер |
|---|---|---|---|
| 1 | `unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF` | `Qwen3-Coder-30B-A3B-Instruct-Q4_K_M.gguf` | 17,28 ГиБ |
| 2 | `bartowski/Qwen2.5-Coder-32B-Instruct-GGUF` | `Qwen2.5-Coder-32B-Instruct-Q4_K_M.gguf` | 18,49 ГиБ |
| 3 | `peculiar-ragdoll/Tiel-Coder-35B-A3B-GGUF` | `Tiel-Coder-35B-A3B-UD-Q4_K_S.gguf` | 19,46 ГиБ |
Пересобирать llama.cpp не нужно:
```
сборка на сервере: build 10597, commit 95b8e33e1
libllama.so содержит: qwen3moe, qwen35moe, deepseek2, granite
```
Место: свободно 256 ГБ, три модели занимают 55 ГиБ.
## Почему именно эти три и в этом порядке
**Qwen3-Coder-30B-A3B — главная.** MoE: 30 миллиардов всего, **3 миллиарда активных**. На V100 производительность упирается в пропускную способность памяти, поэтому скорость определяется активными параметрами, а память — общими. Ожидается скорость малой модели при качестве тридцатимиллиардного кодера. Это ровно та гипотеза, ради которой A38 брала Nemotron и до замера не довела. 12,8 млн скачиваний, 933 отметки — сборка обкатанная.
По размеру садится на место нынешнего кодера: 17,28 ГиБ против 17,67 у Qwen3.8-27B, то есть под контекст остаётся столько же.
**Qwen2.5-Coder-32B — про потолок качества.** Плотная, старшая в семействе нынешнего лидера. Числилась кандидатом ещё в A40 и до замера не дошла. Скорости от неё не ждут: плотные 32B на этом железе должны идти примерно вдвое медленнее 14B. Вопрос к ней один — покупается ли за потерю скорости реальный прирост качества. 14B даёт 75% на стенде.
**Tiel-Coder-35B-A3B — третья, и только после двух первых.** Тоже MoE с тремя активными, первое место в трендах среди кодеров. Но выложена 31 августа, автор незнакомый, 145 отметок против 933 у Qwen. Не обкатана.
## Ожидания ревьюера — это не измерения
Всё, что выше сказано про ожидаемую скорость, выведено из замеренных свойств железа и **числами в отчёт не переносится**. В таблице стоят только измеренные значения.
---
## P0-1. Правило из A40 действует без изменений
**Строка в отчёте появляется только после того, как модель отработала на стенде.**
Для каждой строки обязательны:
1. **Абсолютный путь к файлу GGUF** на сервере.
2. **Размер файла в байтах** из `stat`, а не из карточки модели.
3. **Контрольная сумма** первых мегабайт или `sha256`.
4. **Сырые тайминги** из поля `timings` ответа `llama-server`, не пересчитанные вручную.
5. **Имя сборки** из `general.name` метаданных GGUF, а не из названия каталога.
Модель не скачалась, не запустилась или не влезла — **строки в таблице нет**, вместо неё раздел «не проверено» с причиной. Это полноценный результат, он принимается; выдуманные числа — нет.
## P0-2. Замер на 64К обязателен
Это главное отличие от A40 и главная причина, по которой задание вообще нужно.
1. **Мерить на 64К контекста**, а не только на 32К. Это порог отбора у Hermes: модель, не держащая 64К, в работу не идёт, и замер на 32К на вопрос владельца не отвечает.
2. Если модель на 64К не помещается или деградирует — **так и записать**, с числами.
3. **Длинный контекст у MoE под особым подозрением.** DeepSeek-Coder-V2-Lite, тоже MoE с малым числом активных, по замеру A40 на 32К проваливается до 3,35 ток/с и уходит в таймаут. Проверить целенаправленно, не повторяется ли это у Qwen3-Coder и Tiel: если повторяется, вся привлекательность MoE на этом железе иллюзорна, и это важнейший вывод задания.
4. Дополнительно снять 32К — для сопоставимости с таблицей A40.
## P0-3. Одинаковые условия
1. **Режим мышления выключен у всех**, как в A40.
2. Квантование Q4_K_M, где доступно; у Tiel его нет — взят `UD-Q4_K_S`, и это **оговорить в отчёте** отдельной строкой.
3. `--parallel 1`, посторонних запросов во время замера нет.
4. **Размер контекста указывать при каждом числе.** В A40 его забыли указать вовсе, и числа оказалось не с чем соотнести.
5. **VRAM мерить по процессу**: `nvidia-smi --query-compute-apps=pid,used_memory`, а не общую занятость карты. В A40 столбец собрал занятость вместе с соседней резидентной моделью и стал бесполезен.
## P0-4. Что измерять и куда писать
Как в A40: генерация и обработка промпта в токенах в секунду, видеопамять по процессу, время холодной загрузки, прохождение 12 задач стенда, поведение на длинном контексте.
Отчёт — **новый файл** `benchmarks/BENCHMARK_MOE_CANDIDATES.md` и отдельный файл результатов. `BENCHMARK_REPORT.md` и `benchmark_results.json` не трогать: их правит A44, и одновременная запись даст конфликт.
Вывод в одну строку на каждую модель: годится ли она заменой нынешнему кодеру и почему. **Ничего в конфигурации владельца не менять** — задание исследовательское, решение принимает он.
## P0-5. Аудит вторым проходом
В A38 выдумка прошла первый проход целиком. Здесь она — главный предмет проверки.
1. **Для каждой строки убедиться, что файл существует**: пройти `stat` по всем путям и сверить размеры с таблицей.
2. **Ни одной записи `COMPLETED` без файла** в результатах.
3. **Проверить выборочно тайминги**: повторить два-три замера и убедиться, что цифры воспроизводятся.
4. **Убедиться, что замер на 64К действительно сделан**, а не подменён замером на 32К.
5. **Проверить, что при каждом числе указан контекст**, и что VRAM снята по процессу.
6. **Убедиться, что файлы A44 не тронуты.**
7. **Побочные изменения** объяснить.
8. **Пропущенный пункт назвать пропущенным.**
---
## Ограничения
- **Выполнять после A44**: видеокарта одна.
- Служебные юниты `qwen-coder` и `qwen-compressor` после прогонов вернуть в рабочее состояние: владелец пользуется сервером ежедневно.
- Конфигурацию хаба не менять.
- Учётные данные и `~/.hermes/agy_profiles/` не трогать.
- Место на диске контролировать, раздел не забить.
- Версию `0.1.1` не поднимать, тег не создавать.
- Правило честности без исключений.
## Критерии приёмки
1. Ветка в `origin`, `git status` чист.
2. Три кандидата прогнаны либо честно объявлены недоступными с причиной.
3. Для каждой строки: путь, размер в байтах, контрольная сумма, `general.name`, сырые тайминги.
4. **Для каждой модели есть замер на 64К контекста**; где не влезло или деградировало — с числами.
5. Проверено, повторяется ли у MoE провал на длинном контексте, замеченный у DeepSeek.
6. При каждом числе указан размер контекста; VRAM снята по процессу.
7. Отклонение по квантованию у Tiel оговорено.
8. Отчёт в отдельном файле; `BENCHMARK_REPORT.md` и `benchmark_results.json` не изменены.
9. Служебные модели на портах 8081 и 8082 возвращены в рабочее состояние.
10. Конфигурация владельца не изменена.
11. `ruff check .` чисто; релизный гейт не ухудшен.
12. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`. На `origin/main` сейчас **491 passed**.
## Главное
Нынешний лидер по замерам — Qwen2.5-Coder-14B: 75% качества при 55,9 ток/с. Вопрос владельца в том, есть ли что-то заметно лучше. Qwen3-Coder-30B-A3B — самый обоснованный ответ, какой можно дать не запуская: три активных миллиарда на памяти-узком-месте должны дать скорость малой модели при качестве большой. Но ровно это же обещал DeepSeek, а на длинном контексте провалился до 3,35 ток/с. Поэтому замер на 64К здесь важнее самой таблицы скоростей.
## Порядок сдачи
Передать точный `FINAL_COMMIT_SHA`.

View file

@ -0,0 +1,141 @@
> **ОТМЕНЕНО 31.08.2026.** Работа передана Codex заданием
> `2026-08-31-A48-codex-interface-by-mockup.md`. Исполнитель сидит на сервере,
> где запущен хаб, и может сверять с макетом глазами. Antigravity за фронтенд
> не берётся: два агента в одних файлах уже приводили к переключению ветки под
> чужой работой.
# Задание A46: вёрстка по макетам — возврат по A43
## Дата поступления
2026-08-31
## База
`origin/main` (`81a58f6`) — там уже лежит A43.
```
git fetch origin --prune
git checkout -b antigravity/a46-mockup-redo origin/main
```
В `main` напрямую не пушить.
## Порядок исполнения
Два прохода: **Flash** реализует, **Pro** проводит аудит. Пункт **P0-4** написан для аудитора.
Исполнитель работает на машине владельца, где хаб запущен и есть живой снапшот. Макеты — в `Desktop/фронтенд/`, файлы `1.1.png``7.1.png` и пояснения `1.txt`, `3.txt`.
---
## Почему возврат
A43 закрыл холст и оставил вёрстку нетронутой. Владелец поставил сборку и написал: «интерфейс вообще не изменился, какой был, такой и остался. Зачем тогда было задание на изменение по макетам?»
Он прав. Вот что изменил A43:
```
app.js +297 шесть карточек показателей, обвязка холста
workflow.js +136 панорамирование, зум колесом
index.html +8
workflow.css 15 потолок 430 px снят, слои холста
style.css НЕ ОТКРЫВАЛСЯ НИ РАЗУ
```
`style.css` — это и есть внешний вид: сетка, отступы, типографика, карточки, палитра. Пункт P0-2 задания A43 требовал привести экраны к макетам именно по этим свойствам. Сделать это, не тронув файл со стилями, невозможно.
Скриншотов «до и после», которых требовал критерий приёмки 3, в ветке нет. Работа была принята по прохождению тестов, а тесты внешний вид не проверяют.
**Холст переделывать не нужно.** P0-1 выполнен: панорамирование, зум колесом, снятый потолок высоты — всё работает и остаётся.
---
## P0-1. Расхождения с макетом `1.1.png`
Сверено ревьюером: макет против живой сборки `81a58f6` на сервере владельца.
**Шапка.** В макете: поиск с подсказкой `Ctrl + K`, колокольчик со счётчиком, шестерёнка, карточка пользователя (инициалы, имя, команда). В сборке вместо этого две кнопки — «Обновить всё» и «Добавить аккаунт».
**Логотип и подпись.** В макете вензель, «HERMES HUB» и вторая строка «Крона • Бизнес-экосистема». В сборке — значок молнии и «Multi-Account Router».
**Левое меню.** В макете иной набор и оформление пунктов, внизу блок с эмблемой и текстом про единый визуальный язык. В сборке внизу — служебная строка про Live API и номер сборки.
**Панель инструментов холста.** В макете вертикальная панель слева внутри холста: курсор, добавить узел, связь, рамка, показать, удалить. В сборке отсутствует полностью.
**Карточки узлов.** В макете: иконка, имя, файл `.md`, строка «модель • аккаунт», статус точкой. В сборке: три строки текста, обрезанные многоточием, без модели и аккаунта.
**Подписи связей.** В макете подписи `SUCCESS`, `REVIEW_PASSED`, `REVIEW_FAILED` разнесены и подкрашены, возвраты идут красным пунктиром. В сборке подписи налезают на карточки узлов и режутся: владелец видит «ТАНОВКА ЗАД» и «РАЙПРИЁМКА».
Центрирование подписей ревьюер уже починил (`text-anchor` в `workflow.css`), и эта правка на месте. Режут их **сами карточки узлов, которые рисуются поверх**, и слишком узкий промежуток между узлами. Лечится порядком слоёв и расстоянием в раскладке, а не стилем текста.
**Нижний ряд.** В макете три карточки: «Последние события» с временем и цветными бейджами, «Статистика workflow» с кольцевой диаграммой, «Активные задачи». В сборке — «Последние события» и «Управление LIVE».
**Инспектор.** В макете это основная панель: вкладки «Основное», «Модель», «Инструкции», «Инструменты», «Память», «История»; поля статуса, текущей задачи, итерации, последнего запуска, времени выполнения, успешности; блок «Конфигурация исполнения» с провайдером, аккаунтом, моделью, температурой, лимитом токенов и таймаутом; блок «Agent File»; инструменты чипами; быстрые действия кнопками. В сборке — пустая заглушка «Выберите агента на графе».
**Палитра и рамки.** Тёмно-зелёный фон с золотыми акцентами и тонкими рамками. Это то, что задаётся в `style.css`.
## P0-2. Что делать с элементами, которых нечем наполнить
Часть макета опирается на данные, которых в снапшоте может не быть.
1. **Ничего не выдумывать.** Нет данных — `Н/Д` с причиной, как принято в проекте. Нарисовать кольцевую диаграмму с числом «42» из макета — дефект, а не выполнение задания.
2. **Модель и аккаунт на карточке узла в снапшоте есть** — брать оттуда, а не подписывать примерами из макета.
3. **Версию из макета не переносить.** Там `v2.9.0`, в проекте `0.1.1`, и она заморожена намеренно.
4. **Нижняя панель других приложений экосистемы** (Planner, Journal, Finance и прочие) — этих приложений не существует. Не делать и **назвать пропущенным** в отчёте, а не рисовать неработающие кнопки.
5. Всё остальное, что упирается в отсутствующие данные, — так же: реализовать оформление, показать пустое состояние честно, перечислить в отчёте.
## P0-3. Скриншоты — это и есть сдача работы
Владелец сравнивает глазами. Отчёт без картинок принят не будет.
1. **Список расхождений по каждому экрану** — до начала работы, приложить.
2. **Скриншот до и после по каждому экрану** — обязательно. Это критерий, по которому A43 провалился.
3. **Рядом с каждой парой — фрагмент макета**, к которому приводили.
4. Пройти все макеты `1.1``7.1`, а не только первый.
5. **Три темы** — светлая, средняя, тёмная — проверить на каждом экране.
## P0-4. Аудит вторым проходом
Проверяющему: в прошлый раз работа была принята без единого взгляда на экран.
1. **Открыть хаб и посмотреть.** Не отчёт, не тесты — экран.
2. **Проверить, что `style.css` действительно изменён** и изменения относятся к вёрстке, а не косметике в одну строку.
3. **Сверить скриншоты с макетами** попарно.
4. **Убедиться, что выдуманных данных нет**: ни одного числа из макета в живом интерфейсе.
5. **Холст не сломан**: панорамирование, зум колесом, «вписать» работают как после A43.
6. **Подписи связей читаются** на всех масштабах и не перекрываются карточками.
7. **Побочные изменения** объяснить.
8. **Пропущенный пункт назвать пропущенным.**
---
## Ограничения
- **Без сборки, без npm, без фреймворка** — решение зафиксировано в `docs/web-api/CONTRACT.md` §1.
- Python не трогать.
- Холст A43 не переделывать, только доводить.
- Учётные данные и `~/.hermes/agy_profiles/` не трогать.
- Версию `0.1.1` не поднимать.
- Правило честности без исключений.
## Критерии приёмки
1. Ветка в `origin`, `git status` чист.
2. `style.css` изменён; вёрстка экранов приведена к макетам.
3. По каждому экрану приложены скриншоты до и после рядом с фрагментом макета.
4. Пройдены все макеты `1.1``7.1`.
5. Инспектор агента реализован по макету; отсутствующие данные показаны как `Н/Д` с причиной.
6. Карточки узлов показывают модель и аккаунт из снапшота.
7. Подписи связей не перекрываются карточками узлов; проверено на нескольких масштабах.
8. Панель инструментов холста реализована либо названа пропущенной с причиной.
9. Ни одного числа из макета в живом интерфейсе.
10. Три темы работают на всех экранах.
11. `ruff check .` чисто; релизный гейт не ухудшен.
12. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`. На `origin/main` сейчас **496 passed**.
## Главное
Владелец полдня ждал сборку, поставил её на две машины и увидел прежний интерфейс. Холст стал лучше, но он один экран из семи. Задание закрывает то, что в A43 просто не начинали: вёрстку по макетам. И сдаётся оно скриншотами, потому что проверить его иначе нельзя — тесты этого не видят, что и показал прошлый заход.
## Порядок сдачи
Передать точный `FINAL_COMMIT_SHA`.

View file

@ -0,0 +1,170 @@
# Задание A47: единая память для всех агентов сервера
## Дата поступления
2026-08-31
## База
`origin/main` (`80aab00`).
```
git fetch origin --prune
git checkout -b antigravity/a47-shared-memory origin/main
```
В `main` напрямую не пушить.
## Порядок исполнения
Два прохода: **Flash** реализует, **Pro** проводит аудит. Пункт **P0-7** написан для аудитора.
Задание идёт **на сервере** `192.168.1.81`. Правки кода — через git, правки памяти — прямо в хранилище (оно вне git, см. P0-2).
Не пересекается с A42 (провайдеры), A46 (вёрстка), A45 (замеры).
---
## Задача
Владелец: «чтобы он работал совместно с обсидиан, чтобы все ИИ на сервере использовали единый мозг».
Хранилище уже есть и сделано хорошо. Задание — не строить его заново, а заставить работать: сейчас им никто не пользуется.
## Что проверено ревьюером
**Хранилище.** `/srv/projects/AI-Memory`, Obsidian 1.13.7 из snap, 218 заметок, 2,7 МБ. Структура `00_SYSTEM`, `01_PROJECTS`, `02_KNOWLEDGE`, `03_LESSONS`, `04_PATTERNS`, `05_AGENTS`, `99_ARCHIVE`. Заметки размечены полями (`type`, `severity`, `confidence`, `created_by`, `reviewed_by`). Есть протокол, политика памяти, роли и три шаблона.
Приложение Obsidian нужно человеку. **Агенту достаточно пути**: хранилище — это папка с файлами Markdown, никаких плагинов и серверов поднимать не надо.
**Память проекта устарела на четыре дня и тринадцать заданий.**
```
01_PROJECTS/hermes-hub/CURRENT_STATE.md обновлён 27 августа
в нём: main = c35bc48, идёт работа над A33
на деле: main = 80aab00, идёт A46
worklog/ ПУСТО, 0 записей
```
Протокол требует после каждой задачи обновить `CURRENT_STATE.md`, `HANDOFF.md`, `TASKS.md` и написать worklog. Не делалось ни разу.
**Мосты.** В репозиториях `agent-control-center`, `business-platform`, `finance-*`, `hermes-android` и других `AGENTS.md` есть и на AI-Memory ссылается. Исключением был `hermes-hub`; корневой мост добавлен ревьюером в `80aab00`, но **на сервере лежит старая копия** — нужен `git pull`. Без моста также `hermes-hub-a34`.
**Хранилище не под контролем версий.** `.git` нет, истории нет, отката нет. При этом папка доступна на запись нескольким агентам сразу.
---
## P0-1. Привести память проекта в соответствие с действительностью
Не переписывать заново — обновить.
1. `CURRENT_STATE.md`: текущий `main`, ветки в работе, что сделано за A40A46, что открыто.
2. `HANDOFF.md`: с чего продолжать.
3. `TASKS.md`: состояние заданий A40A47.
4. `DECISIONS.md`: решения, принятые за эти дни, — отказ от `screenshot-to-code` и почему; клиент без сборки; версия `0.1.1` заморожена намеренно; порог 64К у Hermes.
5. **Даты и коммиты обязательны** у каждой записи. Память без даты нельзя отличить от свежей, и агент поверит устаревшей.
Уроки за эти дни оформить по `LESSON_TEMPLATE.md`, минимум эти:
```
мнимый успех: действие вернуло ok:True и не сохранило ничего
клиент читал несуществующий ключ снапшота (profiles вместо all_profiles)
заглушка sleep 3600 вместо llama-server оставлена на рабочей машине
работа принята по зелёным тестам без единого взгляда на экран
зашитые идентификаторы профилей: убраны в A41, возвращены в A42
```
## P0-2. Хранилище под контроль версий
Сейчас это папка без истории, куда пишут несколько агентов. Одна ошибочная перезапись — и восстановить нечем.
1. Завести git **локально**, без публичного удалённого репозитория: в памяти обсуждается внутреннее устройство систем владельца.
2. `.gitignore` для служебного каталога `.obsidian/workspace*` и прочего, что меняется от открытия окна.
3. Ежедневный коммит-снимок либо коммит после изменений — на выбор, но обосновать.
4. **Проверить восстановление**: испортить копию файла, вернуть из истории.
5. Учётные данные, токены и пути к ним в память не писать — проверить, что их там нет уже сейчас.
## P0-3. Единый мозг: все агенты читают одно
Смысл в том, чтобы урок, полученный одним агентом, работал у остальных.
1. **Составить перечень**, какие ИИ действительно работают на сервере и каким файлом каждый настраивается. У разных инструментов это разные имена (`AGENTS.md`, `CLAUDE.md` и другие) — выяснить, а не предположить.
2. **Каждому дать мост** на `/srv/projects/AI-Memory` по образцу `00_SYSTEM/AGENTS_BRIDGE_PLAN.md`: короткий указатель, без копий уроков.
3. **Обновить копию `hermes-hub` на сервере** (`git pull`), чтобы корневой мост из `80aab00` там появился.
4. **`hermes-hub-a34`** — выяснить, живой ли это рабочий каталог. Если остаток — убрать; если рабочий — дать мост.
5. **Правило единственности.** Уроки и решения живут только в AI-Memory. Копия в репозитории — дефект: копии расходятся, и агент читает неверную.
## P0-4. Обновление памяти — часть завершения задачи
Иначе всё вернётся к нынешнему состоянию.
1. Внести в шаблон задания два обязательных пункта: **прочитать память до работы**, **обновить после**.
2. В отчёт добавить строку: какие файлы памяти обновлены и каким уроком пополнилась база.
3. **Проверка свежести**: способ увидеть, что `CURRENT_STATE.md` отстал от `main`. Достаточно скрипта, сравнивающего записанный коммит с текущим, и предупреждения при расхождении.
4. **Всё хранилище в контекст не загружать** — 218 заметок. Читать `00_SYSTEM`, файлы своего проекта и найденное поиском по теме.
## P0-5. Несколько агентов пишут одновременно
Общая папка на запись без разграничения уже дала в этом проекте два случая: агент переключил ветку под чужой работой, и на рабочей машине осталась подменённая заглушка.
1. **Одновременная запись в один файл не должна терять правки.** Предложить механизм и обосновать: раздельные файлы worklog на агента, дозапись вместо перезаписи, блокировка.
2. **Каждая запись подписана**: кто, когда, по какому заданию. Поле `created_by` в шаблоне уже есть — использовать.
3. **Чужие записи не переписывать.** Не согласен — добавить свою и сослаться на исходную.
## P0-6. Граница: память — это данные, а не канал команд
Отдельным пунктом, потому что цена ошибки высока и проект этим уже занимался в A37.
Общая папка, из которой все агенты читают инструкции и в которую все пишут, — это ровно тот канал связи между агентами, о котором предупреждал разбор чужого инцидента, приложенный к A37: разрешённый внутренний сервис становится доской объявлений и точкой опоры.
1. **Память описывает состояние и уроки. Она не отдаёт распоряжений.** Задания приходят от владельца через `agents/inbox/`, а не из заметок.
2. **Заметка, требующая действия, исполнением не является.** Найденный в памяти «TODO» выносится владельцу, а не выполняется молча.
3. **Изменения, расширяющие права или меняющие правила работы агентов**, вносит владелец. Агент может предложить.
4. Подписи и даты из P0-5 нужны и для этого: должно быть видно, кто внёс запись.
## P0-7. Аудит вторым проходом
1. **Сверить `CURRENT_STATE.md` с действительностью**: коммит в памяти против `git log` на сервере.
2. **Проверить восстановление из истории** самостоятельно, а не по описанию.
3. **Проверить, что мост есть у каждого перечисленного агента** и указывает на существующий путь.
4. **Искать копии уроков** в репозиториях — их быть не должно.
5. **Искать учётные данные** в памяти целенаправленно.
6. **Проверить, что заметки не отдают распоряжений** агентам.
7. **Побочные изменения** объяснить.
8. **Пропущенный пункт назвать пропущенным.**
---
## Ограничения
- Хранилище **не публиковать**: ни на GitHub, ни куда-либо ещё.
- Существующие заметки владельца не удалять и не переписывать; устаревшее переносить в `99_ARCHIVE`.
- Структуру папок и разметку полей не менять — она рабочая.
- Учётные данные и `~/.hermes/agy_profiles/` не трогать.
- Службы `qwen-coder` и `qwen-compressor` не трогать — они только что восстановлены.
- Версию `0.1.1` не поднимать.
- Правило честности без исключений.
## Критерии приёмки
1. Ветка в `origin`, `git status` чист.
2. `CURRENT_STATE.md`, `HANDOFF.md`, `TASKS.md`, `DECISIONS.md` проекта соответствуют действительности; у записей есть даты и коммиты.
3. Уроки из P0-1 оформлены по шаблону.
4. Хранилище под git локально; восстановление файла из истории проверено, вывод приложен.
5. Перечень ИИ сервера составлен; у каждого мост на AI-Memory; пути существуют.
6. Копия `hermes-hub` на сервере обновлена, корневой мост на месте; судьба `hermes-hub-a34` решена.
7. Копий уроков в репозиториях нет.
8. Шаблон задания содержит пункты про чтение и обновление памяти.
9. Проверка свежести работает: расхождение памяти с `main` обнаруживается.
10. Механизм одновременной записи предложен, обоснован и проверен.
11. Учётных данных в памяти нет; проверено поиском.
12. `ruff check .` чисто; релизный гейт не ухудшен.
13. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`. На `origin/main` сейчас **496 passed**.
## Главное
Память построена, размечена и продумана — а последняя запись в ней сделана 27 августа, и каталог worklog пуст. Тринадцать заданий прошли мимо. Агент, который добросовестно её прочитает, начнёт работать по состоянию четырёхдневной давности: решит, что идёт A33 и `main` — это `c35bc48`. Устаревшая память вреднее отсутствующей, потому что ей верят.
Задание про то, чтобы память стала живой: обновлялась как часть работы, была одинаково видна всем агентам и пережила ошибочную перезапись.
## Порядок сдачи
Передать точный `FINAL_COMMIT_SHA`.

View file

@ -0,0 +1,174 @@
# Задание A49: расстановка субагентов, вкладка «Скиллы», память через Obsidian
## Дата поступления
2026-08-31
## База
`origin/main` (`17b368a`) — туда слиты A42, A45, A47 и A48.
```
git fetch origin --prune
git checkout -b antigravity/a49-subagents-skills-memory origin/main
```
В `main` напрямую не пушить.
## Порядок исполнения
Два прохода: **Flash** реализует, **Pro** проводит аудит. Пункт **P0-6** написан для аудитора.
Задание крупное и делится на три независимые части. **Части можно сдавать по отдельности**, но каждую — целиком.
Не пересекается с A44 (сервер) и A45 (замеры). Вёрстка A48 уже в `main`: новые экраны делать в её стиле, существующие не ломать.
---
## Что проверено ревьюером
**Ролей объявлено тринадцать**, соединено пять.
```
manager developer-1 developer-2 code-reviewer researcher tester
tech-writer analyst guardian cost-controller integration-expert
security-expert dependency-agent
```
Конвейер по умолчанию связывает только `manager → developer-1 → developer-2 → code-reviewer` с возвратами по `REVIEW_FAILED`. Остальные восемь ролей объявлены, но в графе висят без связей: на экране владельца `Research` и `Fast` стоят в стороне и ни к чему не присоединены.
**Скиллов в интерфейсе нет вовсе.** Ни вкладки, ни поля в инспекторе агента, ни признака, пользовался ли агент скиллом.
**Общая память уже работает** после A47: `/srv/projects/AI-Memory` под git, структура `00_SYSTEM`, `01_PROJECTS`, `03_LESSONS`, `04_PATTERNS`, `05_AGENTS`, протокол и шаблоны на месте, `worklog` заполняется. Корневой `AGENTS.md` в репозитории указывает на неё.
**Obsidian** стоит на сервере (snap 1.13.7), но **агенту он не нужен**. Из руководства владельца по подключению Obsidian к агенту, дословно: «Агенту нужен не GUI Obsidian, а локальная папка vault». Хранилище — это папка с файлами Markdown.
---
# Часть 1. Расстановка субагентов и связи
## P0-1. Разобрать всех тринадцать и соединить
1. **Разбор каждой роли**: что делает, от кого получает работу, кому передаёт, по какому условию. Приложить таблицей.
2. **Связать те, что должны работать вместе.** Восемь ролей сейчас ни с чем не соединены — для каждой либо связь, либо явная запись «работает по вызову, в конвейер не входит» с обоснованием.
3. **Условия переходов** брать из существующего набора: `SUCCESS`, `REVIEW_PASSED`, `REVIEW_FAILED`, `NEXT`, `ERROR`, `ALWAYS`. Новые вводить только при необходимости и объяснять.
4. **Циклы доработки конечны.** Возврат `REVIEW_FAILED` без ограничения числа итераций — это бесконечный круг на живых квотах. Предел итераций уже есть в конвейере — проверить, что он соблюдается на каждом возврате.
5. **Расстановка на холсте осмысленная**: поток слева направо, возвраты видимой дугой, узлы не наезжают друг на друга. После A48 подписи связей читаются — не сломать.
**Ничего не выдумывать про роли.** Назначение брать из `role_registry.py`; если для роли нет внятного места в потоке, так и написать, а не придумывать ей работу.
---
# Часть 2. Вкладка «Скиллы»
## P0-2. Скиллы видны, ищутся и назначаются
1. **Новая вкладка «Скиллы»** в главном меню, в стиле экранов A48.
2. **Список установленных скиллов** — читать из каталога скиллов агента (`~/.claude/skills/` и равнозначные для других инструментов; путь настраивается). Показывать `name`, `description` и путь.
3. **Поиск** по имени и описанию.
4. **Назначение скилла субагенту** — из вкладки и из карточки агента. Назначения сохраняются и переживают перезапуск.
5. **Во вкладке «Инструменты» инспектора** показывать назначенные скиллы. Сейчас там `Н/Д: инструменты не назначены` — это состояние должно наполниться.
6. **Скилл не найден или каталог отсутствует** — сказать об этом с причиной и путём, где искали. Не показывать пустой список как «скиллов нет».
## P0-3. Видно, пользовался ли агент скиллом
Владелец: «добавить режим просмотра, использовал он в проекте скиллы или сам придумывал».
1. **Записывать факт применения**: какой скилл, каким агентом, в какой задаче, когда.
2. **Показывать в истории агента** и отдельным срезом по проекту: применённые скиллы против назначенных, но ни разу не сработавших.
3. **Назначен и ни разу не применён — это сигнал**, а не ошибка. Показывать как факт: скилл может не подходить под задачи, а может быть сломан — второе лечится частью P0-4.
4. **Правило честности здесь особенно важно.** Если признак применения снять неоткуда — писать `Н/Д` с причиной, а не рисовать правдоподобную статистику. Сначала выяснить, что вообще можно узнать достоверно, и в отчёте назвать источник.
## P0-4. Субагент «скилл-доктор»
Готовый скилл лежит у владельца: `Desktop/skills-hermes/skill-doctor/``SKILL.md` и `references/description-cookbook.md`. **Написан, выверен и переделке не подлежит**; задание — встроить его как роль.
Главное из него, что определяет устройство роли:
- **У скилла две независимые части.** `frontmatter` (`name`, `description`) решает, **запустится** ли скилл; тело решает, **что будет после запуска**. Чинить тело, когда сломано описание, — самая частая потеря времени.
- **Порядок диагностики:** формальное (имя файла ровно `SKILL.md`, расположение, границы `---`, `name` латиницей, `description` одной строкой) → разбор описания на три части → тело → проверочные запросы → диагноз.
- **Многострочный `description` — ошибка номер один по частоте**: YAML обрезает его, и решение о запуске принимается по огрызку.
- **Описание состоит из трёх частей**: что делает, когда запускать (реальными словами пользователя, 45 формулировок), когда **НЕ** запускать. Третья отсутствует почти всегда, и без неё скилл тихо срабатывает на соседних темах и жжёт лимиты — это хуже молчания, потому что не замечается.
- **Пять проверочных запросов**: три должны запустить скилл, два — не запустить. Негативные обязательны.
- **Диагноз выдаётся строгим форматом** с готовым `description` целиком, а не советом «сделай понятнее».
Требования к встраиванию:
1. **Новая каноническая роль** `skill-doctor` в реестре, с назначением и способностями, как у остальных.
2. **Запуск из вкладки «Скиллы»**: кнопка «Проверить скилл» рядом с каждым, и общая проверка всех.
3. **Результат показывать в интерфейсе** тем же форматом диагноза, с готовым описанием, которое можно скопировать.
4. **Скилл-доктор не правит файлы молча.** Он ставит диагноз и предлагает правку; применяет её владелец.
---
# Часть 3. Память через Obsidian
## P0-5. Хранилище подключается и наполняется
Владелец: «если на ПК или сервере установлен Обсидиан, то должен подгружаться в память… в настройках добавляешь папку рабочую Обсидиан, и оркестратору даёшь задание, чтобы он настроил работу».
1. **Обнаружение.** Хаб проверяет, есть ли Obsidian и хранилище. Признак хранилища — **папка с каталогом `.obsidian` внутри**, а не установленное приложение: агенту нужна папка, не программа. Найдено — предложить; не найдено — сказать прямо, без догадок.
2. **Настройка пути** в «Настройках»: путь к хранилищу задаётся вручную и сохраняется. На сервере владельца это `/srv/projects/AI-Memory`.
3. **Проверка при сохранении**: путь существует, доступен на запись, внутри есть `.obsidian`. Иначе — отказ с причиной.
4. **Хранилища нет — хаб работает как прежде.** Память не должна стать обязательной.
## P0-6. Оркестратор раскладывает память по структуре
1. **Действие «Настроить память»**, запускающее оркестратора по заложенной структуре. Структура **уже существует** — та, что в `/srv/projects/AI-Memory`: `00_SYSTEM`, `01_PROJECTS/<проект>/`, `03_LESSONS`, `04_PATTERNS`, `05_AGENTS`. Использовать её, а не изобретать вторую.
2. **У каждого субагента во вкладке «Память»** — своя структура по проектам: что он читает перед работой, что записывает после, его записи в `worklog` и его уроки.
3. **Существующие заметки владельца не трогать.** 218 заметок и восемь записей `worklog` уже есть; устаревшее переносить в `99_ARCHIVE`, не удалять.
4. **Разделение чтения и записи.** Субагент читает общее, пишет своё. Каждая запись подписана: кто, когда, по какому заданию.
5. **Граница остаётся.** Память описывает состояние и уроки; **распоряжений она не отдаёт**. Задание приходит от владельца, а не из заметки. Это требование A47, и оно не отменяется тем, что памятью теперь управляет оркестратор.
---
## P0-7. Аудит вторым проходом
1. **Открыть хаб и посмотреть** новую вкладку и связи на холсте. Не отчёт — экран. Скриншоты приложить, как в A48.
2. **Проверить, что список скиллов настоящий**: подложить скилл в каталог и убедиться, что он появился; убрать — исчез.
3. **Скилл-доктор проверить на заведомо сломанном скилле**с многострочным `description` — и убедиться, что диагноз указывает именно на это.
4. **Признак применения скилла**: убедиться, что он снимается измерением, а не выводится из назначения.
5. **Проверить, что без Obsidian хаб работает** как прежде.
6. **Проверить, что заметки владельца не пострадали**: число заметок до и после.
7. **Циклы доработки конечны** — убедиться, что предел итераций соблюдается.
8. **Побочные изменения** объяснить.
9. **Пропущенный пункт назвать пропущенным.**
---
## Ограничения
- Клиент **без сборки, без npm, без фреймворка**.
- Вёрстку A48 не ломать; новые экраны — в её стиле.
- Учётные данные, `~/.hermes/agy_profiles/`, службы `qwen-coder` и `qwen-compressor` не трогать.
- Заметки владельца не удалять.
- Скилл-доктор из `Desktop/skills-hermes/skill-doctor/` не переписывать.
- Версию `0.1.1` не поднимать.
- Правило честности без исключений: не измерено — `Н/Д` с причиной.
## Критерии приёмки
1. Ветка в `origin`, `git status` чист.
2. Разбор тринадцати ролей приложен таблицей; каждая либо соединена, либо объявлена внеконвейерной с обоснованием.
3. Циклы доработки конечны; проверено.
4. Вкладка «Скиллы» есть: список читается из каталога, поиск работает, назначение сохраняется и переживает перезапуск.
5. Назначенные скиллы видны в инспекторе агента.
6. Видно, применялся ли скилл; источник признака назван; неизмеримое помечено `Н/Д`.
7. Роль `skill-doctor` в реестре; запуск из интерфейса; диагноз выводится строгим форматом с готовым описанием; файлы молча не правятся.
8. Скилл-доктор проверен на заведомо сломанном скилле.
9. Хранилище Obsidian обнаруживается по наличию `.obsidian`, путь настраивается и проверяется.
10. Без хранилища хаб работает как прежде.
11. Оркестратор раскладывает память по существующей структуре; у каждого субагента во вкладке «Память» видна структура по проектам.
12. Заметки владельца целы; число до и после совпадает.
13. Скриншоты новых экранов приложены.
14. `ruff check .` чисто; релизный гейт 10/10; тестов не меньше **517**.
15. Память проекта в AI-Memory обновлена.
16. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`.
## Главное
Тринадцать субагентов объявлено, работают пятеро, восемь висят на холсте без связей. Скиллы владелец ставит руками и не видит ни списка, ни того, пользовался ими агент или писал по наитию. Память после A47 ожила, но субагенты в неё не смотрят.
Задание сводит три вещи в одно: агенты расставлены и связаны осмысленно, у каждого свои скиллы с проверкой их исправности, и все читают одну память по структуре, которую раскладывает оркестратор.
## Порядок сдачи
Передать точный `FINAL_COMMIT_SHA`.

View file

@ -0,0 +1,166 @@
# Задание A51: подключённый аккаунт должен реально использоваться Hermes
## Дата поступления
2026-08-31
## База
`origin/main` (`17b368a`).
```
git fetch origin --prune
git checkout -b antigravity/a51-hub-controls-hermes origin/main
```
В `main` напрямую не пушить.
## Порядок исполнения
Два прохода: **Flash** реализует, **Pro** проводит аудит. Пункт **P0-6** написан для аудитора.
Зона: маршрутизация, назначение ролей, плагин Hermes, карточка аккаунта. С A49 (скиллы и память) и A50 (обнаружение и проверка) не пересекается по смыслу, но **трогает те же файлы, что A50**`auto_assigner.py` и экран «Аккаунты». Выполнять **после A50**.
---
## Задача
Владелец: «в хабе я поставил аккаунт аги. Когда я захожу в Гермеса, какой аккаунт будет выбран? И если я поменяю в Гермесе аккаунт, поменяется он в хабе? Иначе толку от хаба, если в самом Гермесе это не работает».
Ответ, проверенный ревьюером: **сейчас не будет выбран ни один из его аккаунтов**.
---
## Что проверено исполнением
**Определение роли работает.** A35 встал: плагин перехватывает каждый `llm_execution` и определяет роль четырьмя уровнями — явная, по модели и провайдеру, по устойчивости сессии, по умолчанию. Это переделке не подлежит.
**Но цепочки указывают в пустоту.** Конфигурация владельца на рабочей машине:
```
default_role: не задан → используется manager
manager → ag-orch-fallback, codex-orch, opengo-3
developer-1 → ag-w1, codex-worker-1, opengo-3
researcher → opengo-1, ag-w3, ag-w4
профилей в конфигурации: 24
ролей: 13
```
Проверка вхождения **подключённых** аккаунтов владельца в цепочки:
```
ollama-1 НИ В ОДНОЙ
grok-1 НИ В ОДНОЙ
local-2 НИ В ОДНОЙ
local-3 НИ В ОДНОЙ
antigravity-1 НИ В ОДНОЙ
```
Все тринадцать ролей по-прежнему ссылаются на заготовки из старой конфигурации на 24 слота, а они не настроены. Значит при обращении Hermes цепочка `manager` перебирает три неавторизованных слота, отказывает, и плагин — правильно, по своему устройству — **пропускает вызов мимо хаба дальше в Hermes**:
```python
if isinstance(completion, dict) and completion.get("router_error"):
logger.warning("Router failover exhausted for role %r; passing the call downstream to Hermes")
```
Хаб при этом ведёт себя корректно: он не подменяет ответ. Но результат для владельца тот самый, которого он опасается — **хаб не участвует в работе вовсе**.
**Карточка аккаунта показывает роль, которой нет.** На экране `ollama-1` подписан «manager (primary)», хотя в цепочке `manager` его нет. Источник подписи — `auto_assigner.get_display_name_and_role`, а она читает **статическую таблицу** `DEFAULT_SLOT_ROLES`, а при промахе достраивает подпись из имени провайдера. В снапшот это попадает так:
```python
assigned_roles=role_assignments.get(pid, [log_role])
```
Есть аккаунт в живой цепочке — берётся живое значение; нет — подставляется **догадка**. Владелец видит «manager (primary)» и считает, что аккаунт назначен.
Тот же аккаунт на карточке списка подписан «worker», а в окне — «manager (primary)». Два разных источника в двух местах.
**Обратной синхронизации нет.** `_select_model` в `hermes_plugin.py` — ручная команда CLI, которая записывает в конфигурацию Hermes провайдера, модель и адрес. Ничего, что читало бы выбор владельца, сделанный **внутри** Hermes, и переносило бы его в хаб, в коде нет.
---
## P0-1. Подключённый аккаунт попадает в цепочку
1. **Подключение аккаунта ставит его в цепочку выбранной роли.** Роль владелец выбирает на третьем шаге мастера — сейчас этот выбор до цепочки не доходит.
2. **Если аккаунт никуда не назначен — так и писать.** «Не назначен» — нормальное состояние, но оно должно быть видно, а не подменяться догадкой.
3. **Кнопка «Авто»**: разложить подключённые аккаунты по ролям по способностям провайдера. Предложить расстановку и **показать до применения**, а не применять молча.
## P0-2. Карточка показывает то, что есть на самом деле
1. **Роль на карточке берётся только из живой цепочки.** Подстановка из `DEFAULT_SLOT_ROLES` в качестве роли — убрать: статическая таблица годится для человекочитаемого имени, но не для утверждения о назначении.
2. **Один источник для карточки и окна.** Сейчас список пишет «worker», окно — «manager (primary)».
3. **Показывать место в цепочке**: основной или запасной номер такой-то. «primary» без указания, в какой роли и на каком месте, ничего не значит.
## P0-3. Владелец видит, кто ответит на вызов
Главное, ради чего задание.
1. **На экране маршрутизации у каждой роли — «сейчас ответит: <аккаунт>»**, вычисленное по текущей цепочке и состоянию аккаунтов.
2. **Если не ответит никто** — сказать прямо: «цепочка пуста или все аккаунты недоступны, вызов уйдёт мимо хаба в Hermes». Это состояние сейчас и есть, и владелец о нём не знает.
3. **Роль по умолчанию видна и настраивается.** Сейчас `default_role` не задан, и молча используется `manager`. Показать это в настройках.
## P0-4. Видно, прошёл вызов через хаб или мимо
1. **Записывать по каждому вызову**: определилась ли роль, каким уровнем, какой профиль выбран, ушёл ли вызов мимо хаба и почему.
2. **Показывать в журнале событий** и счётчиком на «Обзоре»: сколько вызовов прошло через хаб, сколько мимо.
3. Это единственный способ ответить на вопрос владельца «работает ли хаб» измерением, а не рассуждением.
## P0-5. Обратная связь с Hermes
Владелец: «если я поменяю в Гермесе аккаунт, поменяется он в хабе
Сейчас — нет. Прежде чем делать, **выяснить и записать в отчёт**, что именно Hermes позволяет наблюдать: что хранится в его конфигурации, меняется ли она при выборе модели в интерфейсе, есть ли событие или файл, по которому это видно.
Дальше по результату:
1. **Если выбор Hermes читается** — показывать его в хабе и отмечать расхождение с цепочкой: «в Hermes выбран X, хаб направил бы на Y».
2. **Если не читается** — так и написать, а в интерфейсе объяснить владельцу, что хаб управляет маршрутом только когда Hermes не задаёт провайдера явно. Честное объяснение принимается.
3. **Ничего не записывать в конфигурацию Hermes автоматически.** `_select_model` остаётся ручной командой: молчаливая правка чужой конфигурации — это то, за что уже возвращались работы.
4. **Не выдумывать механизм**, которого в Hermes нет. Отсутствие способа — результат, он принимается.
## P0-6. Аудит вторым проходом
1. **Пройти путь целиком на живой машине**: подключить аккаунт, назначить роль, сделать запрос через Hermes и убедиться по журналу, что вызов пошёл через хаб и через **этот** аккаунт. Это единственная настоящая проверка задания.
2. **Проверить обратное**: убрать аккаунт из цепочки и убедиться, что вызов уходит мимо хаба и это видно в интерфейсе.
3. **Проверить, что роль на карточке исчезает**, когда аккаунт не назначен, — а не подменяется догадкой.
4. **Сверить карточку и окно**: подпись роли одинакова.
5. **Проверить конфигурацию владельца на копии**: старые цепочки на 24 заготовки не должны молча пропасть; предложить перенос, но не выполнять его без подтверждения.
6. **Побочные изменения** объяснить.
7. **Пропущенный пункт назвать пропущенным.**
---
## Ограничения
- Конфигурацию владельца молча не переписывать: перенос цепочек — только с подтверждением.
- В конфигурацию Hermes автоматически не писать.
- Учётные данные и `~/.hermes/agy_profiles/` не трогать.
- Определение роли из A35 не переделывать.
- Вёрстку A48 не ломать.
- Версию `0.1.1` не поднимать.
- Правило честности без исключений.
## Критерии приёмки
1. Ветка в `origin`, `git status` чист.
2. Подключение аккаунта с выбором роли кладёт его в цепочку этой роли; проверено.
3. Неназначенный аккаунт показан как неназначенный; догадка из статической таблицы как роль не используется.
4. Карточка и окно аккаунта показывают одну и ту же роль и место в цепочке.
5. На маршрутизации видно, какой аккаунт ответит для каждой роли; пустая цепочка названа прямо.
6. Роль по умолчанию видна и настраивается.
7. По журналу видно, прошёл вызов через хаб или мимо и почему; есть счётчик.
8. Пройден живой путь: подключение, назначение, запрос через Hermes, подтверждение по журналу.
9. Выяснено и записано, что Hermes позволяет наблюдать о своём выборе; сделано либо честно объявлено невозможным.
10. Конфигурация владельца не изменена без подтверждения.
11. `ruff check .` чисто; релизный гейт 10/10; тестов не меньше **517**.
12. Память проекта в AI-Memory обновлена.
13. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`.
## Главное
Владелец подключил аккаунты, увидел на карточках «manager (primary)» и решил, что настроил маршрутизацию. На деле ни один его аккаунт не входит ни в одну цепочку: все тринадцать ролей ссылаются на заготовки старой конфигурации. При обращении Hermes цепочка отказывает, и вызов уходит мимо хаба.
Хаб ведёт себя корректно и не подменяет ответ. Но владелец об этом не знает и считает, что управляет маршрутизацией, а управляет пустотой. Задание должно сделать так, чтобы назначение действительно назначало, а расхождение было видно на экране, а не выяснялось разбором конфигурации.
## Порядок сдачи
Передать точный `FINAL_COMMIT_SHA`.

View file

@ -0,0 +1,295 @@
# Задание A52: локальные модели — замена, надзиратель, пара кодеров с облачным судьёй
## Дата поступления
2026-08-31 (переработано в тот же день: добавлены части 1 и 3)
## База
`origin/main` (`17b368a`).
```
git fetch origin --prune
git checkout -b antigravity/a52-local-models origin/main
```
В `main` напрямую не пушить.
## Порядок исполнения
Два прохода: **Flash** исполняет, **Pro** проводит аудит. Пункт **P0-10** написан для аудитора.
Задание из трёх частей, и они идут **строго по порядку**:
```
Часть 1 замена моделей и замеры сдаётся отдельно, дальше по её числам
Часть 2 надзиратель локальных моделей
Часть 3 пара кодеров и облачный судья
```
Часть 3 планировать **по измеренным числам части 1**, а не заранее: без замера видеопамяти схема не проверяема.
Связано с A49 (расстановка субагентов и память) и A51 (аккаунт реально используется). Выполнять после них: надзирателю нужны и место в графе, и работающее назначение.
---
## Что проверено ревьюером — заново не выяснять
### Видеопамять занята почти полностью
```
Qwen3.8-27B кодер @196K 25 488 МиБ
qwen3-4b компрессор @32K 5 368 МиБ
──────────
30 856 из 32 768 свободно 1 912
```
### Измерено у кандидатов (A45, файлы и контрольные суммы сверены по диску)
```
Qwen3-Coder-30B-A3B @64K 21 368 МиБ 109,6 ток/с 83,3% MoE 30B/3B
Qwen3-Coder-30B-A3B @32K 19 640 МиБ 110,2 ток/с
Qwen2.5-Coder-32B @64K 27 938 МиБ 29,3 ток/с 83,3% плотная
```
Расход контекста у Qwen3-Coder — около 54 КиБ на токен.
### Качество на стенде из 12 задач (A40, признано)
```
Phi-4-14B 83,3% файл 8,28 ГиБ
Qwen2.5-Coder-14B 75,0% файл 8,37 ГиБ
Qwen3-4B-2507 83,3% файл 2,33 ГиБ
Granite-4.2-8B 66,7% файл 5,16 ГиБ
```
**Расход видеопамяти у 14B при 64К не измерен ни разу.** В A45 их не было, столбец VRAM из A40 непригоден: он собрал занятость всей карты, а не процесса.
### Процессор годится для служебных ролей
Замер ревьюера, 32 потока из 72, AVX2:
```
LFM2.5-2.6B промпт 1150,8 ток/с генерация 13,4 ток/с
Qwen3-4B промпт 854,2 ток/с генерация 8,7 ток/с
```
Обработка промпта на процессоре быстрая, генерация медленная: она упирается в память и идёт последовательно.
### Сервер отдаёт всё нужное для честной работы
Проверено на живом `127.0.0.1:8081`:
```
GET /props → default_generation_settings.n_ctx = 196608, total_slots = 1
POST /tokenize → точное число токенов («def add(a, b): return a + b» = 10)
```
Предел контекста и размер задания **измеряются**, а не прикидываются.
### Чего в коде нет
```
разбиения задачи на части — нет
подсчёта токенов для планирования — нет; format_token_count только для показа
model_registry.context_window = 128000 — статическое умолчание,
а у модели владельца 196608
llama-swap — только ttl, групп нет: держать две модели резидентно не станет
```
### Поправка к постановке владельца
Оркестратор **не переставал** давать задачи локальной модели:
```
local_adapter.classify_error: "timeout", "timed out", "502", "503", "504"
→ ErrorCategory.TRANSIENT, retry_delay_seconds=2
```
Профиль не помечается исчерпанным и из цепочки не выбывает. Происходит другое: на каждом запросе локальная модель забирает отведённые Hermes 180 секунд, не успевает, и работу доделывает следующий в цепочке — платный. Чинить надо **подачу работы**, а не возврат в цепочку.
### Физика, которую нельзя обойти
**Две модели на одной V100 не работают вдвое быстрее.** Генерация упирается в пропускную способность памяти; две модели делят одну полосу. Вместе они выдадут примерно столько же, сколько одна.
Значит «параллельно» здесь означает **два независимых решения**, а не выигрыш во времени. Ускорение в интерфейсе обещать нельзя.
Оговорка: у MoE активны три миллиарда из тридцати, полосу они едят иначе. Два MoE могут ужиться лучше — **это гипотеза, её измеряют, а не закладывают**.
---
# Часть 1. Замена моделей и замеры
## P0-1. Заменить кодер
Поставить `Qwen3-Coder-30B-A3B-Instruct-Q4_K_M` вместо `Qwen3.8-27B`.
Основание измерено: **109,6 против 30,3 ток/с**, то же качество 83,3%, и на 4 ГиБ меньше.
1. Контекст **не ниже 65536** — порог отбора у Hermes.
2. Условия запуска взять у нынешнего юнита: `--flash-attn on`, `--cache-type-k/v q8_0`, `--reasoning off`, `--parallel 1`.
3. **Прежний юнит сохранить**; откат одной командой описать и проверить.
4. Скорость и видеопамять замерить **на живой службе**, а не переносить из A45.
## P0-2. Заменить компрессор
Поставить `LFM2.5-2.6B` вместо `Qwen3-4B` на порт 8082.
1. **Сначала замерить качество сжатия** на том же наборе, что у нынешнего. Быстрее — не значит лучше; сожмёт хуже, замену не делать и так и написать.
2. Рассмотреть запуск **на процессоре** (`-ngl 0`): освобождает видеопамять, а сжатие — чтение многого и запись малого, где процессор силён. Замерить оба варианта и дать владельцу числа для решения.
## P0-3. Измерить кандидатов в пару
Замерить **расход видеопамяти по процессу при 64К** для `Phi-4-14B`, `Qwen2.5-Coder-14B`, `Qwen3-4B-2507`, `Granite-4.2-8B` — через `nvidia-smi --query-compute-apps=pid,used_memory`, а не по занятости карты.
Затем **проверить запуском**, какие пары помещаются вместе с компрессором в 32 768 МиБ. Не расчётом.
Отдельно замерить, **что происходит со скоростью при одновременной работе двух моделей**: суммарная выработка против одиночной. Это проверка утверждения о полосе памяти, и её результат решает, имеет ли смысл держать пару резидентно.
**Часть 1 сдаётся отдельно.**
---
# Часть 2. Надзиратель локальных моделей
Владелец: «если выбирается локальная модель, должен появляться субагент, который мониторит подачу работы. Если у модели не хватает контекста, он разбивает задачу на куски и подаёт, пока не заработает. Потом формирует память, какой объём давать модели».
## P0-4. Роль надзирателя
1. **Новая каноническая роль** `local-supervisor` в реестре.
2. **Включается автоматически**, когда выбранный профиль локальный (`local`, `llama.cpp`, `ollama`, `vllm`). Вручную назначать не нужно.
3. **Не встаёт между ролью и платным провайдером.**
4. **Надзиратель — не модель, а распорядитель.** Считает, режет, подаёт, наблюдает; работу делает локальная модель. Тратить на него платный вызов нельзя.
Основная его работа — счёт и разбор, а не рассуждение: токены считает `/tokenize`, предел даёт `/props`, границы кусков определяются разбором кода. Ставить сюда слабую модель значит сделать надзирателя менее надёжным.
## P0-5. Замер перед подачей, а не догадка
1. **Предел контекста брать у живого сервера** через `/props`. Умолчание `model_registry` = 128000 к модели владельца отношения не имеет.
2. **Размер задания считать через `/tokenize`** — точно. Оценка по символам допустима только запасным путём и должна быть помечена как оценка.
3. **Учитывать место под ответ**: в контекст входят задание, история и ожидаемый ответ. Запас обосновать.
4. **Не выдумывать пределы.** Сервер не ответил — так и записать.
## P0-6. Разбиение и подача
1. **Помещается — подавать целиком.** Резать без нужды вредно: теряется связность.
2. **Не помещается — резать по смысловым границам**: файл, функция, класс, раздел. Посреди выражения — нельзя.
3. **Подавать последовательно**, передавая накопленный результат, и собирать ответ.
4. **Неделимая задача — честный отказ**, а не разрез наугад.
5. **Число попыток ограничено** и настраивается. Бесконечный цикл на единственной видеокарте недопустим.
6. **После исчерпания попыток** — отказ с причиной, дальше обычная отказоустойчивость. Надзиратель **не прячет неудачу**, удерживая работу на локальной модели любой ценой.
## P0-7. Наблюдение за ходом
1. **Видеть, что модель работает, а не висит**: поток ответа или тайминги сервера.
2. **Различать три исхода**: успел, не успел, ответил ошибкой. Сейчас всё сваливается в «таймаут».
3. **Показывать ход** на «Обзоре»: какой кусок из скольких, сколько токенов подано.
4. **Отдельно ловить случай A39**: весь лимит ушёл на рассуждения, ответа нет. Измерено: 1500 токенов за 111 секунд и **ноль символов ответа**; с `enable_thinking: false` — ответ за 11 секунд. Признак — пустой ответ при полном расходе лимита; лечится `request_options`, механизм есть после A39.
## P0-8. Память: какой объём модель тянет
1. **Записывать по каждой модели**: при каком размере получался ответ, при каком нет, сколько занимало, какой кусок оказался рабочим.
2. **Хранить в общей памяти** (`/srv/projects/AI-Memory`, структура после A47). Запись подписывается: модель, когда, по какому заданию.
3. **Использовать при следующей подаче**: начинать с размера, который уже работал.
4. **Привязывать к имени сборки из метаданных GGUF**, а не к порту или имени профиля. Урок Tiel-Coder: в файле оказалась `Ornith-1.5-35B`.
5. **Показывать во вкладке «Память»** надзирателя, что он усвоил.
---
# Часть 3. Пара кодеров и облачный судья
Планировать **по числам части 1**.
## P0-9. Схема и её цена
```
задание → Кодер A (локальный) ┐
→ Кодер B (локальный) ┘→ судья (облачная модель)
├ принято → дальше по конвейеру
└ не принято → обоим на доработку
```
1. **Кодеры не видят работу друг друга** до суда. Иначе второе решение не независимо и смысл теряется.
2. **Судья облачный**, видеопамяти не занимает. Это роль `developer-2` существующего конвейера; модель задаёт владелец в интерфейсе — **зашивать имя модели или провайдера в код нельзя**.
3. **Судья получает задание и оба решения**, возвращает: какое принято либо что доработать каждому.
4. **Ревьюер остаётся на своём месте** после судьи; конвейер не переделывать.
5. **Пара включается настройкой**; возврат к одному кодеру возможен.
**Предел итераций обязателен.** Круг «пока не сделают правильно» тратит платную квоту судьи на каждом обороте.
6. **Предел кругов** настраивается, умолчание обосновать. Механизм ограничения итераций в конвейере уже есть — использовать его.
7. **Показывать номер круга.**
8. **Круги исчерпаны — честный отказ** с последним состоянием обеих работ и мнением судьи. Частичный результат за готовый не выдавать.
9. **Считать расход**: сколько вызовов судьи ушло на задачу.
10. **Круг без изменений — застревание.** Оба вернули то же, что и в прошлый раз — прекратить и сказать.
---
## P0-10. Аудит вторым проходом
1. **Числа части 1 сняты на живой службе**, а не перенесены из A45.
2. **Откат к прежнему кодеру** выполнен и проверен.
3. **Пара проверена запуском**, а не расчётом: обе модели подняты, памяти хватило, обе отвечают.
4. **Утверждение о полосе памяти** проверено: суммарная выработка двух моделей против одиночной. Результат записать, каким бы он ни был.
5. **Заведомо большая задача** разбита, подана и собрана; **неделимая** дала честный отказ.
6. **Предел попыток и предел кругов** проверены задачей, которая не выполнится никогда.
7. **Предел контекста взят у сервера**, счёт токенов сверен с `/tokenize` независимо.
8. **Независимость кодеров**: решение одного не попадает в контекст другого.
9. **Модель судьи задаётся из интерфейса**, а не зашита.
10. **Для платных провайдеров путь не изменился**, надзиратель туда не лезет.
11. **Службы владельца вернуть в рабочее состояние.**
12. **Побочные изменения** объяснить.
13. **Пропущенный пункт назвать пропущенным.**
---
## Ограничения
- Видеокарта одна, сервер рабочий: окна для замеров согласовать, службы возвращать в строй.
- Прежние юниты сохранять, откат описывать и проверять.
- Учётные данные и `~/.hermes/agy_profiles/` не трогать.
- Имена моделей и провайдеров в код не зашивать.
- Конфигурацию Hermes не править.
- Версию `0.1.1` не поднимать.
- Правило честности без исключений: ни одного числа без замера; ускорение не обещать без подтверждения.
## Критерии приёмки
**Часть 1**
1. Кодер заменён на Qwen3-Coder-30B-A3B, контекст не ниже 65536; скорость и видеопамять замерены на живой службе; откат проверен.
2. Компрессор замерен в обоих вариантах; замена сделана либо обоснованно отклонена.
3. Видеопамять четырёх кандидатов при 64К измерена по процессу.
4. Проверено запуском, какие пары помещаются; измерено, что со скоростью при одновременной работе.
**Часть 2**
5. Роль `local-supervisor` включается автоматически для локальных профилей; для остальных путь не изменился.
6. Предел контекста берётся через `/props`; размер задания считается через `/tokenize`; проверено.
7. Большая задача разбивается по смысловым границам и собирается; неделимая даёт отказ.
8. Число попыток ограничено; бесконечного цикла нет.
9. Ход виден владельцу; случай «весь лимит на рассуждения» распознаётся отдельно от таймаута.
10. Рабочий объём записан в общую память с привязкой к имени сборки GGUF и используется при следующей подаче.
**Часть 3**
11. Пара работает независимо; облачный судья сравнивает и возвращает на доработку.
12. Модель судьи задаётся из интерфейса.
13. Предел кругов работает; застревание распознаётся; расход вызовов судьи показан.
14. Пара включается и отключается настройкой.
**Общее**
15. Неизмеренное показано как `Н/Д` с причиной; неудачи не скрываются.
16. `ruff check .` чисто; релизный гейт 10/10; тестов не меньше **517**.
17. Службы владельца работают.
18. Память проекта в AI-Memory обновлена.
19. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`.
## Главное
Сейчас локальная модель получает задачу целиком, не успевает за отведённое время и отдаёт работу платному провайдеру. Так на каждом запросе: она не выбывает из цепочки, она просто всякий раз проигрывает.
Замена кодера окупается сама по себе — вчетверо быстрее при том же качестве и на четыре гигабайта меньше. Надзиратель делает подачу работы соразмерной модели: измеряет, а не предполагает, режет по смыслу и запоминает рабочий объём. Пара кодеров с облачным судьёй добавляет вторую независимую попытку — но её ценность в разных ошибках, а не в скорости, и каждый круг доработки стоит платного вызова.
## Порядок сдачи
Передать точный `FINAL_COMMIT_SHA`.

View file

@ -0,0 +1,122 @@
# Задание A55: оставшиеся дефекты подключения аккаунтов
## Дата поступления
2026-08-31
## База
`origin/main` (`26f7d2c`).
```
git fetch origin --prune
git checkout -b antigravity/a55-account-connection origin/main
```
В `main` напрямую не пушить.
## Порядок исполнения
Два прохода: **Flash** реализует, **Pro** проводит аудит. Пункт **P0-6** написан для аудитора.
Владелец не может настроить ни одного аккаунта. Это блокирует всю работу с хабом.
---
## Что ревьюер уже починил — не переделывать
В `main` закрыто и проверено исполнением:
```
кэш опознания _identities/_snapshots не чистились при удалении ключа:
слот, переиспользованный под другой аккаунт, показывал
прежнюю почту. Добавлен forget_profile.
NVIDIA успешный список моделей теперь считается доказательством
рабочего ключа; отказ пробного запроса («Function ... Not
found for account») больше не валит подключение.
401 и 403 по-прежнему отказ.
выход из программы неудачная остановка процессов больше не отменяет выход
конфигурация Hermes проверяется семь известных путей, в сообщении
перечисляется, где искали
```
---
## P0-1. Antigravity не подключается на Windows
Владелец: «на винде не подключается аккаунт аги, выдаёт ошибку API, хотя в браузере вышло, что авторизация прошла. Скорее всего требует ссылку с браузера, как в линуксе».
В браузере открывается `127.0.0.1:<порт>` и показывается «Авторизация успешно завершена», но мастер этого не видит и завершает шаг 3 с «Не указан API-ключ или не завершена авторизация».
1. **Разобраться, почему успешный возврат не доходит до мастера** на Windows, тогда как на Linux доходит.
2. **Мастер обязан дождаться** завершения входа и увидеть его результат, а не требовать ключ у провайдера, который работает по ссылке.
3. **Если возврат по ссылке на Windows невозможен** — дать тот же путь, что на Linux: поле для вставки ссылки или кода. Владелец сам это предположил.
4. **Сообщение «Не указан API-ключ» для Antigravity неверно по сути**: у него ключа нет, у него вход по ссылке. Текст должен соответствовать способу подключения.
## P0-2. Ollama ищет сервер не там
Ошибка `WinError 10061` честна, но бесполезна: мастер по умолчанию подставляет `http://127.0.0.1:11434/v1`, то есть машину, где запущен хаб. Ollama владельца работает **на сервере**.
1. **Подсказка должна объяснять**, что адрес относится к машине с хабом, и предлагать указать сетевой адрес сервера.
2. **Кнопка «Найти на этом компьютере»** уже есть — добавить проверку заданного вручную адреса с внятным ответом.
3. **Суффикс `/v1` для Ollama лишний**: нативный интерфейс живёт на `/api`. Проверить, какой адрес подставляется по умолчанию и куда потом идут запросы.
## P0-3. Antigravity на Linux: подключился, моделей нет
Аккаунт подключён, но «Список моделей ещё не получен», «Каталог моделей (0)», состояние «Не проверялось». При этом квоты подтянулись и показывают 100% — значит связь с провайдером есть.
1. **Выяснить, почему квоты приходят, а список моделей нет.** Источники разные, и один работает.
2. Возможно, поможет уже сделанный сброс кэша — **проверить на живой установке владельца** до того, как чинить что-то ещё.
## P0-4. Версия в интерфейсе
После правки ревьюера номер версии берётся из API, а зашитые значения из разметки убраны. На сборке `b2ca7cd` владелец всё ещё видит `Hermes Hub Web v0.1.1` при версии `0.1.2`.
1. **Проверить, что API отдаёт версию** и что клиент её получает на всех экранах, а не только при открытии панели обновления.
2. **Не подставлять значение по умолчанию.** Нет версии — писать `Н/Д` с причиной.
## P0-5. Экран настроек пуст
На «Настройках» половина полей не заполнена: «Н/Д: нет в снапшоте», «Н/Д: API не передаёт путь», «Н/Д: текущее значение не передано». Пустуют хост и порт, токен, порог квоты, маскирование почты, каталоги данных и конфигурации, путь к журналу.
1. **Передавать текущие значения настроек** в снапшот, чтобы поля показывали настроенное, а не заглушку.
2. **Токен не показывать целиком** — достаточно признака «задан» и возможности заменить.
3. **Значение действительно неизвестно — оставить `Н/Д` с причиной.** Заполнять правдоподобным нельзя.
## P0-6. Аудит вторым проходом
1. **Пройти путь подключения целиком на обеих машинах**: Antigravity, NVIDIA, OpenRouter, Ollama. Скриншоты приложить.
2. **Проверить, что после смены аккаунта в слоте показывается новая почта** — правка ревьюера, убедиться, что она работает на живой установке.
3. **Проверить сообщение о конфигурации Hermes**: оно должно перечислять проверенные пути.
4. **Различать «нет доступа» и «не найдено»** — не повторять ошибку ложного диагноза.
5. **Побочные изменения** объяснить.
6. **Пропущенный пункт назвать пропущенным.**
---
## Ограничения
- Учётные данные и `~/.hermes/agy_profiles/` не трогать.
- Правки ревьюера из `main` не откатывать.
- Версию `0.1.2` не понижать.
- Правило честности без исключений: причина отказа доходит до владельца текстом, неизвестное показывается как `Н/Д` с причиной.
## Критерии приёмки
1. Ветка в `origin`, `git status` чист.
2. Antigravity подключается на Windows; путь входа проверен вручную, скриншоты приложены.
3. Текст ошибки соответствует способу подключения провайдера.
4. Ollama: подсказка объясняет, чья это машина; заданный вручную адрес проверяется; суффикс пути верный.
5. Antigravity на Linux отдаёт список моделей; причина прежнего отказа названа.
6. Версия в интерфейсе совпадает с установленной на всех экранах.
7. Поля настроек показывают текущие значения; неизвестное помечено `Н/Д` с причиной.
8. `ruff check .` чисто; релизный гейт 10/10; тестов не меньше **599**.
9. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`.
## Главное
Владелец третий день не может подключить ни одного аккаунта. Часть причин уже устранена — подменённая почта из кэша, ложный отказ NVIDIA, отмена выхода из программы. Осталось четыре: вход Antigravity на Windows, адрес Ollama, отсутствие моделей на Linux и незаполненные настройки.
Каждая проверяется вручную на живой установке. Тесты все эти дефекты пропустили.
## Порядок сдачи
Передать точный `FINAL_COMMIT_SHA`.

View file

@ -0,0 +1,141 @@
# Задание A56: сжатие контекста — компрессор должен начать работать
## Дата поступления
2026-09-01
## База
`origin/main` (`26f7d2c`).
```
git fetch origin --prune
git checkout -b antigravity/a56-context-compression origin/main
```
В `main` напрямую не пушить.
## Порядок исполнения
Два прохода: **Flash** реализует, **Pro** проводит аудит. Пункт **P0-6** написан для аудитора.
Зона: надзиратель локальных моделей и локальный адаптер. С A55 (подключение аккаунтов) не пересекается.
---
## Задача
На сервере владельца работает вторая локальная модель, называемая компрессором. Ревьюер проверил код: **в хабе нет ни одной строки, которая бы к ней обращалась для сжатия**. Порт 8082 упоминается ровно один раз — в списке адресов для обнаружения локальных серверов.
Надзиратель из A52 умеет резать задачу на куски по смысловым границам, и это работает. Но накопленный контекст между кусками никто не сжимает, и модель простаивает.
## Что проверено ревьюером на живом сервере — заново не мерить
Настройка после переделки раскладки:
```
кодер Qwen3-Coder-30B-A3B порт 8081 -c 229376 30 008 МиБ 107,4 ток/с
компрессор Qwen3-4B-2507 порт 8082 -c 32768 на CPU, -ngl 0 -t 32
604 МиБ видеопамяти
свободно на карте: 2 152 МиБ из 32 768
```
**Скорость компрессора на процессоре измерена на настоящем промпте:**
```
промпт 5068 токенов → 853,9 ток/с
генерация → 5,4 ток/с
```
То есть сжать 32 тысячи токенов — около 38 секунд чтения плюс несколько секунд на сводку. Чтение быстрое, генерация медленная; для сжатия это удачное сочетание, потому что на выходе короткий текст.
**Качество сжатия у этой модели замерено в A52: 100%** — сохраняет порты, адреса, контрольные суммы. Проверено ревьюером повторно: в ответе остались и адрес сервера, и оба порта, и имя модели.
**Родной контекст кодера — 262 144** по метаданным GGUF, поэтому 224К внутри предела.
**Обёртка над llama-server удалена**, юниты описывают действительность. Подменять бинарник больше нельзя: настройки задаются юнитом.
---
## P0-1. Компрессор становится настраиваемой ролью
1. **Отдельная роль или настройка профиля** — «модель для сжатия контекста». Владелец выбирает её в интерфейсе из подключённых локальных профилей.
2. **Адрес берётся из профиля**, а не зашивается. Порт 8082 сегодняшний, завтра другой.
3. **Компрессор не участвует в маршрутизации Hermes.** Это служебная роль: она не должна попадать в цепочки ролей и не обязана проходить порог в 64К. Если владелец захочет — назначит её явно, но по умолчанию нет.
4. **Компрессор не настроен — сжатие не выполняется**, и это нормальное состояние. Показывать `Н/Д: модель для сжатия не выбрана`, а не ошибку.
## P0-2. Когда сжимать
1. **Порог по заполнению контекста**, а не по числу сообщений. Предел берётся у сервера через `/props`, размер накопленного — через `/tokenize`; оба механизма уже есть в надзирателе после A52.
2. **Значение порога настраивается**, умолчание обосновать. Разумно начинать сжатие, когда занято около трёх четвертей.
3. **Сжимать самое старое**, оставляя свежее нетронутым: последние сообщения нужны модели дословно.
4. **Не сжимать то, что уже сжато.** Повторное сжатие сводки теряет факты и делает это незаметно.
## P0-3. Что сохранять обязательно
Главное требование к качеству, и оно проверяемое.
Сводка обязана сохранять **дословно**: пути к файлам, адреса и порты, имена функций и переменных, контрольные суммы, номера версий и коммитов, точные значения из замеров.
1. **Проверять это тестом**: подать текст с известными значениями и убедиться, что они в сводке остались.
2. **Потеря факта — дефект**, а не приемлемая цена сжатия. Модель на этой задаче даёт 100%, значит планка достижима.
3. **Указывать степень сжатия**: было столько токенов, стало столько.
## P0-4. Видно, что происходит
1. **Показывать факт сжатия** владельцу: когда, сколько токенов было и стало, сколько заняло.
2. **Хранить исходный текст** до конца задачи, чтобы можно было вернуться, если сводка потеряла нужное.
3. **Сжатие не должно идти молча**: 38 секунд тишины владелец воспримет как зависание.
4. **Ошибка сжатия не роняет задачу.** Компрессор не ответил — работаем с несжатым контекстом и говорим об этом, а не прекращаем работу.
## P0-5. Память о том, что сработало
Продолжение линии A52.
1. Записывать в общую память (`/srv/projects/AI-Memory`): какой объём сжимался, во сколько раз, сколько заняло, сохранились ли факты.
2. Привязывать к **имени сборки GGUF**, а не к порту или имени профиля.
3. Использовать накопленное: начинать с размера куска, который уже давал хороший результат.
## P0-6. Аудит вторым проходом
1. **Проверить на живом сервере**, а не заглушкой: подать текст больше порога и убедиться, что сжатие произошло и факты уцелели.
2. **Проверить сохранение дословных значений** — пути, порты, суммы. Это главный критерий.
3. **Проверить, что компрессор не попал в маршрутизацию** Hermes и не мешает выбору моделей.
4. **Проверить поведение при недоступном компрессоре**: задача продолжается на несжатом контексте.
5. **Убедиться, что предел контекста и счёт токенов берутся у сервера**, а не из умолчаний.
6. **Побочные изменения** объяснить.
7. **Пропущенный пункт назвать пропущенным.**
---
## Ограничения
- Юниты владельца не править: обёртку над `llama-server` только что убрали, подменять бинарник запрещено.
- Службы `qwen-coder` и `qwen-compressor` возвращать в рабочее состояние после проверок.
- Адреса и порты в код не зашивать.
- Учётные данные и `~/.hermes/agy_profiles/` не трогать.
- Версию `0.1.2` не понижать.
- Правило честности без исключений: неизмеренное — `Н/Д` с причиной, потерянный факт — дефект.
## Критерии приёмки
1. Ветка в `origin`, `git status` чист.
2. Модель для сжатия выбирается в интерфейсе; адрес берётся из профиля.
3. Компрессор не участвует в маршрутизации Hermes по умолчанию.
4. Порог сжатия считается от предела контекста, взятого через `/props`, и объёма, посчитанного через `/tokenize`.
5. Сжимается старое, свежее остаётся дословным; повторное сжатие сводки не выполняется.
6. Тест на сохранение дословных значений проходит: пути, порты, контрольные суммы, номера версий.
7. Владелец видит факт и степень сжатия; исходный текст сохраняется до конца задачи.
8. Недоступный компрессор не роняет задачу.
9. Опыт записан в общую память с привязкой к имени сборки GGUF.
10. Проверено на живом сервере, вывод приложен.
11. `ruff check .` чисто; релизный гейт 10/10; тестов не меньше **599**.
12. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`, `X passed / Y skipped / Z failed`.
## Главное
Владелец держит на сервере вторую модель под сжатие контекста, освободил ради неё место и вынес её на процессор. Модель работает, отвечает и сжимает правильно — но в хабе нет кода, который бы её позвал.
Задание закрывает разрыв между настроенным железом и неиспользуемой возможностью. Ключевое требование одно: **сводка не теряет фактов**. Модель на этой задаче даёт сто процентов, значит планка достижима, и снижать её нельзя — потерянный путь или порт всплывёт через два шага в виде необъяснимой ошибки.
## Порядок сдачи
Передать точный `FINAL_COMMIT_SHA`.