Compare commits

..
2 Commits
Author SHA1 Message Date
oqyude 7aec35b8df metaagent update to v1.1.0 2026-07-22 01:27:30 +03:00
oqyude 685d3262d8 metaagent updated 2026-07-22 01:27:17 +03:00
136 changed files with 3375 additions and 6340 deletions
+78
View File
@@ -0,0 +1,78 @@
# Analysis Report
## Session
- **Session ID:** `metaagent-002`
- **Target repo:** `S:\Git\nifodea`
- **Date:** 2026-07-22
- **Project type:** `existing`
## 1. Общая информация
- **README:** Личная финансовая модель с прогнозом денежных потоков, сценарным анализом и AI-ассистентом. Python + JSON + Excel + AI.
- **Лицензия:** не выбрана
- **CI/CD:** отсутствует
- **Точка входа:** `cli/main.py` (команда `cf`)
- **Система сборки:** `pyproject.toml` (setuptools)
## 2. Стек технологий
| Компонент | Значение |
|---|---|
| Язык | Python >= 3.11 |
| Фреймворк | Typer (CLI) |
| База данных | JSON-файлы |
| Тестовый раннер | pytest |
| Пакетный менеджер | pip (setuptools) |
| Линтер/форматтер | ruff |
## 3. Архитектура
```
cashflow_model/ # Модели данных (dataclass + JSON)
engine/ # Вычислительное ядро (forecast + scenarios)
sync/ # Excel import/export
ai/ # AI-ассистент (заглушка)
cli/ # CLI (Typer)
tests/ # pytest
data/ # JSON-модели
exports/ # Экспортированные .xlsx
```
**Паттерн:** Модульный монолит
**Ключевые модули:**
| Модуль | Описание |
|---|---|
| cashflow_model | Модели данных: Account, Transaction, RecurringCashflow, Asset, Liability, ForecastScenario, FinancialModel |
| engine | Вычислительное ядро: ForecastService (прогноз), ScenarioService (сценарии + what-if) |
| sync | ExcelSync — импорт/экспорт .xlsx |
| ai | AssistantService — генерация промптов (заглушка) |
| cli | Typer CLI — 8 команд |
## 4. Конвенции
- **Стиль:** snake_case для функций/переменных, PascalCase для классов
- **Импорты:** стандартные, сгруппированные
- **Типизация:** используется (dataclass, type hints)
- **Обработка ошибок:** через исключения
- **Логирование:** не используется
## 5. Тесты
- **Команда запуска:** `pytest`
- **Всего тестов:** 26
- **Пройдено:** 26
- **Упало:** 0
- **Пропущено:** 0
## 6. Базовая проверка
- **Сборка:** OK (pip install -e .)
- **Линтер:** OK (ruff check . — all checks passed)
- **Git status:** есть незакоммиченные изменения (checkpoints.json, metaagent-request.md, AGENTS.md, data/model.json, .agent/rules/)
## 8. Примечания
Проект полностью функционален: 26 тестов проходят, линтер чист. Требуется только обновление MetaAgent-артефактов до v1.1.0.
-25
View File
@@ -1,25 +0,0 @@
{
"version": "3.0.0",
"archived_at": "2026-10-08T17:05:00Z",
"session": "metaagent-005",
"goal": "Обсуждение архитектуры и серьёзный refactor",
"tasks": [
{ "id": "T1", "title": "Реструктуризация в domain/application/infrastructure + version=1", "archived_at": "2026-10-08T17:05:00Z", "request": "req-T1", "commit": "feb77ef" },
{ "id": "T2", "title": "Pydantic v2 — миграция моделей", "archived_at": "2026-10-08T17:05:00Z", "request": "req-T2", "commit": "c765f36" },
{ "id": "T3", "title": "Decimal для денег", "archived_at": "2026-10-08T17:05:00Z", "request": "req-T3", "commit": "363d440" },
{ "id": "T4", "title": "Repository pattern — ModelRepository", "archived_at": "2026-10-08T17:05:00Z", "request": "req-T4" },
{ "id": "T5", "title": "Dependency Injection в сервисах", "archived_at": "2026-10-08T17:05:00Z", "request": "req-T5", "commit": "541a768" },
{ "id": "T6", "title": "Декомпозиция CLI", "archived_at": "2026-10-08T17:05:00Z", "request": "req-T6" },
{ "id": "T7", "title": "Финальная валидация", "archived_at": "2026-10-08T17:05:00Z", "request": "req-T7", "commit": "3ef1061" }
],
"requests": [
{ "id": "req-T1", "task_id": "T1", "status": "approved", "archived_at": "2026-10-08T17:05:00Z" },
{ "id": "req-T2", "task_id": "T2", "status": "approved", "archived_at": "2026-10-08T17:05:00Z" },
{ "id": "req-T3", "task_id": "T3", "status": "approved", "archived_at": "2026-10-08T17:05:00Z" },
{ "id": "req-T4", "task_id": "T4", "status": "approved", "archived_at": "2026-10-08T17:05:00Z" },
{ "id": "req-T5", "task_id": "T5", "status": "approved", "archived_at": "2026-10-08T17:05:00Z" },
{ "id": "req-T6", "task_id": "T6", "status": "approved", "archived_at": "2026-10-08T17:05:00Z" },
{ "id": "req-T7", "task_id": "T7", "status": "approved", "archived_at": "2026-10-08T17:05:00Z" }
],
"checkpoints": []
}
-36
View File
@@ -1,36 +0,0 @@
{
"request_id": "req-T1",
"task_id": "T1",
"title": "Restructure to domain/application/infrastructure + schema version 1",
"status": "ready_for_review",
"goal": "Ввести явные слои и подготовить инфраструктуру миграций схемы",
"changes": {
"summary": "Перестроена пакетная структура: cashflow_model/ → domain/ (модели), engine/ → application/ (сервисы), cli/, sync/, ai/ → infrastructure/ (адаптеры). Обновлены все импорты в коде и тестах. В FinancialModel добавлено поле version=1 в to_dict() и миграционный хук _from_v0/_from_v1 в from_dict() для обратной совместимости. Обновлён pyproject.toml: cf = infrastructure.cli.main:app, packages.find = ['domain*', 'application*', 'infrastructure*'].",
"commits": ["feb77ef217a54720868218b911312b040bcfb118"],
"files_changed": [
"domain/ (new, 8 файлов из cashflow_model/)",
"application/ (new, 3 файла из engine/)",
"infrastructure/ai/ (new, из ai/)",
"infrastructure/cli/ (new, из cli/)",
"infrastructure/sync/ (new, из sync/)",
"tests/* (8 файлов, импорты обновлены)",
"pyproject.toml (cf entry + packages.find)",
"data/model.json (version=1)"
]
},
"verification": {
"tests_passed": "63/63",
"lsp_clean": true,
"cf_command_works": true,
"round_trip_v1": "ok",
"legacy_v0_load": "ok"
},
"fulfills_ac": [
"Структура domain/application/infrastructure создана",
"Все исходные файлы перемещены в соответствующие слои",
"Все импорты обновлены",
"FinancialModel.to_dict() возвращает {'version': 1, ...}",
"FinancialModel.from_dict() поддерживает v0 и v1",
"pytest проходит 63/63"
]
}
-34
View File
@@ -1,34 +0,0 @@
{
"request_id": "req-T2",
"task_id": "T2",
"title": "Pydantic v2 — replace @dataclass with BaseModel",
"status": "ready_for_review",
"goal": "Заменить ручную сериализацию на pydantic.BaseModel, добавить валидацию",
"changes": {
"summary": "Все 7 моделей domain/ переведены с @dataclass на pydantic.BaseModel. Удалены ручные to_dict()/from_dict() — заменены на model_dump(mode='json')/model_validate(). Добавлены field_validators: Account.balance >= 0, Transaction.amount != 0, RecurringCashflow.amount != 0 и frequency ∈ {daily,weekly,monthly,yearly}, Liability.interest/payment >= 0, ExchangeRate.rate > 0, ForecastScenario.multipliers >= 0. UUID в JSON автоматически сериализуется как str. excel_sync.py адаптирован на model_validate(). Тесты test_model.py и test_currency.py обновлены. pyproject.toml: pydantic>=2.0.",
"commits": ["c765f36"],
"files_changed": [
"domain/account.py, asset.py, currency.py, liability.py, recurring.py, scenario.py, transaction.py, model.py",
"infrastructure/sync/excel_sync.py",
"tests/test_model.py, tests/test_currency.py",
"pyproject.toml"
]
},
"verification": {
"tests_passed": "63/63",
"validators_work": "Account negative balance, Transaction zero amount, ExchangeRate negative rate — all rejected",
"uuid_in_json_as_str": true,
"round_trip": "ok",
"cf_init_works": true,
"cf_forecast_works": true,
"cf_scenario_works": true
},
"fulfills_ac": [
"Все модели domain/ — наследники pydantic.BaseModel",
"Удалены ручные to_dict() и from_dict()",
"UUID в JSON сериализуется как строка",
"Валидация работает (balance, amount, rate, frequency)",
"Excel-sync адаптирован под pydantic",
"pytest 63/63"
]
}
-31
View File
@@ -1,31 +0,0 @@
{
"request_id": "req-T3",
"task_id": "T3",
"title": "Decimal for money",
"status": "ready_for_review",
"goal": "Точность финансовых расчётов — float → Decimal",
"changes": {
"summary": "Все денежные поля в domain/ переведены с float на Decimal. CurrencyConverter использует Decimal арифметику с ROUND_HALF_UP до 2 знаков. ForecastService и ScenarioService переписаны для работы с Decimal. assistant.py получил _DecimalEncoder для json.dumps (Decimal → str в JSON).",
"commits": ["363d440"],
"files_changed": [
"domain/account.py, asset.py, currency.py, liability.py, recurring.py, scenario.py, transaction.py",
"application/forecast.py, scenarios.py",
"infrastructure/ai/assistant.py"
]
},
"verification": {
"tests_passed": "63/63",
"decimal_preserved": "100.50 round-trip exact (no float drift)",
"json_safe": "Decimal → str via model_dump(mode='json'), back via model_validate",
"cf_init_forecast_scenario_works": true
},
"fulfills_ac": [
"Все monetary поля — Decimal",
"CurrencyConverter работает с Decimal",
"ForecastService арифметика — Decimal",
"Excel-sync продолжает работать",
"rich.print/f-strings форматируют Decimal",
"JSON-сериализация Decimal работает (через pydantic и _DecimalEncoder)",
"pytest 63/63"
]
}
-35
View File
@@ -1,35 +0,0 @@
{
"request_id": "req-T4",
"task_id": "T4",
"title": "Repository pattern — ModelRepository, JsonFileRepository, ExcelRepository",
"status": "ready_for_review",
"goal": "Абстрагировать хранилище FinancialModel через Protocol, подготовить к БД/API",
"changes": {
"summary": "Создан application/repositories/ с ModelRepository Protocol (runtime_checkable). Реализации: infrastructure/repositories/JsonFileRepository (.json с version) и ExcelRepository (бывший ExcelSync, переименован). FinancialModel.save/load удалены — класс хранит только данные. infrastructure/sync/ удалён. CLI (main.py, config.py) использует JsonFileRepository + ExcelRepository через локальные singletons. test_excel_sync.py обновлён на ExcelRepository. Новый test_repositories.py: 5 тестов.",
"commits": ["<see git log>"],
"files_changed": [
"application/repositories/__init__.py, model_repository.py (new)",
"infrastructure/repositories/__init__.py, json_file_repository.py, excel_repository.py (new)",
"infrastructure/sync/ (removed)",
"domain/model.py (save/load удалены)",
"infrastructure/cli/main.py, config.py (используют repositories)",
"tests/test_excel_sync.py, test_model.py, test_repositories.py (new)"
]
},
"verification": {
"tests_passed": "68/68",
"new_tests": 5,
"json_repo_roundtrip": "ok",
"excel_repo_roundtrip": "ok",
"cf_init_works": true,
"cf_export_import_xlsx_works": true
},
"fulfills_ac": [
"ModelRepository Protocol определён",
"JsonFileRepository реализует Protocol",
"ExcelRepository реализует Protocol",
"FinancialModel.save/load удалены",
"Тесты на каждый репозиторий",
"pytest 68/68"
]
}
-30
View File
@@ -1,30 +0,0 @@
{
"request_id": "req-T5",
"task_id": "T5",
"title": "Dependency Injection — services через composition root",
"status": "ready_for_review",
"goal": "Убрать создание сервисов внутри других сервисов, инжектировать зависимости",
"changes": {
"summary": "AssistantService теперь принимает ForecastService через __init__ (раньше создавал new ForecastService() внутри analyze/advice). В infrastructure/cli/main.py добавлен _build_services() — composition root, собирающий граф зависимостей: CurrencyConverter, ForecastService, ScenarioService, AssistantService. Все CLI-команды (forecast, scenario, whatif, compare, analyze) используют _build_services(model) вместо прямого создания сервисов. test_ai.py обновлён.",
"commits": ["541a768"],
"files_changed": [
"infrastructure/ai/assistant.py",
"infrastructure/cli/main.py",
"tests/test_ai.py"
]
},
"verification": {
"tests_passed": "67/67",
"no_internal_service_creation": "AssistantService больше не создаёт ForecastService внутри",
"composition_root": "_build_services() в main.py",
"cf_init_forecast_scenario_compare_whatif_analyze_works": true
},
"fulfills_ac": [
"ForecastService(model) — через __init__",
"ScenarioService(model) — через __init__",
"AssistantService(model, forecast_service, converter) — через __init__",
"Нет new ForecastService() внутри AssistantService",
"CLI: composition root собирает граф",
"pytest 67/67"
]
}
-33
View File
@@ -1,33 +0,0 @@
{
"request_id": "req-T6",
"task_id": "T6",
"title": "Decompose CLI — 9 command files + config sub-typer",
"status": "ready_for_review",
"goal": "Улучшить читаемость CLI: разбить большие main.py/config.py на отдельные модули",
"changes": {
"summary": "infrastructure/cli/main.py (330 LOC) разбит на 9 файлов в commands/: init, forecast, scenario, whatif, compare, import_xlsx, export_xlsx, analyze, info. config.py (428 LOC) перенесён в commands/config_cmd.py как Typer sub-typer. main.py → app.py (entry point, регистрирует все команды). Создан paths.py (константы MODEL_PATH, DATA_DIR) и services.py (composition root: load_model, save_model, build_services, resolve_currency, convert_value, fmt_amount). pyproject.toml: cf = infrastructure.cli.app:app. test_cli.py обновлён.",
"commits": ["<see git log>"],
"files_changed": [
"infrastructure/cli/app.py (new entry point)",
"infrastructure/cli/commands/{init,forecast,scenario,whatif,compare,import_xlsx,export_xlsx,analyze,info,config_cmd}.py",
"infrastructure/cli/paths.py, services.py",
"infrastructure/cli/main.py, config.py (removed)",
"pyproject.toml (cf entry point)",
"tests/test_cli.py"
]
},
"verification": {
"tests_passed": "67/67",
"all_commands_work": ["init", "forecast", "scenario", "whatif", "compare", "import-xlsx", "export-xlsx", "analyze", "info", "config rate-list"],
"file_size_under_100_loc_per_command": true
},
"fulfills_ac": [
"Каждая Typer-команда в отдельном файле cli/commands/*.py",
"config_cmd.py в commands/, остаётся sub-typer",
"paths.py — только пути",
"services.py — composition root + helpers",
"Размер команд < 100 LOC (config_cmd.py — ~300, т.к. содержит 15 sub-команд)",
"Поведение идентично",
"pytest 67/67"
]
}
-31
View File
@@ -1,31 +0,0 @@
{
"request_id": "req-T7",
"task_id": "T7",
"title": "Final validation + README update",
"status": "ready_for_review",
"goal": "Финальная проверка всех 6 задач рефактора + обновление документации",
"changes": {
"summary": "Все 67 тестов проходят. CLI проверен вручную: cf init, forecast, scenario (baseline/optimistic/pessimistic), whatif, compare, info, analyze, config (account-add, transaction-add, asset-add, rate-list). Excel round-trip (export → init → import) сохраняет все данные. README.md полностью обновлён под новую архитектуру: domain/application/infrastructure, pydantic, Decimal, Repository pattern, DI, schema versioning. Все 6 задач рефактора (T1-T6) выполнены и подтверждены.",
"commits": ["3ef1061"],
"files_changed": [
"README.md (полная перезапись: новая архитектура, команды, зависимости)"
]
},
"verification": {
"tests_passed": "67/67",
"cf_init_works": true,
"cf_forecast_works": true,
"cf_scenario_baseline_works": true,
"cf_compare_works": true,
"cf_info_works": true,
"cf_export_import_xlsx_roundtrip": "сохраняет 1 счёт, 1 транзакцию, 1 актив",
"cf_config_subcommands_works": true,
"all_5_refactor_directions_complete": ["A1+A10: слои+version", "A2+A3: pydantic", "A4: Decimal", "A7+A8+A9: DI+Repository", "A5: CLI decompose"]
},
"fulfills_ac": [
"pytest 67/67 pass",
"cf init/forecast/scenario/compare работают",
"cf import-xlsx → cf export-xlsx round-trip работает",
"README.md отражает новую структуру"
]
}
-10
View File
@@ -1,10 +0,0 @@
{
"id": "T1",
"title": "Реструктуризация в domain/application/infrastructure + version=1",
"status": "archived",
"origin": "user:direct",
"request": "req-T1",
"commit": "feb77ef",
"summary": "Перестроена пакетная структура: cashflow_model/ → domain/, engine/ → application/, cli/, sync/, ai/ → infrastructure/. Добавлено version: 1 в FinancialModel.to_dict() с миграционным хуком _from_v0/_from_v1. Обновлён pyproject.toml. 63/63 тестов проходят.",
"archived_at": "2026-10-08T17:05:00Z"
}
-10
View File
@@ -1,10 +0,0 @@
{
"id": "T2",
"title": "Pydantic v2 — миграция моделей",
"status": "archived",
"origin": "user:direct",
"request": "req-T2",
"commit": "c765f36",
"summary": "Все 7 моделей domain/ переведены с @dataclass на pydantic.BaseModel. Удалены ручные to_dict()/from_dict(). Добавлены field_validators (balance >= 0, amount != 0, frequency whitelist, и т.п.). UUID в JSON автоматически сериализуется как str. excel_sync.py и тесты обновлены. 63/63 тестов проходят.",
"archived_at": "2026-10-08T17:05:00Z"
}
-10
View File
@@ -1,10 +0,0 @@
{
"id": "T3",
"title": "Decimal для денег",
"status": "archived",
"origin": "user:direct",
"request": "req-T3",
"commit": "363d440",
"summary": "Все денежные поля (Account.balance, Asset.value, Transaction.amount, ExchangeRate.rate, и т.д.) переведены с float на Decimal. CurrencyConverter использует Decimal арифметику с ROUND_HALF_UP. ForecastService и ScenarioService переписаны. assistant.py получил _DecimalEncoder для json.dumps. 63/63 тестов проходят.",
"archived_at": "2026-10-08T17:05:00Z"
}
-9
View File
@@ -1,9 +0,0 @@
{
"id": "T4",
"title": "Repository pattern — ModelRepository",
"status": "archived",
"origin": "user:direct",
"request": "req-T4",
"summary": "Создан application/repositories/ с ModelRepository Protocol. Реализации: JsonFileRepository (.json с version) и ExcelRepository (бывший ExcelSync, переименован). FinancialModel.save/load удалены. infrastructure/sync/ удалён. CLI использует JsonFileRepository + ExcelRepository. 68/68 тестов проходят (+5 новых для репозиториев).",
"archived_at": "2026-10-08T17:05:00Z"
}
-10
View File
@@ -1,10 +0,0 @@
{
"id": "T5",
"title": "Dependency Injection в сервисах",
"status": "archived",
"origin": "user:direct",
"request": "req-T5",
"commit": "541a768",
"summary": "AssistantService теперь принимает ForecastService через __init__ (раньше создавал new ForecastService() внутри analyze/advice). В infrastructure/cli/main.py добавлен _build_services() — composition root, собирающий граф: CurrencyConverter, ForecastService, ScenarioService, AssistantService. 67/67 тестов проходят.",
"archived_at": "2026-10-08T17:05:00Z"
}
-9
View File
@@ -1,9 +0,0 @@
{
"id": "T6",
"title": "Декомпозиция CLI",
"status": "archived",
"origin": "user:direct",
"request": "req-T6",
"summary": "main.py (330 LOC) → 9 файлов в commands/ + main.py → app.py. config.py (428 LOC) → commands/config_cmd.py как Typer sub-typer. Создан paths.py (константы) и services.py (composition root + helpers). pyproject.toml: cf = infrastructure.cli.app:app. 67/67 тестов проходят. CLI поведение идентично.",
"archived_at": "2026-10-08T17:05:00Z"
}
-10
View File
@@ -1,10 +0,0 @@
{
"id": "T7",
"title": "Финальная валидация",
"status": "archived",
"origin": "user:direct",
"request": "req-T7",
"commit": "3ef1061",
"summary": "67/67 тестов проходят. CLI проверен: init, forecast, scenario, whatif, compare, info, analyze, config sub-typer. Excel round-trip (export → init → import) сохраняет данные. README.md полностью обновлён под новую архитектуру. Все 5 направлений рефактора (A1+A10, A2+A3, A4, A5, A7+A8+A9) реализованы.",
"archived_at": "2026-10-08T17:05:00Z"
}
+24 -17
View File
@@ -1,27 +1,34 @@
{ {
"metaagent_version": "3.0.0", "metaagent_version": "1.1.0",
"session_id": "metaagent-005", "session_id": "metaagent-002",
"target_repo": "/home/oqyude/External/Git/nifodea", "target_repo": "S:\\Git\\nifodea",
"goal": "Обсуждение архитектуры и серьёзный refactor", "goal": "Обновление metaagent-артефактов до v1.0.0, валидация существующего кода и окружения",
"project_type": "existing", "project_type": "existing",
"config": {
"depth": 4,
"design": { "adr": false, "alternative_arch": false },
"red_team": false,
"risk_register": false,
"decomposition": { "invariant_tests": false },
"handoff": { "layer_structure": false }
},
"phases": { "phases": {
"init": "completed", "analysis": "completed",
"analyse": "completed",
"roadmap": "completed",
"design": "skipped", "design": "skipped",
"red_team": "skipped",
"decomposition": "completed", "decomposition": "completed",
"execution": "completed", "environment": "completed",
"metastate": "completed",
"handoff": "completed" "handoff": "completed"
}, },
"tasks": [ "tasks": [
{ "id": "T1", "title": "Реструктуризация в domain/application/infrastructure + version=1", "status": "archived", "origin": "user:direct" }, { "id": "T1", "title": "Инициализация проекта и зависимостей", "status": "completed", "depends_on": [], "acceptance_criteria": ["pyproject.toml создан", "Все __init__.py созданы", "ruff проходит", "pytest запускается"] },
{ "id": "T2", "title": "Pydantic v2 — миграция моделей", "status": "archived", "origin": "user:direct" }, { "id": "T2", "title": "Модель данных (dataclass + JSON)", "status": "completed", "depends_on": ["T1"], "acceptance_criteria": ["Все сущности dataclass", "FinancialModel save/load JSON"] },
{ "id": "T3", "title": "Decimal для денег", "status": "archived", "origin": "user:direct" }, { "id": "T3", "title": "Forecast Engine", "status": "completed", "depends_on": ["T2"], "acceptance_criteria": ["forecast_cashflow работает", "recurring проецируются", "активы/обязательства учтены"] },
{ "id": "T4", "title": "Repository pattern — ModelRepository", "status": "archived", "origin": "user:direct" }, { "id": "T4", "title": "Scenario Analysis", "status": "completed", "depends_on": ["T3"], "acceptance_criteria": ["3 сценария", "what-if модификация", "сравнение сценариев"] },
{ "id": "T5", "title": "Dependency Injection в сервисах", "status": "archived", "origin": "user:direct" }, { "id": "T5", "title": "Excel Sync", "status": "completed", "depends_on": ["T2"], "acceptance_criteria": ["импорт из Excel", "экспорт в Excel", "ошибки невалидного формата"] },
{ "id": "T6", "title": "Декомпозиция CLI", "status": "archived", "origin": "user:direct" }, { "id": "T6", "title": "CLI (Typer)", "status": "completed", "depends_on": ["T2","T3","T4","T5","T7"], "acceptance_criteria": ["init/forecast/analyze/import/export/scenario/whatif/compare команды"] },
{ "id": "T7", "title": "Финальная валидация", "status": "archived", "origin": "user:direct" } { "id": "T7", "title": "AI Assistant", "status": "completed", "depends_on": ["T3"], "acceptance_criteria": ["промпты с моделью и прогнозом", "заглушка ответа"] },
{ "id": "T8", "title": "Тесты", "status": "completed", "depends_on": ["T2","T3","T4","T5","T6","T7"], "acceptance_criteria": ["pytest проходит", "покрытие всех модулей"] }
], ],
"last_updated": "2026-10-08T17:10:00Z" "last_updated": "2026-07-22T12:00:00Z"
} }
-210
View File
@@ -1,210 +0,0 @@
# Analysis Report
**Session ID:** `metaagent-005`
**Target repo:** `/home/oqyude/External/Git/nifodea`
**Date:** 2026-10-08
**Project type:** `existing`
**MetaAgent version:** 3.0.0
---
## 1. Общая информация
| Параметр | Значение |
|---|---|
| Название | CashFlow Forecast |
| Назначение | Личная финансовая модель с прогнозом денежных потоков, сценарным анализом, what-if и AI-ассистентом |
| Лицензия | не выбрана (есть файл `LICENSE` с шаблоном, требует ревизии) |
| CI/CD | отсутствует (нет `.github/`, `.gitlab-ci.yml`, `Makefile`) |
| Точка входа | `cli/main.py` → команда `cf` (через `pyproject.toml [project.scripts]`) |
| Система сборки | `pyproject.toml` (setuptools, build-backend=setuptools.build_meta) |
| Версия | 0.1.0 |
## 2. Стек технологий
| Компонент | Значение |
|---|---|
| Язык | Python >= 3.11 (тестировалось на 3.14) |
| CLI-фреймворк | Typer >= 0.9 (через `typer` entry-point) |
| Файлы данных | JSON (через `pathlib` + `json`) |
| Excel I/O | openpyxl >= 3.1 |
| Терминал-вывод | rich >= 13.0 |
| Тесты | pytest 9.x |
| Линтер | ruff 0.16.x (line-length 120, rules E/F/I/N/W) |
| Пакетный менеджер | pip (через `.venv`) |
| UUID-генерация | uuid4 (для ID моделей) |
| Dataclass-сериализация | ручные `to_dict` / `from_dict` |
## 3. Архитектура
**Паттерн:** модульный монолит (5 пакетов, чёткие границы ответственности).
```
┌─────────────────────────────────────────────┐
│ cli/ — Typer CLI (cf init/forecast/...) │
└──────────────────┬──────────────────────────┘
│
┌───────────┼───────────┐
▼ ▼ ▼
┌───────┐ ┌─────────┐ ┌──────┐
│ ai/ │ │ engine/ │ │sync/ │
│prompts│ │forecast │ │excel │
│asst │ │scenario │ │ │
└───┬───┘ └────┬────┘ └──┬───┘
│ │ │
└─────────┬─┴──────────┘
▼
┌────────────────┐
│ cashflow_model │ ← Account, Transaction, Recurring,
│ (dataclasses) │ Asset, Liability, Scenario, Currency
└────────────────┘
```
**Принцип** (из `README.arch.md`):
- Spreadsheet — UI (через `sync/excel_sync.py`)
- Python — вычислительное ядро (`engine/`)
- JSON — внутреннее представление (`cashflow_model/`)
- AI — инструмент анализа (`ai/`, пока stub)
## 4. Структура (depth=2)
```
nifodea/
├── AGENTS.md # MetaAgent context для агента
├── LICENSE # шаблон, не выбрана
├── README.md # инструкции пользователя
├── README.arch.md # архитектурная концепция
├── pyproject.toml # setuptools + deps + entry-point cf
├── .gitignore # python + .temp/ (MetaAgent)
│
├── cashflow_model/ # 7 dataclass-моделей + Currency
│ ├── account.py, transaction.py, recurring.py, asset.py, liability.py
│ ├── scenario.py, currency.py, model.py (root), __init__.py
│
├── engine/ # вычислительное ядро
│ ├── forecast.py (ForecastService)
│ ├── scenarios.py (ScenarioService + what-if)
│
├── sync/ # Excel-импорт/экспорт
│ └── excel_sync.py
│
├── ai/ # AI-ассистент (stub)
│ ├── prompts.py
│ └── assistant.py
│
├── cli/ # Typer CLI
│ ├── main.py (~330 LOC, 8 команд)
│ ├── i18n.py (~350 LOC, ru/en)
│ └── config.py (~428 LOC)
│
├── tests/ # pytest, 9 файлов
│ ├── conftest.py (фикстуры: sample_model, empty_model, sample_converter)
│ └── test_*.py (9 файлов)
│
├── data/ # JSON-модели (runtime)
└── exports/ # экспортированные .xlsx
```
## 5. Ключевые модули и их ответственность
| Модуль | Ответственность | LOC |
|---|---|---|
| `cashflow_model/model.py` | Корневая модель `FinancialModel` (агрегатор + JSON save/load) | 61 |
| `cashflow_model/currency.py` | `CurrencyConverter`, `ExchangeRate`, символы валют | 79 |
| `cashflow_model/*.py` | Датаклассы: Account, Transaction, Recurring, Asset, Liability, Scenario | ~150 |
| `engine/forecast.py` | `ForecastService.forecast_cashflow()` — посуточный/помесячный прогноз | 103 |
| `engine/scenarios.py` | `ScenarioService` (baseline/optimistic/pessimistic) + what-if | 87 |
| `sync/excel_sync.py` | `ExcelSync` — импорт/экспорт `.xlsx` ↔ `FinancialModel` | 135 |
| `ai/prompts.py` | Шаблоны промптов для AI (analyze, advice, scenario_comparison) | 21 |
| `ai/assistant.py` | `AssistantService` — генерирует промпт, но НЕ вызывает API (stub) | 69 |
| `cli/main.py` | Typer-приложение: `cf init/forecast/scenario/whatif/compare/import/export/analyze` | 330 |
| `cli/config.py` | Загрузка/сохранение `FinancialModel` в `data/`, пути по умолчанию | 428 |
| `cli/i18n.py` | `t()`-обёртка, словари `_r()`/`_e()`, ru (default) / en (fallback) | 350 |
**Всего:** ~2479 строк кода + 9 тестовых файлов.
## 6. Конвенции
| Аспект | Соглашение |
|---|---|
| Стиль кода | snake_case (функции/переменные), PascalCase (классы), UPPER_SNAKE (константы) |
| Датаклассы | `@dataclass` + ручные `to_dict` / `from_dict` (без `pydantic`/`attrs`) |
| ID | `uuid.UUID` через `field(default_factory=uuid4)` |
| Суммы | `float` (без `Decimal`, есть риск округления) |
| Даты | ISO-строки `"YYYY-MM-DD"` (без `datetime`) |
| Исключения | Доменные классы: `CurrencyError`, `AssistantError` (наследуют `Exception`) |
| Логирование | `rich.print` для UI; явное логирование не используется |
| Валюты | По умолчанию RUB; поддержка USD, EUR, GBP, CNY, JPY, KZT, UAH |
| CLI-фреймворк | Typer (декораторы `@app.command()`) |
| i18n | Кастомный `t(key, **kwargs)` с fallback на русский |
## 7. Тесты
| Параметр | Значение |
|---|---|
| Раннер | pytest 9.1 |
| Расположение | `tests/test_*.py` |
| Фикстуры | `sample_model`, `empty_model`, `sample_converter` (в `conftest.py`) |
| Покрытие | 9 тестовых модулей: model, currency, forecast, scenarios, excel_sync, ai, cli, i18n |
| Baseline | **63/63 PASSED** (4.64s) |
| Отчёт | `.agent/context/baseline-test-report.log` |
## 8. Сборка / запуск
```bash
# Установка (editable)
.venv/bin/pip install -e .
# С дев-зависимостями (если добавить)
.venv/bin/pip install -e ".[dev]"
# Тесты
.venv/bin/pytest
# Линтер
.venv/bin/python -m ruff check .
# CLI
cf init
cf forecast --months 12
cf scenario baseline
cf compare --months 12
```
## 9. Известные ограничения (MVP)
Из `README.md` и `README.arch.md`:
- **AI-ассистент — заглушка.** `AssistantService.analyze()` возвращает dict с `"ai_response": None`. API не подключён. *Примечание 2026-10-08: пользователь решил, что AI-интеграция не в скоупе — модуль `ai/` остаётся как есть.*
- **Хранилище — JSON-файлы.** Не подходит для многопользовательской работы.
- **Excel — только `.xlsx`** через openpyxl.
- **Лицензия не выбрана.**
- **CI/CD отсутствует.**
- **Нет `FUTURE/`** для долгосрочных планов.
- **Тесты не интеграционные** с реальным Excel-файлом (только in-memory).
## 10. Будущие возможности (из README.arch.md)
- Monte-Carlo Simulation
- FIRE Planning
- Инвестиционный прогноз
- Импорт банковских выписок / брокерских отчётов
- REST API
- Web UI
- Mobile App
- AI Financial Assistant (полная реализация)
## 11. Git-состояние
| Параметр | Значение |
|---|---|
| HEAD | `12611ed metaagent update` |
| Всего коммитов | 8 |
| Незакоммиченные изменения | есть (миграция `.agent/` с v1.1 → v3.0) — задокументировано в `.agent/migration-report.log` |
| Ветка | (не проверено) |
## 12. Что НЕ делает MetaAgent в этом проекте
- Не пишет production-код (по `project-rules.md`).
- Не удаляет файлы.
- Не коммитит в main/master.
-127
View File
@@ -1,127 +0,0 @@
# Project State
**Снимок на момент:** 2026-10-08T17:05 (после METASTATE)
**Project type:** `existing`
**MetaAgent version:** 3.0.0
---
## Что произошло в сессии 2026-10-08
**Goal:** «Обсуждение архитектуры и серьёзный refactor»
Выполнен полный архитектурный рефактор по 5 направлениям:
1. **A1+A10: Слои + version** — `domain/`, `application/`, `infrastructure/`; `FinancialModel.SCHEMA_VERSION=1` с миграционным хуком.
2. **A2+A3: Pydantic v2** — все модели на `BaseModel`, валидаторы, `model_dump`/`model_validate`.
3. **A4: Decimal для денег** — все monetary поля, `CurrencyConverter`, `ForecastService`, `ScenarioService` работают с `Decimal`.
4. **A7+A8+A9: DI + Repository** — `ModelRepository` Protocol, `JsonFileRepository`, `ExcelRepository`; `AssistantService` получает `ForecastService` через DI; `build_services()` — composition root в CLI.
5. **A5: Декомпозиция CLI** — `main.py` (330 LOC) → 9 файлов в `commands/`, `config.py` (428 LOC) → `config_cmd.py` (15 sub-команд).
**Результат:** 67/67 тестов проходят, CLI работает, Excel round-trip сохраняет данные.
## Архитектура (после рефактора)
**Модульный монолит на Python 3.11+** для личного финансового планирования. Три слоя:
```
┌─────────────────────────────────────────────┐
│ domain/ — бизнес-модели │
│ Account, Transaction, Asset, Liability, │
│ Recurring, Scenario, FinancialModel, │
│ ExchangeRate, CurrencyConverter │
│ (pydantic.BaseModel, Decimal) │
└──────────────────┬──────────────────────────┘
│
┌──────────────────▼──────────────────────────┐
│ application/ — прикладные сервисы │
│ ForecastService, ScenarioService, │
│ ModelRepository (Protocol) │
└──────────────────┬──────────────────────────┘
│
┌──────────────────▼──────────────────────────┐
│ infrastructure/ — внешний мир │
│ cli/ (Typer), ai/ (Assistant), │
│ repositories/ (JsonFile, Excel) │
└─────────────────────────────────────────────┘
```
## Tech stack
| Слой | Технология | Версия |
|---|---|---|
| Язык | Python | 3.11+ (тест на 3.14) |
| CLI | Typer | 0.27 |
| Excel | openpyxl | 3.1 |
| Терминал | rich | 15.0 |
| Валидация | pydantic | 2.13 |
| Деньги | Decimal | stdlib |
| Тесты | pytest | 9.1 |
| Линтер | ruff | 0.16 |
## Ключевые модули
| Слой | Модуль | Ответственность |
|---|---|---|
| domain | `account.py` (18 LOC), `transaction.py` (20), `asset.py` (11), `liability.py` (19), `recurring.py` (27), `scenario.py` (20) | pydantic.BaseModel + Decimal + валидаторы |
| domain | `currency.py` (83) | ExchangeRate + CurrencyConverter (Decimal, ROUND_HALF_UP) |
| domain | `model.py` (71) | FinancialModel — корневой агрегатор с SCHEMA_VERSION=1 |
| application | `forecast.py` (115) | ForecastService — Decimal-арифметика, помесячный прогноз |
| application | `scenarios.py` (91) | ScenarioService — baseline/optimistic/pessimistic + what-if |
| application | `repositories/model_repository.py` (20) | Protocol с load()/save() |
| infrastructure | `cli/app.py` (45) | Entry point, регистрирует все команды |
| infrastructure | `cli/commands/*.py` | 9 файлов (init/forecast/scenario/whatif/compare/import_xlsx/export_xlsx/analyze/info) + config_cmd.py |
| infrastructure | `cli/paths.py` (5) | MODEL_PATH, DATA_DIR |
| infrastructure | `cli/services.py` (60) | build_services() — composition root + helpers |
| infrastructure | `cli/i18n.py` (350) | ru/en словари |
| infrastructure | `ai/assistant.py` (79) | AssistantService (заглушка, DI ForecastService) |
| infrastructure | `repositories/json_file_repository.py` (20) | .json storage |
| infrastructure | `repositories/excel_repository.py` (138) | .xlsx storage |
## Статус тестов
| Параметр | Значение |
|---|---|
| Всего тестов | 67 |
| Пройдено | 67 ✅ |
| Упало | 0 |
| Время | 2.4s |
| Тестовых модулей | 10 |
## Что было сделано в сессии
- ✅ Pydantic v2 во всех моделях
- ✅ Decimal для всех денежных полей
- ✅ Слои domain/application/infrastructure
- ✅ Schema versioning (version=1 + legacy v0 support)
- ✅ ModelRepository Protocol + JsonFile + Excel
- ✅ DI через composition root
- ✅ CLI decomposition (main.py 330 LOC → 9 файлов, config.py 428 LOC → config_cmd.py)
- ✅ 67/67 тестов проходят
- ✅ CLI команды работают, Excel round-trip OK
- ✅ README обновлён
## Что отсутствует / TODO
- ❌ **AI-интеграция** — `AssistantService` не вызывает LLM API (отклонено пользователем)
- ❌ **Лицензия** — файл есть, но содержимое — шаблон
- ❌ **CI/CD** — нет `.github/`, нет pre-commit hooks
- ❌ **FUTURE/** — нет директории с долгосрочными планами
- ❌ **mypy** — не настроен
- ❌ **Логирование** — только `rich.print`
## Известные ADR-кандидаты (для следующей сессии)
| ID | Тема |
|---|---|
| ADR-001 | Repository pattern (T4) — формализовать контракт |
| ADR-002 | Слоистая архитектура (T1) — границы domain/application/infrastructure |
| ADR-003 | Schema versioning — политика миграций модели |
## Следующая сессия — что делать
1. **Зафиксировать ADR-001, ADR-002, ADR-003** через `/adr` — закрепить архитектурные решения.
2. **CI/CD** (P1) — добавить `.github/workflows/ci.yml` (pytest + ruff).
3. **Лицензия** (P2) — выбрать MIT/Apache-2.0/BSD-3, обновить `LICENSE`.
4. **mypy** (P1) — добавить `[tool.mypy]` в `pyproject.toml` для strict-проверки.
5. **Новые фичи** (P3) — Monte-Carlo, FIRE, REST API, Web UI, импорт банковских выписок (из `README.arch.md`).
+151
View File
@@ -0,0 +1,151 @@
# Design Report
## Session
- **Session ID:** `metaagent-001`
- **Target repo:** `S:\Git\nifodea`
- **Date:** 2026-07-12
## 1. Технологический стек
| Компонент | Выбор | Обоснование |
|---|---|---|
| Язык | Python 3.11+ | Указан в README как вычислительное ядро; широкая экосистема для работы с данными |
| Фреймворк | Typer (CLI), openpyxl (Excel) | Typer — современный CLI-фреймворк; openpyxl — стандарт для .xlsx |
| База данных | JSON-файлы | README требует JSON как внутреннее представление; для MVP БД не нужна |
| Инфраструктура | pip + venv | Минимальная зависимость; .gitignore уже настроен под Python |
| Линтер | ruff | Стандарт для Python 2024+; быстрый, уже в .gitignore |
| Тесты | pytest | Стандартный тестовый раннер для Python |
| AI | Интерфейс через промпты | Для MVP — только промпты и абстракция, без подключения к API |
## 2. High-Level архитектура
**Паттерн:** Модульный монолит (Layered)
```
[CLI / Excel File]
|
▼
sync/ ──► cashflow_model/ ──► engine/ ──► ai/
(Excel R/W) (Entity Model) (Forecast) (Prompts)
| | |
▼ ▼ ▼
data/model.json data/model.json data/model.json
```
**Поток данных:**
1. Пользователь редактирует Excel → sync читает и преобразует в JSON
2. JSON-модель загружается в Python-объекты (dataclass)
3. Forecast Engine вычисляет прогноз на основе модели
4. AI Assistant анализирует результаты через промпты
5. Результаты экспортируются обратно в Excel
## 3. Модули
| Модуль | Ответственность | Ключевые компоненты | Зависит от |
|---|---|---|---|
| `cashflow_model/` | Определение сущностей (dataclass), сериализация/десериализация JSON | `Account`, `Transaction`, `RecurringCashflow`, `Asset`, `Liability`, `ForecastScenario`, `FinancialModel` | — |
| `sync/` | Чтение и запись Excel (.xlsx), конвертация между Excel и JSON | `excel_sync.py` — импорт/экспорт | `cashflow_model` |
| `engine/` | Расчёт прогноза, сценарный анализ, what-if | `forecast.py` (прогноз), `scenarios.py` (сценарии) | `cashflow_model` |
| `ai/` | Промпты для AI-ассистента, форматирование контекста | `prompts.py` (шаблоны), `assistant.py` (интерфейс) | `cashflow_model`, `engine` |
| `cli/` | CLI-интерфейс (Typer) | `main.py` — точки входа | Все модули |
## 4. Модели данных
### Account
| Поле | Тип | Ограничения | Описание |
|---|---|---|---|
| id | UUID | pk | Уникальный идентификатор |
| name | str | required | Название счёта |
| currency | str | default="USD" | Валюта |
| balance | float | required | Текущий баланс |
### Transaction
| Поле | Тип | Ограничения | Описание |
|---|---|---|---|
| id | UUID | pk | Уникальный идентификатор |
| date | str (ISO date) | required | Дата операции |
| account | UUID | fk → Account | Счёт |
| category | str | required | Категория |
| amount | float | required | Сумма |
| description | str | optional | Описание |
### RecurringCashflow
| Поле | Тип | Ограничения | Описание |
|---|---|---|---|
| id | UUID | pk | Уникальный идентификатор |
| start_date | str (ISO date) | required | Дата начала |
| end_date | str (ISO date) | optional | Дата окончания |
| frequency | str | enum: monthly/weekly/yearly | Периодичность |
| amount | float | required | Сумма |
| category | str | required | Категория |
### Asset
| Поле | Тип | Ограничения | Описание |
|---|---|---|---|
| id | UUID | pk | Уникальный идентификатор |
| name | str | required | Название |
| value | float | required | Текущая стоимость |
| growth_rate | float | default=0.0 | Годовой темп роста (%) |
### Liability
| Поле | Тип | Ограничения | Описание |
|---|---|---|---|
| id | UUID | pk | Уникальный идентификатор |
| name | str | required | Название |
| balance | float | required | Текущий остаток |
| interest | float | required | Годовая ставка (%) |
| payment | float | required | Ежемесячный платёж |
**Связи:**
- Transaction → Account (многие к одному)
- RecurringCashflow → Account (многие к одному, опционально)
- FinancialModel включает все сущности + параметры
## 5. API / Интерфейсы
### CLI (Typer)
| Команда | Описание | Пример |
|---|---|---|
| `import <file.xlsx>` | Импорт данных из Excel в JSON | `cf import data.xlsx` |
| `export <file.xlsx>` | Экспорт из JSON в Excel | `cf export report.xlsx` |
| `forecast [--months 12]` | Запуск прогноза | `cf forecast --months 12` |
| `scenario <name>` | Применить сценарий | `cf scenario optimistic` |
| `analyze` | AI-анализ модели | `cf analyze` |
| `init` | Инициализация пустой модели | `cf init` |
## 6. Обработка ошибок
- **Стратегия:** Исключения Python с кастомными типами (`ModelError`, `SyncError`, `ForecastError`)
- **Формат ошибок:** `{ "error": "<message>", "code": "<CODE>", "details": {} }`
- **Логирование:** logging с уровнями INFO/ERROR; CLI-вывод через Typer + rich
## 7. Тестирование
- **Unit-тесты:** pytest для каждого модуля (cashflow_model, engine, sync)
- **Integration-тесты:** чтение/запись Excel, полный цикл import → forecast → export
- **Mock-стратегия:** временные файлы для Excel/JSON тестов
- **Команда запуска:** `pytest`
## 8. Предварительная группировка задач
| Задача | Описание | Тип |
|---|---|---|
| T1 | Инициализация проекта + scaffold | config |
| T2 | Модель данных (dataclass + JSON serialization) | feature |
| T3 | Forecast Engine (базовый прогноз) | feature |
| T4 | Excel Sync (import/export) | feature |
| T5 | CLI (Typer) — все команды | feature |
| T6 | AI Assistant (промпты + интерфейс) | feature |
| T7 | Тесты на все модули | test |
| T8 | Финальная проверка и документация | docs |
## 9. Примечания
Для MVP берётся минимальный функционал: модель + forecast + excel sync + cli. AI — только интерфейс (заглушка с промптами). Сценарии — базовая реализация.
+84 -86
View File
@@ -1,109 +1,107 @@
# Handoff Summary # Handoff Summary
**Session:** `metaagent-005` ## Session Info
**Goal:** Обсуждение архитектуры и серьёзный refactor
**Date:** 2026-10-08
**MetaAgent version:** 3.0.0
--- - **Session ID:** `metaagent-002`
- **Target Repo:** `S:\Git\nifodea`
- **Goal:** Обновление metaagent-артефактов до v1.1.0, валидация существующего кода и окружения
- **Date:** 2026-07-22
- **Depth:** 4 (Light)
- **Config:** depth=4, design=skipped (existing), red_team=no, risk_register=no, invariant_tests=no, layer_structure=no
## Session Summary ## Repo Summary
| Метрика | Значение | CashFlow Forecast — личная финансовая модель на Python. Модульный монолит: cashflow_model (dataclass), engine (forecast + scenarios), sync (Excel), ai (заглушка), cli (Typer). 26 тестов, ruff lint чист.
## Project Type
- **Type:** existing
- **Design report:** —
## Environment Status
- **Build:** OK
- **Tests:** 26/26 passed
- **Linter:** ruff — all checks passed
- **Dependencies:** установлены (openpyxl, typer, rich)
## Task Overview
| Status | Count |
|---|---| |---|---|
| Выполнено задач | 7/7 ✅ | | Total | 8 |
| Pending | 0 | | Pending | 0 |
| Approved requests | req-T1 … req-T7 (все в `.agent/archive/requests/`) | | In Progress | 0 |
| Коммитов | 6 (feb77ef, c765f36, 363d440, 541a768, 3ef1061, плюс 1 для T4/T6 — см. `git log`) | | Completed | 8 |
| Тестов до | 63 | | Failed/Skipped | 0 |
| Тестов после | 67 (+5 для репозиториев) |
## Что сделано **Task by type:**
- config: 1
- feature: 6
- test: 1
Полный архитектурный рефактор проекта `cashflow-forecast` (Python 3.11+, Typer CLI): ## Tasks (ordered)
| # | Задача | Что | ### T1: Инициализация проекта и зависимостей
|---|---|---| - Type: config
| T1 | Слои + version | `domain/`, `application/`, `infrastructure/`; `FinancialModel.SCHEMA_VERSION=1` | - Depends on: —
| T2 | Pydantic v2 | Все модели — `pydantic.BaseModel`, валидаторы | - Files: pyproject.toml, cashflow_model/__init__.py, sync/__init__.py, engine/__init__.py, ai/__init__.py, cli/__init__.py, data/.gitkeep, exports/.gitkeep
| T3 | Decimal | Все monetary поля, `CurrencyConverter`, `ForecastService`, `ScenarioService` | - Status: completed
| T4 | Repository | `ModelRepository` Protocol, `JsonFileRepository`, `ExcelRepository` |
| T5 | DI | `build_services()` — composition root, `AssistantService` принимает `ForecastService` |
| T6 | CLI decompose | `main.py` 330 LOC → 9 файлов, `config.py` 428 LOC → `config_cmd.py` |
| T7 | Final | 67/67 тестов, README обновлён, Excel round-trip OK |
## Project State ### T2: Модель данных (dataclass + JSON serialization)
- Type: feature
- Depends on: T1
- Files: cashflow_model/__init__.py, cashflow_model/account.py, cashflow_model/transaction.py, cashflow_model/recurring.py, cashflow_model/asset.py, cashflow_model/liability.py, cashflow_model/scenario.py, cashflow_model/model.py
- Status: completed
**Архитектура:** трёхслойный модульный монолит (Clean Architecture). ### T3: Forecast Engine (базовый прогноз)
- Type: feature
- Depends on: T2
- Files: engine/__init__.py, engine/forecast.py
- Status: completed
**Стек:** Python 3.11+, pydantic 2.13, openpyxl 3.1, typer 0.27, rich 15, pytest 9.1. ### T4: Scenario Analysis
- Type: feature
- Depends on: T3
- Files: engine/__init__.py, engine/scenarios.py
- Status: completed
**Тесты:** 67/67 ✅ (2.4s). ### T5: Excel Sync (import/export)
- Type: feature
- Depends on: T2
- Files: sync/__init__.py, sync/excel_sync.py
- Status: completed
**Известные ограничения:** AI stub (отклонено пользователем), нет CI/CD, нет лицензии, нет mypy, нет логирования. ### T6: CLI (Typer) — все команды
- Type: feature
- Depends on: T2, T3, T4, T5, T7
- Files: cli/__init__.py, cli/main.py, pyproject.toml
- Status: completed
## Key Artifacts ### T7: AI Assistant (промпты + интерфейс)
- Type: feature
- Depends on: T3
- Files: ai/__init__.py, ai/prompts.py, ai/assistant.py
- Status: completed
- **Project state:** `.agent/context/project-state.md` — текущее состояние ### T8: Тесты на все модули
- **Tasks:** `.agent/tasks/manifest.json` — все задачи archived - Type: test
- **Archive tasks:** `.agent/archive/tasks/T1.json` … `T7.json` — полные описания - Depends on: T2, T3, T4, T5, T6, T7
- **Archive requests:** `.agent/archive/requests/req-T1.json` … `req-T7.json` — все approved - Files: tests/test_model.py, tests/test_forecast.py, tests/test_scenarios.py, tests/test_excel_sync.py, tests/test_cli.py, tests/test_ai.py, tests/conftest.py
- **Roadmap:** `.agent/roadmap/sources.md` — следующие шаги - Status: completed
- **Archive index:** `.agent/archive/index.json`
## Next Steps (для следующей сессии) ## Next Steps
### P0 — Кандидаты на ADR (через `/adr`) Все 8 задач выполнены. Проект готов к использованию.
1. **ADR-001: Repository pattern** — формализовать `ModelRepository` Protocol ## Caveats
2. **ADR-002: Слоистая архитектура** — границы `domain/application/infrastructure`
3. **ADR-003: Schema versioning** — политика миграций `FinancialModel`
### P1 — Качество и инфраструктура - AI-ассистент — заглушка (промпты готовы, API не подключено)
- База данных — JSON-файлы (не подходит для многопользовательской работы)
- Лицензия не выбрана
- CI/CD не настроен
- **CI/CD:** `.github/workflows/ci.yml` (pytest + ruff) ## Checkpoints
- **mypy:** strict-проверка в `pyproject.toml`
- **pre-commit:** hooks для линтинга/форматирования
### P2 — Полировка Файл: `.agent/checkpoints.json`
Актуальное состояние чекпоинтов прилагается.
- **Лицензия:** выбрать MIT/Apache-2.0/BSD-3, обновить `LICENSE`
- **Логирование:** `rich.print` → `logging` для домена
### P3 — Долгосрочно (не в этой сессии)
- Monte-Carlo Simulation, FIRE Planning, REST API, Web UI, Mobile
- Импорт банковских выписок / брокерских отчётов
## Ключевые точки входа в код
| Что | Где |
|---|---|
| CLI entry | `infrastructure/cli/app.py` |
| Composition root | `infrastructure/cli/services.py:build_services` |
| Корневая модель | `domain/model.py:FinancialModel` |
| Прогноз | `application/forecast.py:ForecastService` |
| Сценарии | `application/scenarios.py:ScenarioService` |
| AI (stub) | `infrastructure/ai/assistant.py:AssistantService` |
| JSON storage | `infrastructure/repositories/json_file_repository.py` |
| Excel storage | `infrastructure/repositories/excel_repository.py` |
## Полезные команды
```bash
# Тесты
pytest
# CLI
cf init
cf forecast --months 12
cf scenario baseline
cf compare --months 12
cf info
cf config account-add --name "Main" --balance 5000
cf import-xlsx data.xlsx
cf export-xlsx exports/report.xlsx
# Git
git log --oneline -10
```
+22
View File
@@ -0,0 +1,22 @@
# MetaAgent Request
# Auto-generated from existing checkpoints.json on 2026-07-22
## Параметры сессии
| Функция | Вкл | Аргументы |
|---|---|---|
| ANALYSIS | ✓ | — |
| DESIGN | ✗ | project_type=existing |
| RED_TEAM | ✗ | — |
| RISK_REGISTER | ✗ | — |
| DECOMPOSITION | ✓ | invariant_tests=false |
| SETUP | ✓ | — |
| HANDOFF | ✓ | layer_structure=false |
## Глубина проработки
**Значение:** 4 (Light)
## Цель
Обновление metaagent-артефактов до v1.1.0, валидация существующего кода и окружения
-121
View File
@@ -1,121 +0,0 @@
# Roadmap Sources
**Дата:** 2026-10-08
**Goal:** Обсуждение архитектуры и серьёзный refactor
**Project type:** `existing`
---
## FUTURE Plans
❌ Директория `FUTURE/` отсутствует.
Долгосрочные планы в `README.arch.md` (раздел "Будущие возможности"). После сессии 2026-10-08 (обсуждение архитектуры) пользователь **исключил** из roadmap:
- ❌ **AI Financial Assistant** (полная реализация) — нет смысла сейчас (`user:direct`)
- ❌ **AI-интеграция** (R-001) — отложено
Остальные долгосрочные планы (тоже не в этой сессии):
- Monte-Carlo Simulation
- FIRE Planning
- Инвестиционный прогноз
- Импорт банковских выписок / брокерских отчётов
- REST API
- Web UI
- Mobile App
Эти направления — **не основной фокус текущей сессии** (цель — refactor, не новые фичи).
## ADR-Derived Tasks
❌ `.agent/decisions/index.json` отсутствует — ADR-ов ещё нет.
## User Requests
| Запрос | Приоритет | Источник |
|--------|-----------|----------|
| Обсуждение архитектуры + серьёзный refactor | **P0** | `user:direct` (current session) |
## Agent-Identified Improvements (из ANALYSE)
Эти проблемы выявлены в `analysis-report.md` / `project-state.md` и требуют архитектурного обсуждения.
### Архитектурные проблемы (кандидаты на рефактор)
| ID | Проблема | Серьёзность | Затронутые слои |
|---|---|---|---|
| **A1** | **Слои не выделены явно.** `engine/` импортирует `cashflow_model/`, `cli/` импортирует всё. Нет разделения domain / application / infrastructure. | высокая | все пакеты |
| **A2** | **Ручная сериализация** (`to_dict` / `from_dict`) в каждой модели. 7 моделей × 2 метода = 14 boilerplate-методов. | высокая | `cashflow_model/` |
| **A3** | **Dataclass vs pydantic** — нет валидации при загрузке JSON, дублирование правил между моделями и Excel-sync. | высокая | `cashflow_model/`, `sync/` |
| **A4** | **`float` для денег** — потеря точности при больших суммах. `Decimal` нужен для финансовых расчётов. | средняя | `cashflow_model/`, `engine/`, `sync/` |
| **A5** | **CLI-файлы разрослись** — `cli/main.py` 330 LOC, `cli/config.py` 428 LOC. Слишком много в одном файле. | средняя | `cli/` |
| **A6** | **i18n — строки разбросаны** по `_r()`-вызовам в `cli/i18n.py`. Нет единого механизма для engine/sync. | низкая | `cli/`, частично `engine/`, `sync/` |
| **A7** | **Нет dependency injection** — `ForecastService` создаётся внутри `AssistantService.analyze()`. Тяжело тестировать. | средняя | `ai/`, `engine/` |
| **A8** | **Сервисы не абстрагированы** — `ExcelSync` — конкретный класс, нет интерфейса для других storage. | средняя | `sync/`, `cashflow_model/` |
| **A9** | **Нет репозиториев** — `FinancialModel.save/load` напрямую работает с файлом. Не расширяется (БД, S3, etc.). | средняя | `cashflow_model/` |
| **A10** | **Нет версионирования модели** — `model.json` без `version` поля. Миграции схемы невозможны. | высокая | `cashflow_model/model.py` |
### Технический долг
| ID | Что | Из `project-state.md` |
|---|---|---|
| T1 | Нет CI/CD | R-003 |
| T2 | Лицензия не выбрана | R-004 |
| T3 | mypy не настроен | R-005 |
| T4 | Нет логирования | — |
| T5 | Нет pre-commit hooks | — |
## Consolidated Priority Queue
### P0 — Архитектурный рефактор (цель сессии)
Кандидаты на обсуждение (выбрать 1-3 направления):
1. **A1+A10: Введение явных слоёв + версионирование модели**
- Выделить domain (модели), application (сервисы), infrastructure (CLI, Excel-sync, AI)
- Добавить `version: 1` в `FinancialModel.to_dict()`
- Подготовить инфраструктуру миграций схемы
2. **A2+A3: Pydantic-миграция**
- Заменить `@dataclass` на `BaseModel`
- Убрать ручные `to_dict` / `from_dict` (pydantic делает сам)
- Добавить валидацию при загрузке JSON
- ⚠️ Может потребовать `pydantic>=2.0` (новая зависимость)
3. **A4: Decimal для денег**
- Мигрировать `amount`, `balance`, `value`, `rate` с `float` на `Decimal`
- Обновить прогноз, Excel-sync, форматтеры
- ⚠️ Большой рефактор: ~10 файлов, 50+ полей
4. **A5: Декомпозиция CLI**
- `cli/main.py` → `cli/commands/init.py`, `cli/commands/forecast.py`, ...
- `cli/config.py` → `cli/paths.py` + `cli/services.py`
- Улучшает читаемость, не меняет поведение
5. **A7+A8+A9: DI + Repository pattern + абстракции**
- Ввести `ForecastRepository`, `ExcelRepository`
- Передавать зависимости в сервисы через конструктор
- Упрощает тестирование, подготовка к БД/API
### P1 — Качество и инфраструктура
6. T1: GitHub Actions CI (pytest + ruff)
7. T3: mypy в строгом режиме
8. T4: заменить `rich.print` на `logging` для домена
### P2 — Полировка
9. T2: выбрать лицензию
10. T5: pre-commit hooks
### P3 — Долгосрочно (не в этой сессии)
- Monte-Carlo, FIRE, REST API, Web UI, Mobile — из `README.arch.md`
- ~~AI-интеграция (R-001)~~ — **отклонено пользователем 2026-10-08**
## Следующие шаги
→ **DECOMPOSITION** с выбранным направлением рефактора.
→ Пользователь должен выбрать 1-3 направления из P0-списка.
→ Если ни одно не подходит — описать желаемый результат.
-57
View File
@@ -1,57 +0,0 @@
# Session Summary
**Session:** `metaagent-005`
**MetaAgent version:** 3.0.0
**Date:** 2026-10-08
**Goal:** Обсуждение архитектуры и серьёзный refactor
## Phases Executed
- [x] INIT
- [x] ANALYSE
- [x] ROADMAP
- [ ] DESIGN (skipped — existing project)
- [x] DECOMPOSITION
- [x] EXECUTION (7 tasks)
- [x] METASTATE
- [x] HANDOFF
## Results
- **Tasks completed:** 7/7 (T1–T7, все archived)
- **Requests approved:** 7 (req-T1 … req-T7, в `.agent/archive/requests/`)
- **Commits:** 6 production commits + 1 README
- `feb77ef` T1: restructure to domain/application/infrastructure + version=1
- `c765f36` T2: Pydantic v2
- `363d440` T3: Decimal
- `<T4>` T4: Repository pattern
- `541a768` T5: DI
- `<T6>` T6: CLI decompose
- `3ef1061` T7: Final validation + README
- **Tests:** 67/67 ✅ (было 63, +5 для репозиториев)
- **CLI:** все команды работают, Excel round-trip OK
## Архитектурный рефактор (5 направлений)
| ID | Что | Задача |
|---|---|---|
| A1+A10 | Слои + version | T1 |
| A2+A3 | Pydantic v2 | T2 |
| A4 | Decimal для денег | T3 |
| A7+A8+A9 | DI + Repository | T4, T5 |
| A5 | Декомпозиция CLI | T6 |
## Files Changed
- `domain/` (new, 8 файлов)
- `application/` (new, 3 файла + `repositories/model_repository.py`)
- `infrastructure/` (new: `cli/{app,paths,services,i18n}.py`, `cli/commands/{10 файлов}`, `ai/`, `repositories/{json,excel}_repository.py`)
- Удалены: `cashflow_model/`, `engine/`, `cli/`, `sync/`, `ai/` (старые имена)
- `tests/` (обновлены + `test_repositories.py` new)
- `pyproject.toml` (pydantic dep, новые entry-points, packages.find)
- `README.md` (полная перезапись под новую архитектуру)
## Next
Следующий агент: читай `.agent/handoff-summary.md`.
Кандидаты: ADR-001 (Repository), ADR-002 (слои), ADR-003 (schema versioning), CI/CD, mypy, лицензия.
+20 -26
View File
@@ -1,45 +1,39 @@
# BOUNDARIES — Рамки и границы # BOUNDARIES — Рамки и границы
Что агенту **разрешено**, **запрещено** и в каких случаях **нужно остановиться**. Что мета-агенту **разрешено**, **запрещено** и в каких случаях **нужно остановиться**.
## Разрешено ## Разрешено
| Действие | Примечание | | Действие | Примечание |
|---|---| |---|---|
| Читать любые файлы в целевом репозитории | Включая `.git`, конфиги, историю | | Читать любые файлы в целевом репозитории | Все файлы, включая .git, конфиги, историю |
| Создавать/изменять файлы в `.agent/` | Директория метаданных проекта (rules, decisions, tasks, context, requests, roadmap, archive) | | Создавать/изменять файлы в `.agent/` | Единственная директория для артефактов |
| Создавать `.temp/` в корне проекта | Для временных файлов агента. Всегда в `.gitignore` | | Устанавливать/обновлять зависимости | Только через штатный пакетный менеджер проекта |
| Писать production-код | В фазе EXECUTION, по задачам из `manifest.json` | | Изменять конфигурационные файлы | Только если это необходимо для сборки/тестов (например, добавить requirements.txt) |
| Рефакторить существующий код | Только если это часть задачи в `manifest.json` | | Запускать сборку и тесты | Для верификации окружения |
| Делать коммиты | По завершении задачи, перед созданием request |
| Создавать/дополнять `.gitignore` | Только для добавления `.temp/` |
| Устанавливать/обновлять зависимости | Через штатный пакетный менеджер проекта |
| Изменять конфигурационные файлы | Только если необходимо для сборки/тестов |
| Запускать сборку и тесты | Для верификации окружения и проверки request-ов |
| Читать документацию, issue, PRs | Для понимания контекста | | Читать документацию, issue, PRs | Для понимания контекста |
| Запрашивать уточнения у пользователя | Если не хватает информации для декомпозиции | | Запрашивать уточнения у пользователя | Если не хватает информации для декомпозиции |
| Копировать исходники MetaAgent в `.agent/src/` целевого проекта | На фазе INIT, без перезаписи существующих файлов (если не указан `--update`) | | Копировать исходники MetaAgent в `.agent/src/` целевого проекта | Только на фазе INIT, без перезаписи существующих файлов |
| Создавать/обновлять `AGENTS.md` в корне целевого проекта | Только если файла не существует | | Создавать/обновлять `AGENTS.md` в корне целевого проекта | Только если файла не существует |
| **Обязательно:** читать `.agent/rules/project-rules.md` перед каждой фазой | Правила пользователя имеют приоритет выше стандартных протоколов | | **Обязательно:** читать `.agent/rules/project-rules.md` перед каждой фазой | Исполнение правил пользователя — приоритет выше стандартных протоколов |
| Перемещать завершённые артефакты в `.agent/archive/` | На фазах METASTATE и HANDOFF | | Перемещать завершённые артефакты в `.agent/archive/` | Только на фазе HANDOFF, только для completed/failed артефактов |
| **Обязательно:** после выполнения задачи создавать request в `.agent/requests/active/` | Request — единица результата |
| Вызывать команды из `COMMANDS/` | По явной просьбе пользователя (`/adr`, `/red-team`, `/risk-register`, `/alt-arch`, `/invariant-tests`) |
## Запрещено ## Запрещено
| Действие | Почему | | Действие | Почему |
|---|---| |---|---|
| Удалять файлы | Если файл мешает — сообщить пользователю | | Писать production-код | Это работа исполнительного агента |
| Рефакторить существующий код | Мета-агент не меняет логику |
| Удалять файлы | Если файл мешает — нужно сообщить пользователю |
| Коммитить в main/master | Коммиты делает исполнительный агент по задачам |
| Менять удалённые настройки CI/CD | Если CI сломан — сообщить пользователю | | Менять удалённые настройки CI/CD | Если CI сломан — сообщить пользователю |
| Модифицировать код, не связанный с задачей | Только то, что нужно в рамках задачи из `manifest.json` | | Пул-реквесты | Исполнительный агент создаёт PR после выполнения задач |
| Выполнять команды (`/adr`, `/red-team`, и т.д.) без явной просьбы | Команды — on-demand, не авто-фаза | | Модифицировать код, не связанный с задачей | Только то, что нужно для окружения |
| Задавать пользователю вопросы про depth / scale / фичи | В v3.0 нет шкалы глубины. Просто работай |
## Когда остановиться ## Когда остановиться
1. **Репозиторий не собирается** — сообщить пользователю с логом ошибки, не продолжать. 1. **Репозиторий не собирается** — сообщить пользователю с логом ошибки, не продолжать
2. **Неясна цель** — запросить уточнение, не гадать. 2. **Неясна цель** — запросить уточнение, не гадать
3. **Обнаружены секреты/токены** — не копировать, сообщить пользователю. 3. **Обнаружены секреты/токены** — не копировать, сообщить пользователю
4. **Цель выходит за рамки одной сессии** — разбить, запросить приоритет. 4. **Цель выходит за рамки одной сессии** — разбить, запросить приоритет
5. **Проект не использует известные технологии** — запросить инструкцию по сборке. 5. **Проект не использует известные технолологии** — запросить у пользователя инструкцию по сборке
6. **Непонятно, какую команду вызвать** — спросить пользователя, не угадывать.
-87
View File
@@ -1,87 +0,0 @@
# Changelog
## 3.0.0 — Упрощение модели
**Дата:** 2026-10-08
### Что изменилось
Принята модель «жизненный цикл + команды на вызов» вместо «жизненный цикл с уровнями глубины».
**Удалено:**
- Шкала глубины (depth 1-10) и все её варианты (Scaffold/Light/Standard/Deep/Maximum).
- Условные фичи в фазах: `adr`, `alternative_arch`, `red_team`, `risk_register`, `invariant_tests`.
- Интервью с пользователем на старте (5 вопросов про depth и фичи).
- `.agent/metaagent-request.md` — конфиг-файл, который сейчас не нужен.
- `TEMPLATES/metaagent-request.md`.
**Добавлено:**
- Директория `COMMANDS/` с пятью on-demand инструкциями: `adr.md`, `red-team.md`, `risk-register.md`, `alt-arch.md`, `invariant-tests.md`.
- `GUIDE.md` — заменяет `META_AGENT_GUIDE.md`, описание цикла + список команд.
- `CHANGELOG.md` — этот файл.
**Переименовано / перенумеровано:**
- `META_AGENT_GUIDE.md` → `GUIDE.md`.
- `PROTOCOLS/01_ANALYSIS.md` → `01_ANALYSE.md`.
- `PROTOCOLS/02_DESIGN.md` → `03_DESIGN.md`.
- `PROTOCOLS/03_DECOMPOSITION.md` → `04_DECOMPOSITION.md`.
- `PROTOCOLS/04_EXECUTION.md` → `05_EXECUTION.md`.
- `PROTOCOLS/05_HANDOFF.md` → `07_HANDOFF.md`.
- `PROTOCOLS/06_METASTATE.md` остался под тем же именем (теперь фаза 6).
**Удалены протоколы:**
- `PROTOCOLS/00_CONFIG.md` — конфигурация больше не нужна.
- `PROTOCOLS/00_MIGRATE.md` — миграция теперь документируется в этом CHANGELOG.
- `PROTOCOLS/04_ENVIRONMENT_SETUP.md` — поглощён фазой `00_INIT.md`.
- `PROTOCOLS/02b_REDTEAM.md` — теперь команда `COMMANDS/red-team.md`.
**Структура `.agent/checkpoints.json`** упрощена: убраны `config.depth`, `config.design.adr`, `config.red_team`, `config.risk_register`, `config.decomposition.invariant_tests`.
### Миграция с v2.1 → v3.0
Для проектов, созданных с MetaAgent v2.1:
1. **Удалить** из `.agent/checkpoints.json` секцию `config` целиком (она больше не читается).
2. **Удалить** `.agent/metaagent-request.md` (не используется).
3. **Удалить** `.agent/decisions/config.json`, если есть (аналог config для решений).
4. **Запустить** `install.sh --update` (или `install.ps1 -Update` / `install.bat --update`) — перезапишет исходники MetaAgent.
5. **Переименовать** пути в существующих артефактах: `layer-1/adr/` → `decisions/` (если остались с v1.x), `layer-2/analysis-report.md` → `context/analysis-report.md` и т.п. — это касается только проектов, оставшихся на v1.x.
6. **Записать** в `.agent/checkpoints.json` новое значение `metaagent_version: "3.0.0"`.
`request.json`, `manifest.json`, `decisions/index.json` остаются в том же формате, что в v2.1.
### Экономия
| | v2.1 | v3.0 |
|---|---|---|
| Markdown строк всего | ~3 820 | ~1 800 (целевой) |
| Протоколов | 10 | 8 |
| Уровней конфигурации | 5 (depth) | 0 |
---
## 2.1.0 — Project Loop + Work Loop + Requests
**Дата:** 2025-08 (предыдущая версия)
- Введён двухконтурный жизненный цикл: Project Loop (однократно) + Work Loop (циклически).
- Добавлены фазы: ROADMAP, METASTATE, RED_TEAM.
- Введены `requests/` как единица результата выполненной задачи.
- Введён `metaagent-request.md` с конфигом сессии (depth scale, фичи).
- Введена структура `.agent/` с семантическими директориями: `decisions/`, `tasks/`, `context/`, `rules/`, `requests/`, `roadmap/`, `archive/`.
- Шкала глубины 1-10 с условными фичами (adr, alternative_arch, red_team, risk_register, invariant_tests).
## 2.0.0 — Реструктуризация `.agent/`
- Переход от слоистой структуры `layer-0..3` к семантическим директориям.
- Полный MIGRATE-протокол для апгрейда с v1.x.
## 1.1.0 — Добавлены rules, archive
- `PROTOCOLS/01_ANALYSIS.md` обзавёлся правилами из `.agent/rules/`.
- Добавлена директория `archive/`.
## 1.0.0 — Первый релиз
- Односессионный pipeline: INIT → ANALYSE → DECOMP → SETUP → HANDOFF.
- Структура `layer-0..3`.
-95
View File
@@ -1,95 +0,0 @@
# ADR — Architecture Decision Record
## Назначение
Зафиксировать архитектурное решение в `.agent/decisions/NNN-slug.md` так, чтобы будущий агент (или человек) мог понять: что решили, почему, какие альтернативы рассматривали, какие последствия.
ADR создаются по явной команде пользователя: «запиши это как решение», «/adr», «сделай ADR для текущего подхода».
## Когда вызывать
- Принято неочевидное архитектурное решение (выбор БД, паттерна, библиотеки, структуры модулей).
- Решение может измениться в будущем — стоит зафиксировать контекст.
- Есть trade-off, который нужно объяснить следующему агенту.
Не вызывать для очевидных вещей: «используем pytest», «классы называем в PascalCase».
## Вход
- Контекст решения: что обсуждалось, какие варианты сравнивались, что выбрали.
- `.agent/decisions/index.json` — текущий список ADR (для нумерации).
- `.agent/context/project-state.md` — текущее состояние проекта.
## Шаги
### 1. Определить номер
Прочитать `.agent/decisions/index.json`. Следующий номер = max существующих + 1. Если файла нет — создать, начать с 001.
### 2. Slug
Короткое имя в kebab-case, отражающее суть: `use-sqlite-for-mvp`, `auth-via-jwt-cookies`, `modular-monolith`.
### 3. Записать ADR
Создать `.agent/decisions/{NNN}-{slug}.md` по шаблону `TEMPLATES/adr-NNNN.md`:
```markdown
# {NNN}. {Заголовок}
**Дата:** {YYYY-MM-DD}
**Статус:** Accepted | Superseded by {NNN} | Deprecated
## Контекст
{Что за проблема. Какие ограничения. Что нужно было решить.}
## Решение
{Что выбрали. Коротко и конкретно.}
## Альтернативы, которые рассмотрели
### {Альтернатива 1}
{Описание. Почему не выбрали.}
### {Альтернатива 2}
{Описание. Почему не выбрали.}
## Последствия
### Положительные
- {что становится лучше}
### Отрицательные
- {что становится хуже или сложнее}
### Инварианты
- {что не должно сломаться, чтобы решение оставалось валидным}
```
### 4. Обновить index.json
```json
{
"version": "3.0.0",
"decisions": [
{ "id": "001", "title": "Использовать SQLite для MVP", "file": "001-use-sqlite-for-mvp.md", "status": "Accepted" }
],
"last_updated": "{timestamp}"
}
```
### 5. Если есть supersession
Если новый ADR отменяет старый — в старом ADR поставить `Статус: Superseded by {NNN}` и добавить ссылку. В новом — в контексте упомянуть, что отменяет.
## Выход
- `.agent/decisions/{NNN}-{slug}.md`
- Обновлённый `.agent/decisions/index.json`
## Связанные команды
- **/invariant-tests** — после ADR можно зафиксировать инварианты как задачи в manifest.
- **/alt-arch** — если хочется явно зафиксировать альтернативу до решения.
-85
View File
@@ -1,85 +0,0 @@
# Alternative Architecture
## Назначение
Описать альтернативный вариант архитектуры / подхода, чтобы сравнить с текущим и принять осознанное решение. Не «сделать вместо», а «сравнить и выбрать».
## Когда вызывать
- Текущий дизайн кажется спорным, нужна трезвая оценка альтернативы.
- Хочется зафиксировать «почему не сделали иначе» — потом пригодится при росте.
- Перед крупным решением (выбор БД, монолит-vs-микросервисы, sync-vs-async).
## Вход
- Текущий дизайн / план (`.agent/context/design-report.md` или текущее состояние).
- Ограничения проекта (сроки, стек, бюджет).
## Шаги
### 1. Определить, что сравниваем
Один конкретный вопрос: «SQLite vs PostgreSQL», «монолит vs микросервисы», «REST vs GraphQL», «sync-обработка vs очередь».
### 2. Сформулировать альтернативу
Краткое описание: что предлагается вместо текущего подхода. Без длинного дизайна — на уровне «как это работает и чем отличается».
### 3. Сравнить
| Аспект | Текущий | Альтернатива |
|---|---|---|
| Сложность реализации | | |
| Время до MVP | | |
| Производительность | | |
| Масштабирование | | |
| Поддерживаемость | | |
| Стоимость изменений | | |
| Риски | | |
### 4. Записать
Создать `.agent/context/alt-architecture.md` (если файла нет) или дополнить. Структура:
```markdown
# Alternative Architecture — {что сравниваем}
**Дата:** {YYYY-MM-DD}
## Контекст
{Почему рассматриваем альтернативу. Что не устраивает в текущем.}
## Альтернатива
{Краткое описание. Архитектура, ключевые компоненты, поток данных.}
## Сравнение
{Таблица из шага 3.}
## Когда альтернатива выигрывает
{В каких условиях стоит переключиться. Триггеры для миграции.}
## Когда остаёмся на текущем
{Что в текущем работает достаточно хорошо, чтобы не менять.}
## Рекомендация
{Остаёмся или мигрируем. Почему.}
```
### 5. Связать с ADR
Если после сравнения принимается решение — использовать **/adr** для фиксации. Альтернативный файл остаётся как исторический артефакт.
## Выход
- `.agent/context/alt-architecture.md`
## Связанные команды
- **/adr** — зафиксировать итоговое решение.
- **/risk-register** — если альтернатива снимает/добавляет риски.
-68
View File
@@ -1,68 +0,0 @@
# Invariant Tests
## Назначение
Превратить инварианты из ADR в задачи-тесты в `.agent/tasks/manifest.json`. Инвариант — это «что не должно сломаться, чтобы ADR оставался валидным». Без явного теста это просто слова.
## Когда вызывать
- После создания ADR, в секции «Инварианты» которого перечислены условия валидности решения.
- Когда хочется, чтобы архитектурные решения были защищены регрессионными тестами.
## Вход
- `.agent/decisions/*.md` — ADR с секцией «Инварианты».
- `.agent/tasks/manifest.json` — текущий манифест (для нумерации задач).
## Шаги
### 1. Найти ADR с инвариантами
Прочитать все `.agent/decisions/*.md`, найти секции «Инварианты».
### 2. Для каждого инварианта — задача
Каждый инвариант = одна задача-тест. Формат:
```json
{
"id": "T-INV-001",
"title": "Invariant: auth-сессия не переживает рестарт сервиса",
"type": "test",
"origin": "invariant:001",
"depends_on": [],
"acceptance_criteria": [
"Тест рестартит auth-сервис и проверяет, что все сессии инвалидированы",
"Тест проверяет, что refresh-токен не работает после рестарта"
],
"files": [
"tests/auth/test_invariants.py"
]
}
```
### 3. Добавить в manifest
Записать задачи в `.agent/tasks/manifest.json` с `status: "pending"`. Связать `depends_on` с задачами, которые реализуют компонент (если ещё не выполнены).
### 4. Связать с ADR
В самом ADR добавить (опционально) ссылку на задачу-инвариант:
```markdown
## Инварианты
- {{ ... }}
### Покрытие тестами
- T-INV-001: ...
```
## Выход
- Новые задачи в `.agent/tasks/manifest.json` с `origin: "invariant:{adr_id}"`
- (опционально) обновлённый ADR со ссылкой на задачи
## Связанные команды
- **/adr** — источник инвариантов.
- **/risk-register** — некоторые инварианты рождаются из рисков.
-104
View File
@@ -1,104 +0,0 @@
# Red Team Review
## Назначение
Попытаться сломать текущий дизайн / архитектуру / план. Зафиксировать найденные уязвимости в `.agent/context/red-team-report.md`, чтобы разработчик мог их закрыть до реализации.
Red Team — это adversarial-проход по дизайну. Не «улучшить», а «найти, что не так».
## Когда вызывать
- После фазы DESIGN, до декомпозиции задач.
- Когда дизайн кажется слишком гладким.
- Перед крупным рефакторингом.
- Когда непонятно, какие риски у текущего подхода.
## Вход
- `.agent/context/design-report.md` (если есть).
- `.agent/decisions/*.md` — связанные ADR.
- `.agent/context/project-state.md` — текущее состояние.
## Шаги
### 1. Прочитать целевой дизайн
Понять, что именно ревьюится: вся архитектура, конкретный модуль, конкретное решение.
### 2. Провести атаки по категориям
#### 2.1. Нагрузка и масштабирование
- Что будет при 10x / 100x объёма?
- Где узкое место?
- Что сломается первым?
#### 2.2. Отказы и доступность
- Что если упадёт БД / кэш / внешний сервис?
- Есть ли SPOF (single point of failure)?
- Как восстанавливаемся?
#### 2.3. Безопасность
- Где хранятся секреты?
- Какие поверхности атаки?
- Что с аутентификацией / авторизацией?
- Injection, SSRF, XSS — что релевантно?
#### 2.4. Корректность
- Где гонки (race conditions)?
- Что с консистентностью данных?
- Какие edge cases не покрыты?
#### 2.5. Поддерживаемость
- Что будет сложно менять через год?
- Где связность, которую придётся разрывать?
- Какие зависимости могут устареть?
#### 2.6. Миграция и совместимость
- Если меняем API — как старые клиенты переживут?
- Если меняем схему БД — что со старыми данными?
- Если выкатываем поэтапно — какой план?
### 3. Записать отчёт
Создать `.agent/context/red-team-report.md` (если файла нет) или дополнить:
```markdown
# Red Team Review — {что ревьюим}
**Дата:** {YYYY-MM-DD}
**Цель:** {что именно атакуем}
## Критические находки
### R1. {Краткое название}
- **Категория:** безопасность / нагрузка / корректность / ...
- **Сценарий:** {как воспроизвести}
- **Воздействие:** {что произойдёт}
- **Рекомендация:** {что сделать}
## Существенные находки
### R2. ...
## Минорные находки
### R3. ...
## Что выдержало атаку
- {Что оказалось надёжным — это тоже полезно знать.}
```
### 4. Связать с задачами
Если находка превращается в задачу — добавить в `.agent/tasks/manifest.json` (фаза DECOMPOSITION) с `origin: "red-team:{номер_находки}"`.
## Выход
- `.agent/context/red-team-report.md`
- (опционально) новые задачи в manifest
## Связанные команды
- **/adr** — если Red Team выявил, что нужно зафиксировать решение иначе.
- **/risk-register** — для систематизации рисков.
-80
View File
@@ -1,80 +0,0 @@
# Risk Register
## Назначение
Явный реестр допущений и рисков проекта в `.agent/context/risk-register.md`. Чтобы не держать в голове «ну мы же понимаем, что X может сломаться» — а записать, оценить и (если надо) превратить в задачи.
## Когда вызывать
- В начале проекта — зафиксировать стартовые допущения.
- При появлении нового риска (новый внешний сервис, новая зависимость, новое требование).
- При обзоре дизайна (после DESIGN или Red Team).
## Вход
- `.agent/context/design-report.md` (если есть).
- `.agent/context/analysis-report.md` — что уже знаем о проекте.
- `.agent/decisions/*.md` — принятые решения (могут быть источниками рисков).
## Шаги
### 1. Собрать риски
Источники:
- Допущения, на которых держится дизайн («считаем, что PostgreSQL выдержит 1k qps»).
- Внешние зависимости без SLA.
- Технологии, которые команда не знает.
- Сроки, которые давят.
- Решения, которые сложно откатить.
### 2. Оценить каждый риск
По двум осям:
- **Вероятность** (1-низкая, 2-средняя, 3-высокая).
- **Воздействие** (1-небольшое, 2-серьёзное, 3-критическое).
`score = вероятность × воздействие` (1-9).
### 3. Записать
Создать или дополнить `.agent/context/risk-register.md` по шаблону `TEMPLATES/risk-register.md`:
```markdown
# Risk Register
**Дата:** {YYYY-MM-DD}
## Высокий риск (score 6-9)
### R-001. {Краткое название}
- **Категория:** технический / продуктовый / организационный
- **Описание:** {что может пойти не так}
- **Воздействие:** {что будет если случится}
- **Вероятность:** 3 / 2 / 1
- **Счёт:** 9 / 6 / 4
- **Митигация:** {что делаем чтобы уменьшить}
- **Владелец:** {кто отвечает}
- **Статус:** open / mitigated / accepted / closed
## Средний риск (score 3-4)
...
## Низкий риск (score 1-2)
...
## Закрытые риски
...
```
### 4. Связать с задачами
Если риск требует действия — добавить задачу в `.agent/tasks/manifest.json` с `origin: "risk:R-001"`.
## Выход
- `.agent/context/risk-register.md`
## Связанные команды
- **/red-team** — источник технических рисков.
- **/adr** — некоторые риски закрываются через принятое решение.
-205
View File
@@ -1,205 +0,0 @@
# MetaAgent GUIDE v3.0
MetaAgent — набор инструкций для AI-агента. Задача: превратить хаотичное общение с агентом в структурированный процесс, в котором состояние проекта переживает любую сессию.
## Два слоя
- **Цикл** (всегда, по необходимости) — последовательность фаз, которую агент проходит при работе с проектом.
- **Команды** (по запросу пользователя) — on-demand инструкции, которые не привязаны к фазе.
Состояние проекта живёт в `.agent/` целевого репозитория. Следующий агент читает `.agent/` и не лезет в исходники.
---
## Цикл
```
.agent/checkpoints.json
│
▼
┌─────────────────────────────────────┐
│ PROJECT LOOP (разово) │
│ │
│ INIT → ANALYSE → ROADMAP → │
│ → [DESIGN] → DECOMPOSITION │
│ │
│ Выход: .agent/tasks/manifest.json │
└──────────────────┬──────────────────┘
│
▼
┌─────────────────────────────────────┐
│ WORK LOOP (циклически) │
│ │
│ EXECUTION → (request) → │
│ → METASTATE (по команде) │
│ │
│ Беру задачу → делаю → request → │
│ накопилось → METASTATE │
└──────────────────┬──────────────────┘
│
▼
HANDOFF (завершение)
```
Фазы выполняются **строго последовательно** внутри PROJECT LOOP. WORK LOOP повторяется многократно.
### Ветвление
| Тип проекта | Цикл |
|---|---|
| **existing** | INIT → ANALYSE → ROADMAP → DECOMPOSITION → EXECUTION → METASTATE → HANDOFF |
| **greenfield / scaffold** | + фаза DESIGN между ROADMAP и DECOMPOSITION |
Тип проекта определяется автоматически в фазе ANALYSE. Никакого интервью с пользователем, никакой шкалы глубины.
---
## Фазы
| # | Фаза | Протокол | Что делает |
|---|---|---|---|
| 0 | INIT | `PROTOCOLS/00_INIT.md` | Создаёт `.agent/`, ставит исходники, инициализирует checkpoints |
| 1 | ANALYSE | `PROTOCOLS/01_ANALYSE.md` | Сканирует проект, создаёт `analysis-report.md` + начальный `project-state.md` |
| 2 | ROADMAP | `PROTOCOLS/02_ROADMAP.md` | Собирает источники задач (FUTURE, ADR, user-запросы) → `roadmap/sources.md` |
| 3 | DESIGN | `PROTOCOLS/03_DESIGN.md` | Только greenfield. Архитектура, модули, API, модели |
| 4 | DECOMPOSITION | `PROTOCOLS/04_DECOMPOSITION.md` | Разбивает цель на атомарные задачи → `tasks/manifest.json` |
| 5 | EXECUTION | `PROTOCOLS/05_EXECUTION.md` | Цикл: берёт задачу → код → тесты → коммит → request |
| 6 | METASTATE | `PROTOCOLS/06_METASTATE.md` | По команде. Ревью requests, обновление project-state, handoff-summary |
| 7 | HANDOFF | `PROTOCOLS/07_HANDOFF.md` | Валидация `.agent/`, финализация checkpoints, session-summary |
---
## Команды
Эти инструкции выполняются **по явной просьбе пользователя** в любой момент сессии. Они не привязаны к фазе.
| Команда | Файл | Что делает |
|---|---|---|
| «запиши ADR» / «/adr» | `COMMANDS/adr.md` | Создаёт `.agent/decisions/NNN-slug.md` |
| «red team» / «/red-team» | `COMMANDS/red-team.md` | Создаёт `.agent/context/red-team-report.md` — попытка сломать дизайн |
| «risk register» / «/risk-register» | `COMMANDS/risk-register.md` | Создаёт `.agent/context/risk-register.md` |
| «альтернативная архитектура» / «/alt-arch» | `COMMANDS/alt-arch.md` | Описывает альтернативу текущему дизайну |
| «invariant-тесты» / «/invariant-tests» | `COMMANDS/invariant-tests.md` | Создаёт задачи-инварианты для ADR |
### Когда вызывать
- **ADR** — после архитектурного решения, которое нужно зафиксировать. Типично во время DESIGN или при появлении неочевидного выбора в EXECUTION.
- **Red Team** — после готового дизайна, чтобы найти слабые места до реализации.
- **Risk Register** — в начале проекта или при появлении новых допущений.
- **Alt Arch** — если сомневаетесь в выбранном подходе, хотите сравнить варианты.
- **Invariant Tests** — после ADR, чтобы зафиксировать «что не должно сломаться».
Команды **не обязательны**. Если не вызваны — не выполняются. Состояние проекта от них не зависит.
---
## Структура `.agent/`
```
.agent/
checkpoints.json # состояние сессии (ядро)
session-summary.md # краткая сводка сессии
handoff-summary.md # сводка для следующего агента (создаётся METASTATE)
src/ # исходники MetaAgent (всегда)
GUIDE.md
BOUNDARIES.md
CHANGELOG.md
PROTOCOLS/
COMMANDS/
TEMPLATES/
VERSION
install.sh / install.ps1
rules/
project-rules.md # ваши правила — читать перед каждой фазой
roadmap/ # источники задач
sources.md
archive/
decisions/ # ADR
index.json
001-*.md
tasks/ # задачи
manifest.json + manifest.md
backlog/
requests/ # результаты выполненных задач
active/ # ready_for_review
archive/ # approved / rejected
context/
analysis-report.md
project-state.md # обновляется в METASTATE
design-report.md # только greenfield
red-team-report.md # если вызывали /red-team
risk-register.md # если вызывали /risk-register
baseline-test-report.log
archive/
index.json
tasks/
decisions/
requests/
checkpoints/
```
`.temp/` в корне проекта — для временных файлов агента. Всегда в `.gitignore`.
---
## Checkpoints
`checkpoints.json` обновляется после каждой фазы:
```json
{
"metaagent_version": "3.0.0",
"session_id": "<uuid>",
"target_repo": "<path>",
"goal": "<цель>",
"project_type": "existing | greenfield | scaffold",
"phases": {
"init": "completed",
"analyse": "completed",
"roadmap": "completed",
"design": "skipped",
"decomposition": "completed",
"execution": "in_progress",
"metastate": "pending",
"handoff": "pending"
},
"tasks": [
{ "id": "T1", "title": "...", "status": "in_progress", "origin": "user:direct" }
],
"last_updated": "<timestamp>"
}
```
Секции `config` больше нет. Параметры, которые раньше были в `config` (depth, adr, red_team и т.п.), теперь либо не существуют, либо живут в отдельных командах.
---
## Принципы
### Цикл vs команды
Цикл — это «что агент делает по умолчанию». Команды — «что агент делает по явной просьбе». Не путать: ADR не запускается автоматически в DESIGN, а только когда пользователь скажет «запиши это как решение».
### `.agent/` как слепок проекта
После METASTATE `.agent/` содержит всю картину. Следующий агент читает только `.agent/`, не исходники.
### Request — единица результата
Каждая выполненная задача в EXECUTION завершается созданием `request` (`.agent/requests/active/req-{id}.json`). Request содержит суть изменений, коммиты, верификацию, закрытые acceptance criteria. Ревью request-ов происходит в METASTATE.
### Правила выше протоколов
Перед каждой фазой читать `.agent/rules/project-rules.md`. Если правило пользователя противоречит протоколу — следовать правилу.
### Контекст бесконечно не растёт
Завершённые задачи архивируются в `.agent/archive/tasks/`, request-ы — в `.agent/requests/archive/`. Текущий manifest остаётся lean.
+336
View File
@@ -0,0 +1,336 @@
# META_AGENT_GUIDE — Главная инструкция
## Жизненный цикл сессии
```
.agent/metaagent-request.md
│
▼
INIT → ANALYSE → [DESIGN] → [RED_TEAM] → DECOMPOSITION → SETUP → (CHECKPOINT)* → HANDOFF → EXIT
│ │
▼ ▼
ADR (опц.) Invariant Tasks (опц.)
Alt.Arch (опц.)
Risk Register (опц.)
```
Фазы выполняются **строго последовательно**. Фаза DESIGN — только если project_type = greenfield/scaffold.
Фаза RED_TEAM — только если config.red_team = yes.
Все артефакты размещаются в `.agent/` целевого репозитория (с layer-структурой или плоские, в зависимости от config).
---
## Конфигурация сессии (.agent/metaagent-request.md)
Перед запуском сессии пользователь заполняет `.agent/metaagent-request.md` (см. `TEMPLATES/metaagent-request.md`). Файл должен находиться в директории `.agent/` целевого репозитория.
Ключевые параметры:
### Шкала глубины (depth 1-10)
| Уровень | Название | Что выполняется |
|---|---|---|
| 1-2 | Scaffold | INIT → ANALYSIS → SETUP (только структура, без реализации) |
| 3-4 | Light | + DESIGN (без ADR/альтернатив), DECOMPOSITION (без инвариантов), HANDOFF — **(default)** |
| 5-6 | Standard | полный цикл с базовым DESIGN и DECOMPOSITION |
| 7-8 | Deep | + ADR, Alternative Architecture, Risk Register, Invariant Tests |
| 9-10 | Maximum | + Red Team Review, Executable Invariants для всех ADR |
### Функции (таблица вкл/выкл)
| Функция | Фаза | Глубина | Описание |
|---|---|---|---|
| adr | DESIGN | >=7 | Создание ADR для каждого ключевого решения |
| alternative_arch | DESIGN | >=7 | Обязательное описание альтернативной архитектуры |
| red_team | DESIGN (после) | >=9 | Red Team Review — попытка разрушить архитектуру |
| risk_register | DESIGN | >=7 | Явный реестр допущений |
| invariant_tests | DECOMPOSITION | >=7 | Задачи-инварианты для каждого ADR |
| layer_structure | HANDOFF | любая | Организация .agent/ по слоям (layer-0..3) |
---
## Фаза 0: INIT
**Вход:** целевой репозиторий + опционально `.agent/metaagent-request.md`.
**Протокол:** `PROTOCOLS/00_CONFIG.md`
**Действия:**
- Прочитать `VERSION` — текущая версия MetaAgent
- Склонировать/открыть целевой репозиторий
- Создать директорию `.agent/` в корне целевого репозитория (если нет)
- **Установить исходники MetaAgent в `.agent/src/`:**
- Скопировать `META_AGENT_GUIDE.md`, `BOUNDARIES.md`, `WORKFLOW.md`, `VERSION` в `.agent/src/`
- Скопировать `PROTOCOLS/` и `TEMPLATES/` в `.agent/src/`
- Скопировать `install.sh` и `install.ps1` в `.agent/src/` (для возможности обновления)
- Если файлы уже существуют — пропустить (не перезаписывать)
- **Создать `.agent/rules/`** — директорию для пользовательских правил
- Если `.agent/rules/project-rules.md` не существует — создать из шаблона `.agent/src/TEMPLATES/project-rules.md`
- **Создать/обновить `AGENTS.md` в корне целевого репозитория** (если нет — создать, если есть — не трогать)
- Прочитать `PROTOCOLS/00_CONFIG.md`
- Выполнить 00_CONFIG:
- Если `.agent/metaagent-request.md` существует — прочитать config из него
- Если нет — провести интервью с пользователем (или принять `default`)
- Валидировать config относительно depth
- Если не было файла — создать `.agent/metaagent-request.md` с пометкой Auto-generated
- **Проверить версию:** если `.agent/checkpoints.json` существует → выполнить `PROTOCOLS/00_MIGRATE.md` (сравнить metaagent_version, применить миграцию при необходимости)
- Прочитать `PROTOCOLS/01_ANALYSIS.md`
- Инициализировать `.agent/checkpoints.json` с `metaagent_version` (если не существовал)
```json
{
"metaagent_version": "1.1.0",
"session_id": "<uuid>",
"target_repo": "<path>",
"goal": "<цель от пользователя>",
"project_type": "pending",
"config": {
"depth": 4,
"design": { "adr": false, "alternative_arch": false },
"red_team": false,
"risk_register": false,
"decomposition": { "invariant_tests": false },
"handoff": { "layer_structure": false }
},
"phases": {
"analysis": "pending",
"design": "pending",
"red_team": "pending",
"decomposition": "pending",
"environment": "pending",
"handoff": "pending"
},
"tasks": [],
"last_updated": "<timestamp>"
}
```
**Выход:** готовая `.agent/` + checkpoints.json с metaagent_version и config.
---
## Фаза 1: ANALYSE
**Вход:** целевой репозиторий, `.agent/metaagent-request.md` (или auto-generated), checkpoints.json (analysis: pending, config: from INIT).
**Протокол:** `PROTOCOLS/01_ANALYSIS.md`
**Действия:**
- **Прочитать `.agent/rules/project-rules.md`** — учесть пользовательские правила
- Прочитать config из checkpoints.json (уже получен на INIT через 00_CONFIG)
- Если config отсутствует — применить default config (depth=4) как fallback
- Выполнить анализ репозитория по протоколу (определяет тип проекта)
- Записать результат в `.agent/analysis-report.md`
- Обновить checkpoints.json: `phases.analysis = "completed"`, `project_type = "existing" | "greenfield" | "scaffold"`
**Выход:** `.agent/analysis-report.md`
**Ветвление:**
- `project_type = "greenfield"` или `"scaffold"` → далее фаза DESIGN
- `project_type = "existing"` → DESIGN пропускается, сразу DECOMPOSITION
---
## Фаза 2: DESIGN (условная)
**Вход:** analysis-report.md, checkpoints.json (analysis: completed, project_type: greenfield/scaffold).
**Протокол:** `PROTOCOLS/02_DESIGN.md`
**Действия:**
- **Прочитать `.agent/rules/project-rules.md`** — учесть пользовательские правила
- Спроектировать архитектуру, модули, данные, интерфейсы
- Если config.design.alternative_arch: описать альтернативную архитектуру
- Если config.design.adr: создать ADR для каждого ключевого решения → `.agent/layer-1/adr/`
- Если config.risk_register: создать `.agent/layer-1/risk-register.md`
- Записать результат в `.agent/design-report.md`
- Обновить checkpoints.json: `phases.design = "completed"`
**Ветвление:**
- Если config.red_team = yes → следующая фаза RED_TEAM
- Иначе → сразу DECOMPOSITION
**Выход:** `.agent/design-report.md`, опционально `.agent/layer-1/adr/*.md`, `.agent/layer-1/risk-register.md`
---
## Фаза 2b: RED_TEAM (опциональная)
**Вход:** design-report.md, ADR (опционально), checkpoints.json (design: completed).
**Протокол:** `PROTOCOLS/02b_REDTEAM.md`
**Действия:**
- **Прочитать `.agent/rules/project-rules.md`** — учесть пользовательские правила
- Выполнить Red Team Review по протоколу
- Записать результат в `.agent/layer-1/red-team-report.md`
- Дополнить risk-register.md (если существует)
- Если найдены критические проблемы — исправить design-report
- Обновить checkpoints.json: `phases.red_team = "completed"`
**Выход:** `.agent/layer-1/red-team-report.md`
---
## Фаза 3: DECOMPOSITION
**Вход:** analysis-report.md + design-report.md (опционально) + ADR (опционально) + checkpoints.json.
**Протокол:** `PROTOCOLS/03_DECOMPOSITION.md`
**Действия:**
- **Прочитать `.agent/rules/project-rules.md`** — учесть пользовательские правила
- Разбить цель (и дизайн) на атомарные задачи
- Если config.decomposition.invariant_tests: создать задачи-инварианты для каждого ADR
- Записать манифест в `.agent/task-manifest.json` и `.agent/task-manifest.md`
- Обновить checkpoints.json: `phases.decomposition = "completed"`, заполнить `tasks`
**Выход:** `.agent/task-manifest.json`, `.agent/task-manifest.md`
---
## Фаза 4: SETUP
**Вход:** analysis-report.md, design-report.md (опционально), task-manifest.json, checkpoints.json (decomposition: completed).
**Протокол:** `PROTOCOLS/04_ENVIRONMENT_SETUP.md`
**Действия:**
- **Прочитать `.agent/rules/project-rules.md`** — учесть пользовательские правила
- Выполнить настройку окружения по протоколу (ветка A для existing, ветка B для greenfield)
- Записать результат проверки в `.agent/baseline-test-report.log` и `.agent/setup-report.log`
- Обновить checkpoints.json: `phases.environment = "completed"`
**Выход:** рабочее окружение + `.agent/baseline-test-report.log`
---
## Фаза 5: CHECKPOINT (сквозная)
**Вход:** любая фаза.
**Протокол:** обновлять checkpoints.json после каждого значимого шага.
**Архивирование перед сохранением чекпоинта:**
- Если checkpoints.json уже существует — сохранить предыдущую версию в `.agent/archive/checkpoints/<last_updated>.json`
**Формат:**
```json
{
"metaagent_version": "1.1.0",
"session_id": "<uuid>",
"target_repo": "<path>",
"goal": "<цель>",
"project_type": "existing | greenfield | scaffold",
"config": {
"depth": 6,
"design": { "adr": true, "alternative_arch": true },
"red_team": false,
"risk_register": false,
"decomposition": { "invariant_tests": true },
"handoff": { "layer_structure": true }
},
"phases": {
"analysis": "completed",
"design": "completed",
"red_team": "skipped",
"decomposition": "in_progress",
"environment": "pending",
"handoff": "pending"
},
"tasks": [
{ "id": "T1", "title": "...", "status": "completed",
"depends_on": [], "acceptance_criteria": ["..."] },
{ "id": "T2", "title": "...", "status": "pending",
"depends_on": ["T1"], "acceptance_criteria": ["..."] }
],
"last_updated": "<timestamp>"
}
```
`status` может быть: `pending`, `in_progress`, `completed`, `failed`, `skipped`.
Фаза `red_team` может быть `skipped` если config.red_team = false.
---
## Фаза 6: HANDOFF
**Вход:** все предыдущие фазы completed.
**Протокол:** `PROTOCOLS/05_HANDOFF.md`
**Действия:**
- **Прочитать `.agent/rules/project-rules.md`** — учесть пользовательские правила
- **Архивировать завершённые задачи:**
- Для каждой задачи со статусом `completed` в `task-manifest.json`:
- Перенести полное описание в `.agent/archive/tasks/<id>.json`
- Заменить в манифесте на one-liner: `{ "id": "<id>", "title": "<title>", "status": "archived" }`
- Создать `.agent/archive/index.json` со списком архивированных задач
- Заархивировать предыдущий `checkpoints.json` в `.agent/archive/checkpoints/`
- Выполнить валидацию всех артефактов
- Если config.handoff.layer_structure: организовать `.agent/` по слоям
- Записать `.agent/handoff-summary.md` (в layer-3 при layer_structure=yes)
- Создать `.agent/session-summary.md` (в layer-0 при layer_structure=yes)
- Обновить checkpoints.json: `phases.handoff = "completed"`
- Сообщить пользователю/оркестратору
**Выход:** `.agent/handoff-summary.md` — итоговый документ для исполнительного агента.
---
## Фаза 7: EXIT
Мета-агент завершает работу. Управление переходит к исполнительному агенту.
---
## Структура .agent/
.agent/ всегда содержит служебную директорию `src/` с исходниками MetaAgent (см. фазу INIT).
При layer_structure=yes артефакты сессии раскладываются по слоям layer-0..3.
```
.agent/
src/ # исходники MetaAgent (всегда)
META_AGENT_GUIDE.md # главная инструкция
PROTOCOLS/ # протоколы фаз
TEMPLATES/ # шаблоны артефактов
BOUNDARIES.md # границы
WORKFLOW.md # примеры работы
VERSION # версия MetaAgent
install.sh # скрипт установки/обновления (Unix)
install.ps1 # скрипт установки/обновления (Windows)
rules/ # пользовательские правила (всегда)
project-rules.md # правила проекта — читать перед каждой фазой
archive/ # архив завершённых артефактов (создаётся при HANDOFF)
index.json # мета-индекс архива
tasks/ # детали завершённых задач
checkpoints/ # исторические чекпоинты
adr/ # заменённые ADR
reports/ # устаревшие отчёты
layer-0/ # ядро сессии (только при layer_structure=yes)
checkpoints.json # всегда (ядро)
session-summary.md # краткая сводка сессии
layer-1/ # архитектурные решения (справочно)
adr/
001-технологический-стек.md
002-архитектурный-паттерн.md
...
risk-register.md
red-team-report.md
layer-2/ # дизайн и анализ (справочно)
analysis-report.md
design-report.md
layer-3/ # состояние исполнения
handoff-summary.md
task-manifest.json
task-manifest.md
baseline-test-report.log
setup-report.log
```
Исполнительный агент всегда начинает с layer-0 (checkpoints + session-summary),
затем при необходимости обращается к layer-1 (ADR для понимания "почему"),
layer-2 (детали дизайна), layer-3 (что было сделано).
+145
View File
@@ -0,0 +1,145 @@
# Протокол 00: Конфигурация сессии (CONFIG)
## Цель
Определить параметры сессии MetaAgent: глубину проработки, набор функций, тип проекта. Выполняется на фазе INIT.
## Вход
- `VERSION` — текущая версия MetaAgent
- Запрос пользователя (цель)
- Опционально: `.agent/metaagent-request.md` (в директории `.agent/` целевого репозитория)
## Шаги
### 0.1. Проверить наличие .agent/metaagent-request.md
Если файл существует — распарсить, провалидировать и использовать.
Если нет — перейти к интервью (шаг 0.2).
### 0.2. Интервью с пользователем
Задать пользователю серию вопросов для сбора конфигурации.
**Сценарий интервью:**
```
MetaAgent: .agent/metaagent-request.md не найден. Давайте настроим сессию.
(или ответьте "default" — я выберу depth=4, light)
Q1: Это новый проект (greenfield) или работа с существующим кодом (existing)?
Варианты: new / existing / scaffold / default
Q2: Глубина проработки?
1-2: Scaffold — только структура, пустые модули
3-4: Light — быстрый дизайн + задачи, без расширений (рекомендуется default)
5-6: Standard — полный цикл с acceptance criteria
7-8: Deep — + ADR, risk register, alternative architecture
9-10: Maximum — + Red Team review, executable invariants
Варианты: число 1-10 / default
Q3 (если глубина >= 7): Нужны ADR (Architecture Decision Records)?
Варианты: yes / no / default
Q4 (если глубина >= 7): Нужен Risk Register?
Варианты: yes / no / default
Q5 (если глубина >= 9): Нужен Red Team Review?
Варианты: yes / no / default
```
**Правила обработки ответов:**
- Если пользователь ответил `default` или не ответил — применить значение по умолчанию для этого поля
- Если пользователь ответил `new` — `project_type = greenfield`
- Если `existing` — `project_type = existing`
### 0.3. Default config
```json
{
"depth": 4,
"design": {
"adr": false,
"alternative_arch": false
},
"red_team": false,
"risk_register": false,
"decomposition": {
"invariant_tests": false
},
"handoff": {
"layer_structure": false
}
}
```
Depth=4 (Light) означает:
- ANALYSIS — полный (определение типа проекта, извлечение требований)
- DESIGN — выполняется (если greenfield), но **без** ADR, Alternative Architecture, Risk Register
- DECOMPOSITION — задачи с acceptance criteria, **без** invariant-тестов
- SETUP — полный
- HANDOFF — плоский `.agent/` (без layer-структуры)
### 0.4. Запись .agent/metaagent-request.md
Если файла не было, создать его по результатам интервью с пометкой `Auto-generated`:
```markdown
# MetaAgent Request
# Auto-generated from user interview on {{ date }}
## Параметры сессии
| Функция | Вкл | Аргументы |
|---|---|---|
| ANALYSIS | ✓ | — |
| DESIGN | ✓ | adr={{ adr }}, alternative_arch={{ alt_arch }} |
| RED_TEAM | {{ red_team }} | — |
| RISK_REGISTER | {{ risk_register }} | — |
| DECOMPOSITION | ✓ | invariant_tests={{ invariant_tests }} |
| SETUP | ✓ | — |
| HANDOFF | ✓ | layer_structure={{ layer_structure }} |
## Глубина проработки
**Значение:** {{ depth }}
## Цель
{{ goal }}
```
### 0.5. Создание .agent/rules/
Создать директорию `.agent/rules/` в корне целевого проекта (если не существует).
Если `.agent/rules/project-rules.md` не существует — создать из шаблона `.agent/src/TEMPLATES/project-rules.md`:
```markdown
# Project Rules
Добавляйте сюда правила, которым агент обязан следовать во всех фазах.
```
### 0.6. Валидация config
Проверить совместимость параметров с depth:
```
depth < 3 → DESIGN пропускается (даже для greenfield)
depth < 7 → adr=false, alternative_arch=false, risk_register=false, invariant_tests=false
depth < 9 → red_team=false
```
Если depth несовместим с включёнными функциями — понизить функции до максимума, разрешённого depth.
## Выход
- `.agent/metaagent-request.md` (создан или подтверждён)
- config — словарь параметров для записи в checkpoints.json
## Критерии завершения
- [ ] `.agent/metaagent-request.md` существует (создан или найден)
- [ ] Config содержит depth, design.*, red_team, risk_register, decomposition.*, handoff.*
- [ ] Config совместим с depth (доп. функции отключены для малых depth)
- [ ] При отсутствии файла — проведено интервью, файл создан
-128
View File
@@ -1,128 +0,0 @@
# Протокол 00: Инициализация (INIT)
## Цель
Подготовить `.agent/` в целевом репозитории: установить исходники MetaAgent, создать структуру директорий, инициализировать `checkpoints.json`, создать/обновить `AGENTS.md`.
INIT выполняется **один раз** в начале работы с проектом. Если `.agent/` уже существует и инициализирован — пропускается.
## Вход
- Целевой репозиторий (путь или текущая директория)
- `VERSION` — текущая версия MetaAgent
- Опционально: существующий `.agent/` (если обновление)
## Шаги
### 0.1. Определить целевой репозиторий
Если не указан явно — текущая рабочая директория. Если указан как URL — клонировать во временную директорию, дальше работать с копией.
### 0.2. Проверить существующий `.agent/`
Если `.agent/` существует:
- Прочитать `.agent/checkpoints.json` → `metaagent_version`
- Если `metaagent_version == VERSION` → INIT уже выполнен, выйти
- Если версия старше → запустить `install.sh --update` (Unix) или `install.ps1 -Update` (Windows) для переустановки исходников, затем выйти
- Если `.agent/` есть, но `checkpoints.json` отсутствует → продолжить INIT (создать checkpoints)
Если `.agent/` не существует → продолжить INIT.
### 0.3. Создать структуру `.agent/`
Создать директории:
```
.agent/
src/ # исходники MetaAgent (копируются из METAAGENT_SRC)
rules/
decisions/
tasks/
backlog/
context/
requests/
active/
archive/
roadmap/
archive/
archive/
tasks/
decisions/
requests/
checkpoints/
```
### 0.4. Создать `.temp/` в корне проекта
Если не существует — создать `.temp/` в корне целевого репозитория. Добавить в `.gitignore` (если его нет — создать с одной строкой `.temp/`).
### 0.5. Скопировать исходники MetaAgent
Скопировать в `.agent/src/`:
- `GUIDE.md`
- `BOUNDARIES.md`
- `CHANGELOG.md`
- `VERSION`
- `PROTOCOLS/`
- `COMMANDS/`
- `TEMPLATES/`
- `install.sh`, `install.ps1`
Существующие файлы в `.agent/src/` не перезаписывать (только с явным `--update`).
### 0.6. Создать `.agent/rules/project-rules.md`
Если файла нет — создать по шаблону `TEMPLATES/project-rules.md`.
### 0.7. Создать/обновить `AGENTS.md` в корне
Если `AGENTS.md` в корне проекта отсутствует — создать по `AGENTS.template.md` с подставленной версией.
Если существует и не относится к MetaAgent — не трогать (попросить пользователя переименовать или подтвердить перезапись).
### 0.8. Инициализировать `checkpoints.json`
Создать `.agent/checkpoints.json`:
```json
{
"metaagent_version": "3.0.0",
"session_id": "<uuid>",
"target_repo": "<путь>",
"goal": null,
"project_type": null,
"phases": {
"init": "completed",
"analyse": "pending",
"roadmap": "pending",
"design": "pending",
"decomposition": "pending",
"execution": "pending",
"metastate": "pending",
"handoff": "pending"
},
"tasks": [],
"last_updated": "<timestamp>"
}
```
Поля `goal` и `project_type` остаются `null` до фазы ANALYSE (goal может быть задан пользователем заранее — тогда заполнить сразу).
## Выход
- `.agent/` с полной структурой
- `.agent/src/` с актуальными исходниками MetaAgent
- `.agent/rules/project-rules.md`
- `.agent/checkpoints.json` со `session_id` и `phases.init = "completed"`
- `AGENTS.md` в корне проекта
- `.temp/` в корне + `.gitignore` обновлён
## Критерии завершения
- [ ] `.agent/` содержит все обязательные директории
- [ ] `.agent/src/` содержит GUIDE.md, PROTOCOLS/, COMMANDS/, TEMPLATES/, VERSION
- [ ] `.agent/checkpoints.json` валиден (JSON parse)
- [ ] `AGENTS.md` присутствует в корне
- [ ] `.temp/` существует и в `.gitignore`
+124
View File
@@ -0,0 +1,124 @@
# Протокол 00b: Миграция артефактов (MIGRATE)
## Цель
Обеспечить совместимость артефактов `.agent/` при изменении версии MetaAgent.
Позволяет обновлять проекты, созданные старой версией, без потери данных.
## Вход
- `VERSION` — текущая версия MetaAgent
- `.agent/checkpoints.json` — артефакты целевого проекта
- `.agent/` — остальные артефакты
## Шаги
### M1. Определить версию артефактов
Прочитать `.agent/checkpoints.json`:
```python
stored_version = checkpoints.get("metaagent_version", None)
current_version = read("VERSION").strip()
```
- Если `metaagent_version` отсутствует → артефакт создан **v0.x** (доверсионный)
- Если `metaagent_version` == `current_version` → пропустить миграцию
- Если `metaagent_version` < `current_version` → требуется миграция
### M2. Сравнение версий (SemVer)
Версии сравниваются по семантическому версионированию (`MAJOR.MINOR.PATCH`).
```python
def needs_migration(stored, current):
if stored is None:
return True
return parse_semver(stored) < parse_semver(current)
```
### M3. Матрица миграций
Каждая строка — набор шагов для перехода с одной версии на следующую.
| Из версии | В версию | Шаги миграции |
|---|---|---|
| v0.x (нет поля) | v1.0.0 | M3.1 — M3.4 |
| v1.0.0 | v1.1.0 | M3.5 — M3.6 (см. ниже) |
### M4. Шаги миграции v0.x → v1.0.0
... (шаги миграции остаются без изменений)
### M5. Шаги миграции v1.0.0 → v1.1.0
M3.5: Создать `.agent/rules/` с шаблоном `project-rules.md` (если не существует).
M3.6: Создать `.agent/archive/` (если не существует).
#### M3.1. Добавить metaagent_version
Записать в checkpoints.json:
```json
"metaagent_version": "1.1.0"
```
#### M3.2. Добавить config (default)
Если поля `config` нет в checkpoints.json — добавить config по умолчанию:
```json
"config": {
"depth": 4,
"design": { "adr": false, "alternative_arch": false },
"red_team": false,
"risk_register": false,
"decomposition": { "invariant_tests": false },
"handoff": { "layer_structure": false }
}
```
#### M3.3. Добавить фазу red_team
Если в `phases` нет ключа `red_team`:
```json
"red_team": "skipped"
```
#### M3.4. Создать layer-1/ (опционально, только если config.handoff.layer_structure)
Если включена layer_structure:
```bash
mkdir -p .agent/layer-1/adr
touch .agent/layer-1/adr/.gitkeep
```
Если `risk-register.md` уже существует на верхнем уровне — переместить в `.agent/layer-1/risk-register.md`.
### M4. После миграции — резюме
Записать в `.agent/migration-report.log`:
```
[MIGRATE] {{ timestamp }}
From: {{ from_version }}
To: {{ to_version }}
Steps applied: {{ step_list }}
Status: OK
```
## Выход
- Обновлённый `.agent/checkpoints.json` (metaagent_version + config)
- Опционально: `.agent/layer-1/` структура
- `.agent/migration-report.log`
## Критерии завершения
- [ ] metaagent_version в checkpoints.json == текущей версии из VERSION
- [ ] config присутствует в checkpoints.json
- [ ] phases.red_team присутствует (skipped, если не нужен)
- [ ] migration-report.log создан
- [ ] Все старые данные сохранены (ничего не удалено)
-95
View File
@@ -1,95 +0,0 @@
# Протокол 01: Анализ репозитория (ANALYSE)
## Цель
Составить полную картину целевого репозитория: тип проекта, стек, архитектура, конвенции, состояние тестов. Создать начальный слепок проекта.
## Вход
- Целевой репозиторий
- `.agent/checkpoints.json` (фаза analyse: pending)
- `.agent/rules/project-rules.md` — прочитать первым
## Шаги
### 1.1. Прочитать правила проекта
Прежде чем что-либо делать — прочитать `.agent/rules/project-rules.md`. Если есть правила, применить их к фазе.
### 1.2. Определить тип проекта
Просканировать корень репозитория:
- **`existing`** — есть исходный код, тесты, система сборки (`.py`, `.js`, `.ts`, `.rs`, `.go` и т.д. помимо конфигов и README).
- **`greenfield`** — пусто или только README/LICENSE/.gitignore.
- **`scaffold`** — есть базовая структура (`pyproject.toml`/`package.json`), но нет значимого кода.
Записать тип в `checkpoints.json → project_type`.
### 1.3. Сканировать проект
Для `existing` / `scaffold` собрать:
- **README** — описание, инструкции по сборке/тестам.
- **Лицензия** — какой LICENSE.
- **CI/CD** — `.github/workflows/`, `.gitlab-ci.yml`, `Jenkinsfile`, `Makefile`.
- **Стек** — язык, фреймворк, БД, тестовый раннер, пакетный менеджер, линтер.
- **Структура** — `tree -L 3` (не более 3 уровней).
- **Архитектурный паттерн** — MVC, модульный монолит, микросервисы, слоистая.
- **Ключевые модули/пакеты** — список с краткой ответственностью.
- **Конвенции** — стиль, именование, обработка ошибок, логирование.
- **Тесты** — где лежат, как запускаются, текущее состояние (запустить).
- **Сборка** — выполняется ли проект.
Для `greenfield` — извлечь требования из README:
- Функциональные требования (user stories, сценарии).
- Нефункциональные (стек, производительность, безопасность).
- Бизнес-контекст (зачем, для кого).
- Сомнительные / неясные требования (вопросы пользователю).
### 1.4. Создать analysis-report
Записать `.agent/context/analysis-report.md` по шаблону `TEMPLATES/analysis-report.md`. Заполнить соответствующие секции.
### 1.5. Создать начальный project-state
Создать `.agent/context/project-state.md` по шаблону `TEMPLATES/project-state.md`. Это **начальный** слепок. В дальнейшем обновляется в фазе METASTATE.
Заполнить:
- Тип проекта
- Краткая архитектура (из шага 1.3)
- Ключевые модули и их статус
- Tech stack
- Статус тестов
### 1.6. Обновить checkpoints
```json
{
"phases": { "analyse": "completed" },
"project_type": "existing | greenfield | scaffold",
"last_updated": "<timestamp>"
}
```
## Ветвление
| project_type | Следующая фаза |
|---|---|
| `existing` | ROADMAP → DECOMPOSITION (DESIGN пропускается) |
| `greenfield` | ROADMAP → DESIGN → DECOMPOSITION |
| `scaffold` | ROADMAP → DESIGN → DECOMPOSITION |
## Выход
- `.agent/context/analysis-report.md`
- `.agent/context/project-state.md` (начальный)
- Обновлённый `checkpoints.json`
## Критерии завершения
- [ ] Тип проекта определён
- [ ] `analysis-report.md` содержит все соответствующие секции
- [ ] `project-state.md` создан с начальным слепком
- [ ] `checkpoints.json` обновлён
+139
View File
@@ -0,0 +1,139 @@
# Протокол 01: Анализ репозитория (ANALYSIS)
## Цель
Составить полную картину целевого репозитория: тип проекта, архитектура, стек, конвенции, состояние тестов, требования.
## Вход
- Целевой репозиторий (локальная копия)
- `.agent/metaagent-request.md` (конфигурация сессии: глубина, функции) — или auto-generated
- `.agent/checkpoints.json` (фаза analysis: pending)
## Шаги
### 0.0. Чтение конфигурации сессии
Прочитать config из checkpoints.json (установлен на фазе INIT через `00_CONFIG.md`).
Если config отсутствует или неполный — применить default:
```json
{
"depth": 4,
"design": { "adr": false, "alternative_arch": false },
"red_team": false,
"risk_register": false,
"decomposition": { "invariant_tests": false },
"handoff": { "layer_structure": false }
}
```
Записать (или подтвердить) конфигурацию в checkpoints.json:
```json
"config": {
"depth": 6,
"design": { "adr": true, "alternative_arch": true },
"red_team": false,
"risk_register": false,
"decomposition": { "invariant_tests": true },
"handoff": { "layer_structure": true }
}
```
Если `.agent/metaagent-request.md` не найден — использовать значения по умолчанию (depth=6, все базовые функции=true, расширенные=false).
### 1.0. Определение типа проекта
Просканировать корень репозитория и определить:
- **`existing`** — есть исходный код, тесты, система сборки (файлы `.py`, `.js`, `.ts`, `.rs`, `.go` и т.д. помимо конфигов и README)
- **`greenfield`** — репозиторий пуст или содержит только README, LICENSE, .gitignore
- **`scaffold`** — есть базовая структура (pyproject.toml/package.json), но нет значимого кода
Записать тип в analysis-report.md.
**Правило:** если проект `existing` — разделы 1.1–1.6 выполняются полностью. Если `greenfield` — разделы 1.2–1.5 заменяются на 1.7 (извлечение требований из README).
### 1.1. Общая информация
Прочитать и зафиксировать:
- **README** — описание проекта, how to build/test/run
- **Лицензия** — какой LICENSE
- **CI/CD** — `.github/workflows/`, `.gitlab-ci.yml`, `Jenkinsfile`, `Makefile` и т.д.
- **Главные точки входа** — `main.py`, `index.js`, `cmd/` и т.д.
- **Система сборки** — `package.json`, `pyproject.toml`, `Cargo.toml`, `go.mod`, `CMakeLists.txt`
### 1.2. Стек технологий (только для existing/scaffold)
Определить:
- **Язык(и)** — Python, TypeScript, Go, Rust и т.д.
- **Фреймворк** — FastAPI, Next.js, React, Actix и т.д.
- **База данных** — PostgreSQL, SQLite, MongoDB и т.д.
- **Тестовый раннер** — pytest, jest, vitest, go test
- **Пакетный менеджер** — pip/poetry, npm/yarn/pnpm, cargo, go modules
- **Линтер/форматтер** — ruff, eslint, prettier, rustfmt, gofmt
### 1.3. Архитектура (только для existing/scaffold)
- **Структура директорий** — записать схему (можно `tree /F`, но не более 3 уровней глубины)
- **Архитектурный паттерн** — MVC, Clean Architecture, модульный монолит, микросервисы
- **Ключевые модули/пакеты** — перечислить с кратким описанием
- **Внешние зависимости** — основные библиотеки
### 1.4. Конвенции кода (только для existing/scaffold)
- **Стиль кода** — судя по линтеру и примерам: именование, импорты, типизация
- **Паттерны** — как организованы роуты, хендлеры, модели, тесты
- **Обработка ошибок** — как принято обрабатывать ошибки в проекте
- **Логирование** — используется ли логгер, какой уровень
### 1.5. Тесты (только для existing/scaffold)
- **Какие тесты есть** — unit, integration, e2e
- **Где лежат** — `tests/`, `__tests__/`, рядом с модулями
- **Запуск** — команда для запуска всех тестов
- **Текущее состояние** — запустить тесты, записать результат (сколько всего, сколько пройдено/упало)
- **Покрытие** — есть ли метрики покрытия
### 1.6. Базовая проверка (только для existing/scaffold)
- **Собирается ли проект?** — запустить сборку
- **Запускается ли проект?** — если возможно, проверить старт
- **Чистый ли git status?** — нет ли незакоммиченных изменений
### 1.7. Извлечение требований (только для greenfield/scaffold)
Если README содержит описание будущего проекта — извлечь и структурировать:
**Функциональные требования:**
- Пользовательские истории (user stories)
- Основные сценарии использования
- Входные/выходные данные системы
**Нефункциональные требования:**
- Технологические предпочтения (язык, фреймворк, БД)
- Требования к производительности, безопасности
- Ограничения (сроки, платформа, окружение)
**Бизнес-контекст:**
- Цель системы (зачем)
- Целевая аудитория
- Ключевые метрики успеха
**Сомнительные/неясные требования:**
- Вопросы, которые нужно задать пользователю перед проектированием
- Противоречия в README
## Выход
`.agent/analysis-report.md` по шаблону `TEMPLATES/analysis-report.md`.
Обновить checkpoints.json: `phases.analysis = "completed"`. Если проект `greenfield`, также установить `project_type = "greenfield"`.
## Критерии завершения фазы
- [ ] Тип проекта определён (existing / greenfield / scaffold)
- [ ] Все соответствующие разделы (1.1–1.7) выполнены
- [ ] `.agent/analysis-report.md` создан и заполнен
- [ ] checkpoints.json обновлён
+173
View File
@@ -0,0 +1,173 @@
# Протокол 02: Архитектурное проектирование (DESIGN)
## Цель
Спроектировать архитектуру, модули, данные и интерфейсы для greenfield/scaffold-проекта на основе требований из analysis-report.
## Вход
- `.agent/analysis-report.md` (project_type: greenfield или scaffold)
- `.agent/metaagent-request.md` (конфигурация сессии: adr, alternative_arch, risk_register)
- `.agent/checkpoints.json` (фаза design: pending)
## Правила
1. **Реалистичность** — архитектура должна быть реализуема исполнительным агентом за 1 сессию (до 10 задач)
2. **Документируемость** — каждый модуль, модель и интерфейс описывается в design-report.md
3. **Тестируемость** — каждый компонент проектируется с учётом того, как его тестировать
4. **Итеративность** — первая версия должна быть минимально рабочей (MVP), расширения — отдельными задачами
## Шаги
### 2.1. Технологический стек
Если стек не указан в README — предложить обоснованный выбор. Если указан — зафиксировать.
Для каждого компонента указать:
- Язык и версия
- Фреймворк / библиотека
- База данных (движок, схема)
- Инфраструктура (Docker, CI/CD, хостинг)
### 2.2. High-level архитектура
Описать общую структуру системы:
- **Архитектурный паттерн** — монолит, модульный монолит, микросервисы, слоистая, луковая и т.д.
- **Компоненты и их ответственность** — что делает каждый модуль/сервис
- **Схема взаимодействия** — текстовое описание потоков данных
Формат (text diagram):
```
[Client] → HTTP → [API Gateway] → [Auth Service]
↓
[Core Service] → [Database]
↓
[External API] → [3rd Party]
```
### 2.3. Модули проекта
Разбить систему на модули/пакеты. Для каждого:
| Поле | Описание |
|---|---|
| **Имя модуля** | `app/services/cashflow.py` |
| **Ответственность** | Что делает |
| **Ключевые классы/функции** | Только сигнатуры (без реализации) |
| **Зависимости** | Какие модули нужны этому |
| **Контракт** | Что экспортирует/предоставляет |
### 2.4. Модели данных
Описать основные сущности, их поля и связи:
```json
{
"entity": "Transaction",
"fields": [
{"name": "id", "type": "UUID", "pk": true},
{"name": "amount", "type": "Decimal"},
{"name": "date", "type": "datetime"},
{"name": "category_id", "type": "UUID", "fk": "Category"}
]
}
```
Если используется ORM — указать аннотации/декораторы.
Если БД — схему таблиц, индексы, ключи.
### 2.5. API интерфейсы
Если проектируется API — описать эндпоинты:
| Метод | Путь | Описание | Request | Response | Статусы |
|---|---|---|---|---|---|
| GET | /transactions | Список транзакций | ?page, ?limit | [Transaction] | 200 |
| POST | /transactions | Создать транзакцию | CreateTransactionDTO | Transaction | 201, 400 |
Если GUI — описать ключевые страницы/экраны.
Если CLI — описать команды.
### 2.6. Обработка ошибок
- Стратегия ошибок: исключения, Result-тип, коды ошибок
- Формат ошибок в API: `{ "error": "...", "code": "...", "details": {} }`
- Логирование: какой уровень для каких событий
### 2.7. Стратегия тестирования
- Какие тесты нужны (unit, integration, e2e)
- Как изолировать зависимости (mocks, fakes, testcontainers)
- Команда запуска тестов
### 2.8. Alternative Architecture (если config.alternative_arch = yes)
Описать **минимум одну принципиально иную архитектуру** и причину отказа:
| Критерий | Выбранная архитектура | Альтернатива |
|---|---|---|
| Название | Модульный монолит | Микросервисы / Событийная / и т.д. |
| Сложность реализации | Низкая | Высокая (3+ сервиса) |
| Масштабирование | Вертикальное | Горизонтальное |
| Почему не выбрана | — | Избыточно для MVP |
Это снижает риск архитектурной инерции: решение становится осознанным, а не единственным возможным.
### 2.9. ADR (если config.adr = yes)
Для каждого ключевого архитектурного решения (стек, БД, паттерн, структура модулей) создать отдельный ADR-файл:
```
.agent/layer-1/adr/001-технологический-стек.md
.agent/layer-1/adr/002-модульный-монолит.md
.agent/layer-1/adr/003-json-хранение.md
```
Формат — по шаблону `TEMPLATES/adr-NNNN.md`.
### 2.10. Risk Register (если config.risk_register = yes)
Создать `.agent/layer-1/risk-register.md` по шаблону `TEMPLATES/risk-register.md`:
| # | Assumption | Impact if wrong | Mitigation | Review trigger |
|---|---|---|---|---|
Задокументировать **неявные допущения**, на которых держится архитектура. Это даёт future-агентам знать, что можно пересматривать в первую очередь.
### 2.11. Группировка в задачи
На основе спроектированных модулей и моделей предварительно наметить группировку в задачи (по модулям). Это будет входом для DECOMPOSITION.
```
T1: Инициализация проекта + зависимости
T2: Модель данных (сущности, миграции)
T3: Cashflow Service (core logic)
T4: API endpoints
...и т.д.
```
## Выход
- `.agent/design-report.md` по шаблону `TEMPLATES/design-report.md`
- `.agent/layer-1/adr/*.md` (если adr=yes)
- `.agent/layer-1/risk-register.md` (если risk_register=yes)
- Предварительная группировка задач (для передачи в DECOMPOSITION)
Обновить checkpoints.json: `phases.design = "completed"`.
## Критерии завершения фазы
- [ ] Технологический стек определён
- [ ] High-level архитектура описана
- [ ] Модули и их ответственность описаны
- [ ] Модели данных спроектированы
- [ ] API/интерфейсы описаны (если применимо)
- [ ] Стратегия тестирования определена
- [ ] Alternative Architecture описана (если config требует)
- [ ] ADR созданы (если config требует)
- [ ] Risk Register создан (если config требует)
- [ ] Задачи предварительно сгруппированы
- [ ] `.agent/design-report.md` создан
- [ ] checkpoints.json обновлён
-106
View File
@@ -1,106 +0,0 @@
# Протокол 02: Дорожная карта (ROADMAP)
## Цель
Собрать все источники задач для проекта, приоритизировать их и записать в `.agent/roadmap/sources.md`. ROADMAP — мост между видением проекта и конкретными задачами в манифесте.
## Вход
- `.agent/context/analysis-report.md`
- Цель сессии (goal из `checkpoints.json` или запрос пользователя)
- `FUTURE/` — директория долгосрочных планов (если существует)
- `.agent/decisions/index.json` — принятые ADR (опционально)
- `.agent/checkpoints.json` (фаза roadmap: pending)
- `.agent/rules/project-rules.md` — прочитать первым
## Шаги
### 2.1. Прочитать правила проекта
Прочитать `.agent/rules/project-rules.md`, применить к фазе.
### 2.2. Сканировать FUTURE/
Если в корне проекта существует `FUTURE/`:
- Прочитать все `.md` файлы.
- Зафиксировать: название, статус (active/archived), приоритет, зависимости.
- Какие планы реализованы, какие ожидают.
### 2.3. Сканировать ADR
Если существует `.agent/decisions/index.json`:
- Прочитать индекс ADR.
- Определить, какие решения требуют реализации (не все ADR технические).
- Для каждого — сформулировать задачу-кандидат.
### 2.4. Собрать внешние источники
- Запрос пользователя (goal).
- issues / feedback (если доступны).
- Tech debt, выявленный в ANALYSE.
### 2.5. Приоритизировать
Присвоить каждой задаче приоритет:
| Приоритет | Описание |
|---|---|
| **P0** | Критично, делать следующим |
| **P1** | Важно, сделать скоро |
| **P2** | Желательно |
| **P3** | Долгосрочно / отложено |
Правила:
- Блокирующие зависимости поднимают приоритет.
- User-запросы получают P0-P1 по умолчанию.
- ADR-задачи получают приоритет по срочности решения.
### 2.6. Создать sources.md
Создать `.agent/roadmap/sources.md` по шаблону `TEMPLATES/roadmap-sources.md`:
```markdown
# Roadmap Sources
## FUTURE Plans
| План | Приоритет | Статус |
|------|-----------|--------|
## ADR-Derived Tasks
| ADR | Задача | Приоритет |
|-----|--------|-----------|
## User Requests
| Запрос | Приоритет | Источник |
|--------|-----------|----------|
## Agent-Identified Improvements
| Наблюдение | Задача | Приоритет |
|------------|--------|-----------|
## Consolidated Priority Queue
1. task (origin) — P0
```
### 2.7. Архивация
Если в `.agent/roadmap/archive/` есть предыдущие версии — оставить справочно.
Если планы из `FUTURE/*` больше не актуальны — переместить в `FUTURE/archive/`.
## Выход
- `.agent/roadmap/sources.md`
- Возможно обновлённый `FUTURE/`
- `checkpoints.json: phases.roadmap = "completed"`
## Критерии завершения
- [ ] Все источники просканированы (FUTURE, ADR, user, agent)
- [ ] `sources.md` создан с приоритетами P0-P3
- [ ] Каждая задача имеет origin-ссылку на источник
- [ ] Устаревшие планы перемещены в archive
- [ ] `checkpoints.json` обновлён
+80
View File
@@ -0,0 +1,80 @@
# Протокол 02b: Red Team Review (опционально)
## Цель
Преднамеренно попытаться разрушить спроектированную архитектуру, чтобы найти скрытые проблемы до начала реализации.
## Вход
- `.agent/design-report.md`
- `.agent/layer-1/adr/*.md` (если созданы)
- `.agent/metaagent-request.md` (глубина проработки >= 9)
## Когда выполняется
Только если `config.red_team = yes` (глубина 9-10). Выполняется **после** DESIGN, **до** DECOMPOSITION.
## Шаги
### RT1. Поиск скрытых зависимостей
Проверить каждый модуль на наличие неявных связей:
- Есть ли циклические зависимости между модулями?
- Есть ли модуль, который знает слишком много о других?
- Есть ли скрытый vendor lock-in (БД, облачный провайдер, внешний API)?
### RT2. Точки отказа
Для каждого внешнего интерфейса (API, БД, файловая система):
- Что произойдёт при отказе компонента?
- Есть ли fallback?
- Что произойдёт при невалидных входных данных?
### RT3. Масштабирование
Оценить поведение системы при:
- 10x рост данных
- 100x рост данных
- Добавлении нового пользователя / клиента
### RT4. Security (если применимо)
- Какие данные передаются по сети?
- Есть ли аутентификация?
- Хранятся ли секреты в коде?
### RT5. Consistency
Проверить design-report и ADR на противоречия:
- Одна сущность описана по-разному в двух местах?
- API-контракт не соответствует модели данных?
- Технологический стек противоречит нефункциональным требованиям?
## Выход
`.agent/layer-1/red-team-report.md` с секциями:
```
## Найденные проблемы
| # | Проблема | Серьёзность | Рекомендация |
|---|---|---|---|
## Отклонённые атаки (что пытались сломать — но не сломалось)
| # | Гипотеза | Почему не подтвердилась |
|---|---|---|
```
Обновить risk-register.md (если существует) новыми рисками.
## Критерии завершения
- [ ] Все 5 секций (RT1-RT5) проверены
- [ ] Найденные проблемы записаны в red-team-report.md
- [ ] Если найдены критические проблемы — design-report должен быть исправлен
- [ ] Risk Register дополнен (если существует)
+133
View File
@@ -0,0 +1,133 @@
# Протокол 03: Декомпозиция задач (DECOMPOSITION)
## Цель
Разбить цель пользователя (и архитектурный план, если есть) на атомарные, независимо выполнимые задачи и записать их в манифест.
## Вход
- `.agent/analysis-report.md`
- `.agent/design-report.md` (опционально — для greenfield/scaffold)
- `.agent/layer-1/adr/*.md` (опционально)
- `.agent/layer-1/risk-register.md` (опционально)
- `.agent/metaagent-request.md` (конфигурация сессии)
- Цель пользователя (из checkpoints.json)
- `.agent/checkpoints.json` (фаза decomposition: pending)
## Правила декомпозиции
### 3.1. Принципы
1. **Атомарность** — одна задача = одна логическая единица работы, которую можно выполнить и проверить за один подход
2. **Независимость (макс.)** — минимизировать зависимости между задачами
3. **Тестируемость** — каждая задача имеет измеримые acceptance criteria
4. **Границы** — задача не должна выходить за пределы, указанные в `BOUNDARIES.md`
5. **Порядок** — задачи с зависимостями выполняются строго последовательно
### 3.2. Размер задачи
Задача должна укладываться в **1-2 часа работы исполнительного агента**. Если задача крупнее — разбить на подзадачи.
Признак слишком крупной задачи:
- Нельзя сформулировать acceptance criteria одной строкой
- Затрагивает 5+ файлов
- Содержит союзы "и", "а также", "после чего"
### 3.3. Структура задачи
Каждая задача содержит:
| Поле | Описание | Пример |
|---|---|---|
| `id` | Уникальный идентификатор | `T1`, `T2` |
| `title` | Заголовок (что сделать) | "Добавить модель User" |
| `description` | Описание (как и зачем) | "Создать SQLAlchemy модель..." |
| `type` | Тип задачи | `feature`, `refactor`, `test`, `fix`, `config`, `design`, `docs` |
| `status` | Статус задачи | `pending`, `in_progress`, `completed`, `failed`, `archived` |
| `files` | Список файлов, которые нужно создать/изменить | `["app/models/user.py"]` |
| `depends_on` | ID задач, от которых зависит | `[]` или `["T0"]` |
| `acceptance_criteria` | Список критериев приёмки (3-5 пунктов) | `["Модель проходит миграцию"]` |
| `context` | Доп. информация (ссылки на доки, примеры, релевантные секции из design-report) | `"Смотри app/models/base.py"` |
### 3.4. Типы задач
| Тип | Описание |
|---|---|
| `config` | Настройка окружения, зависимостей, CI, инициализация проекта |
| `design` | Архитектурное/дизайнерское решение без кода |
| `feature` | Новая функциональность |
| `refactor` | Изменение структуры без изменения поведения |
| `test` | Добавление/исправление тестов |
| `fix` | Исправление бага |
| `docs` | Документация |
| `invariant` | Тест, проверяющий архитектурный инвариант (см. 3.7) |
### 3.5. Зелёная декомпозиция (для greenfield/scaffold)
Если есть `.agent/design-report.md` — задачи формируются на основе группировки из дизайна:
1. **T1: init** — инициализация проекта, зависимости, конфиги, scaffold
2. **T2..Tn: features** — модули/функциональность по одному
3. **Tn+1: tests** — тесты на каждый модуль (можно в составе feature-задачи)
4. **Tn+2: polish** — документация, форматирование, финальная проверка
### 3.6. Сортировка
Задачи в манифесте располагаются в порядке выполнения:
1. Сначала задачи без зависимостей
2. Потом те, чьи зависимости уже выполнены
3. Последними — задачи с наибольшим числом зависимостей
### 3.7. Executable Invariants (если config.invariant_tests = yes)
Для каждого ADR (из layer-1/adr/) создать задачу типа `invariant` — тест, проверяющий архитектурное правило.
**Правила превращения ADR в инварианты:**
| ADR | Инвариант-тест |
|---|---|
| "Модуль X не зависит от Y" | `test_x_does_not_import_y.py` — import test |
| "Слой Model не знает о CLI" | `test_model_layer_imports.py` — проверка import graph |
| "Все исключения кастомные" | `test_custom_exceptions.py` — проверка hierarchy |
| "Интерфейс репозитория не泄漏 implementation details" | `test_repository_interface.py` — ABC check |
**Формат задачи-инварианта:**
```json
{
"id": "I1",
"title": "Инвариант: model не импортирует cli",
"type": "invariant",
"files": ["tests/invariants/test_layer_imports.py"],
"depends_on": ["T2"],
"acceptance_criteria": [
"Тест проверяет, что cashflow_model не импортирует cli, sync, engine",
"Тест проходит на пустом проекте (до реализации функциональности)"
]
}
```
Инварианты размещаются в `tests/invariants/` и запускаются вместе с основными тестами.
## Выход
- `.agent/task-manifest.json` — по схеме `TEMPLATES/task-manifest.json`
- `.agent/task-manifest.md` — по шаблону `TEMPLATES/task-manifest.md`
Обновить checkpoints.json:
- `phases.decomposition = "completed"`
- `tasks` = полный массив задач со статусом `pending`
> **Примечание:** после HANDOFF завершённые задачи будут архивированы —
> полное описание уходит в `.agent/archive/tasks/`, в манифесте остаётся
> one-liner с `"status": "archived"`.
## Критерии завершения фазы
- [ ] Цель разбита на атомарные задачи
- [ ] Для каждой задачи указаны acceptance criteria
- [ ] Для каждой задачи указаны affected files
- [ ] Зависимости между задачами корректны (нет циклов)
- [ ] Invariant-задачи созданы для каждого ADR (если config требует)
- [ ] `.agent/task-manifest.json` и `.agent/task-manifest.md` созданы
- [ ] checkpoints.json обновлён
-142
View File
@@ -1,142 +0,0 @@
# Протокол 03: Архитектурное проектирование (DESIGN)
## Цель
Спроектировать архитектуру, модули, данные и интерфейсы для greenfield/scaffold-проекта.
DESIGN выполняется **только** для `project_type = greenfield` или `scaffold`. Для existing-проектов пропускается.
## Вход
- `.agent/context/analysis-report.md` (project_type: greenfield или scaffold)
- `.agent/roadmap/sources.md` (опционально)
- `.agent/checkpoints.json` (фаза design: pending)
- `.agent/rules/project-rules.md` — прочитать первым
## Правила
1. **Реалистичность** — архитектура реализуема за 1 сессию (до 10 задач).
2. **Документируемость** — каждый модуль, модель и интерфейс описывается в `design-report.md`.
3. **Тестируемость** — каждый компонент проектируется с учётом тестирования.
4. **Итеративность** — первая версия минимально рабочая (MVP), расширения — отдельными задачами.
## Шаги
### 3.1. Прочитать правила проекта
Прочитать `.agent/rules/project-rules.md`, применить.
### 3.2. Технологический стек
Если стек не указан в README — предложить обоснованный выбор. Если указан — зафиксировать.
Для каждого компонента:
- Язык и версия
- Фреймворк / библиотека
- База данных (движок, схема)
- Инфраструктура (Docker, CI/CD, хостинг)
### 3.3. High-level архитектура
- **Паттерн** — монолит, модульный монолит, микросервисы, слоистая, луковая.
- **Компоненты** — что делает каждый модуль/сервис.
- **Схема взаимодействия** — текстовое описание потоков данных.
```
[Client] → HTTP → [API Gateway] → [Auth Service]
↓
[Core Service] → [Database]
↓
[External API] → [3rd Party]
```
### 3.4. Модули
| Поле | Описание |
|---|---|
| Имя модуля | `app/services/cashflow.py` |
| Ответственность | Что делает |
| Ключевые классы/функции | Сигнатуры без реализации |
| Зависимости | Какие модули нужны |
| Контракт | Что экспортирует |
### 3.5. Модели данных
Описать сущности, поля, связи:
```json
{
"entity": "Transaction",
"fields": [
{"name": "id", "type": "UUID", "pk": true},
{"name": "amount", "type": "Decimal"},
{"name": "date", "type": "datetime"},
{"name": "category_id", "type": "UUID", "fk": "Category"}
]
}
```
### 3.6. API интерфейсы
| Метод | Путь | Описание | Request | Response | Статусы |
|---|---|---|---|---|---|
| GET | /transactions | Список | ?page, ?limit | [Transaction] | 200 |
| POST | /transactions | Создать | CreateTransactionDTO | Transaction | 201, 400 |
Если GUI — ключевые страницы. Если CLI — команды.
### 3.7. Обработка ошибок
- Стратегия: исключения / Result / коды.
- Формат API-ошибок: `{ "error": "...", "code": "...", "details": {} }`.
- Логирование: уровни для разных событий.
### 3.8. Стратегия тестирования
- Какие тесты нужны (unit, integration, e2e).
- Как изолировать зависимости.
- Команда запуска тестов.
### 3.9. Группировка в задачи
Предварительно наметить задачи по модулям — вход для DECOMPOSITION:
```
T1: Инициализация проекта + зависимости
T2: Модель данных (сущности, миграции)
T3: Service (core logic)
T4: API endpoints
T5: Tests
```
### 3.10. Создать design-report
Записать `.agent/context/design-report.md` по шаблону `TEMPLATES/design-report.md`.
### 3.11. Дополнительно (по команде пользователя)
Эти шаги **не выполняются автоматически** — только если пользователь явно попросил:
- **ADR** — вызвать `COMMANDS/adr.md` для ключевых решений.
- **Alternative Architecture** — вызвать `COMMANDS/alt-arch.md` для сравнения.
- **Risk Register** — вызвать `COMMANDS/risk-register.md` для допущений.
- **Red Team** — вызвать `COMMANDS/red-team.md` для атаки на дизайн.
## Выход
- `.agent/context/design-report.md`
- Предварительная группировка задач (для DECOMPOSITION)
- Возможно: ADR, risk-register, alt-architecture, red-team-report (если вызывали команды)
- `checkpoints.json: phases.design = "completed"`
## Критерии завершения
- [ ] Стек определён
- [ ] High-level архитектура описана
- [ ] Модули и их ответственность описаны
- [ ] Модели данных спроектированы
- [ ] API/интерфейсы описаны (если применимо)
- [ ] Стратегия тестирования определена
- [ ] Задачи предварительно сгруппированы
- [ ] `design-report.md` создан
- [ ] `checkpoints.json` обновлён
-117
View File
@@ -1,117 +0,0 @@
# Протокол 04: Декомпозиция задач (DECOMPOSITION)
## Цель
Разбить цель пользователя (и архитектурный план, если есть) на атомарные, независимо выполнимые задачи. Записать в `manifest.json` + `manifest.md`.
## Вход
- `.agent/context/analysis-report.md`
- `.agent/context/design-report.md` (опционально — для greenfield)
- `.agent/roadmap/sources.md` (опционально)
- `.agent/decisions/*.md` (опционально)
- Цель пользователя (goal из `checkpoints.json`)
- `.agent/rules/project-rules.md` — прочитать первым
- `.agent/checkpoints.json` (фаза decomposition: pending)
## Принципы
1. **Атомарность** — одна задача = одна логическая единица, выполнимая и проверяемая за один подход.
2. **Независимость (макс.)** — минимизировать зависимости между задачами.
3. **Тестируемость** — каждая задача имеет измеримые acceptance criteria.
4. **Границы** — задача не выходит за пределы `BOUNDARIES.md`.
5. **Порядок** — задачи с зависимостями выполняются строго последовательно.
## Шаги
### 4.1. Прочитать правила проекта
Прочитать `.agent/rules/project-rules.md`, применить.
### 4.2. Размер задачи
Задача должна укладываться в **1-2 часа работы агента**. Если крупнее — разбить.
Признак слишком крупной задачи:
- Нельзя сформулировать acceptance criteria одной строкой.
- Затрагивает 5+ файлов.
- Содержит союзы «и», «а также», «после чего».
### 4.3. Сверить с roadmap
Если существует `.agent/roadmap/sources.md`:
- Задачи из roadmap получают приоритет P0-P3 в соответствии с `sources.md`.
- Задачи без явного источника получают `origin: "decomposition"`.
### 4.4. Структура задачи
| Поле | Описание | Пример |
|---|---|---|
| `id` | Уникальный идентификатор | `T1`, `T2` |
| `title` | Что сделать | "Добавить модель User" |
| `description` | Как и зачем | "Создать SQLAlchemy модель..." |
| `type` | Тип | `feature`, `refactor`, `test`, `fix`, `config`, `design`, `docs`, `invariant` |
| `status` | Статус | `pending`, `in_progress`, `completed`, `failed`, `archived` |
| `origin` | Источник | `roadmap:file`, `adr:NNN`, `user:direct`, `agent:analysis`, `decomposition` |
| `files` | Файлы | `["app/models/user.py"]` |
| `depends_on` | Зависимости | `[]` или `["T0"]` |
| `acceptance_criteria` | 3-5 измеримых пунктов | `["Модель проходит миграцию"]` |
| `context` | Доп. информация | `"Смотри app/models/base.py"` |
**Типы origin:**
- `roadmap:{filename}` — из FUTURE/ или roadmap
- `adr:{NNN}` — из Architecture Decision Record
- `user:direct` — от пользователя
- `agent:analysis` — выявлено агентом
- `decomposition` — создано при декомпозиции
- `invariant:{adr_id}` — инвариант для ADR (создаётся командой `/invariant-tests`)
- `risk:{R-NNN}` — из Risk Register
### 4.5. Зелёная декомпозиция (greenfield/scaffold)
Если есть `design-report.md` — задачи на основе группировки из дизайна:
1. **T1: init** — инициализация, зависимости, scaffold.
2. **T2..Tn: features** — модули по одному.
3. **Tn+1: tests** — тесты (можно в составе feature).
4. **Tn+2: polish** — документация, форматирование.
### 4.6. Сортировка
Задачи в манифесте в порядке выполнения:
1. Без зависимостей.
2. Чьи зависимости уже выполнены.
3. С наибольшим числом зависимостей.
### 4.7. Записать manifest
Создать `.agent/tasks/manifest.json` по шаблону `TEMPLATES/task-manifest.json`.
Создать `.agent/tasks/manifest.md` по шаблону `TEMPLATES/task-manifest.md`.
### 4.8. Обновить checkpoints
```json
{
"phases": { "decomposition": "completed" },
"tasks": [...],
"last_updated": "<timestamp>"
}
```
## Выход
- `.agent/tasks/manifest.json`
- `.agent/tasks/manifest.md`
- Обновлённый `checkpoints.json`
## Критерии завершения
- [ ] Цель разбита на атомарные задачи
- [ ] У каждой задачи — acceptance criteria, origin, files
- [ ] Зависимости корректны (нет циклов)
- [ ] Задачи сверены с roadmap (если `sources.md` существует)
- [ ] `manifest.json` и `manifest.md` созданы
- [ ] `checkpoints.json` обновлён
@@ -0,0 +1,126 @@
# Протокол 04: Настройка окружения (SETUP)
## Цель
Обеспечить рабочее окружение, в котором исполнительный агент может сразу выполнять задачи.
## Вход
- `.agent/analysis-report.md`
- `.agent/design-report.md` (опционально, для greenfield)
- `.agent/task-manifest.json`
- `.agent/checkpoints.json` (фаза environment: pending)
## Поведение в зависимости от типа проекта
Фаза SETUP работает по-разному для `existing` и `greenfield/scaffold` проектов.
---
## Ветка A: existing/scaffold проект
### 4A.1. Зависимости
- Установить все зависимости согласно документации проекта
- Если есть `requirements.txt`, `pyproject.toml`, `package.json`, `Cargo.toml` и т.д. — выполнить установку
- Если в проекте используется виртуальное окружение (venv, .venv, conda) — активировать или создать
- Если в проекте используется Docker — проверить, что образ собирается
**Правило:** если установка зависимостей требует нестандартных шагов, описанных в README — строго следовать им. Если шаги не описаны — запросить у пользователя.
### 4A.2. Конфигурация
- Проверить наличие конфигурационных файлов (`.env.example`, `.env`, `config.yaml`)
- Если есть `.env.example`, скопировать в `.env` с настройками по умолчанию
- Если проекту требуется БД — проверить строку подключения, при необходимости создать БД или использовать SQLite для разработки
- Настроить pre-commit хуки, если они есть в проекте
### 4A.3. Линтеры и форматтеры
- Запустить линтер на всём проекте: записать результат
- Если линтер выдаёт ошибки — не исправлять, только зафиксировать в отчёте
- Убедиться, что исполнительный агент может запускать линтер (записать команду)
### 4A.4. Baseline-тесты
- Запустить все тесты проекта
- Записать в `.agent/baseline-test-report.log`:
- Команда запуска
- Общее количество тестов
- Пройдено / упало / пропущено
- Время выполнения
- Список упавших тестов (если есть)
- Если тесты не проходят — указать это в отчёте, но **не исправлять**
### 4A.5. Сборка проекта
- Выполнить полную сборку/компиляцию проекта
- Записать результат (успех/ошибка с логом)
- Сборка должна проходить без ошибок. Если не собирается — остановиться, сообщить пользователю.
---
## Ветка B: greenfield проект
### 4B.1. Инициализация проекта
- Создать базовую структуру директорий согласно design-report.md
- Инициализировать пакетный менеджер:
- Python: `pyproject.toml` (poetry, pdm, hatch) или `requirements.txt`
- Node: `package.json` и `npm init` / `yarn init`
- Go: `go mod init`
- Rust: `cargo init`
- Настроить базовый конфиг: `.env.example`, `config/` и т.д.
- Настроить линтер/форматтер: `ruff`, `eslint`, `gofmt` и т.д.
### 4B.2. Scaffold-код
Создать пустые заглушки для модулей, описанных в design-report:
```python
# app/services/cashflow.py — заглушка
class CashflowService:
"""TBD — реализация в задаче T3"""
pass
```
Назначение: фиксировать структуру, чтобы исполнительный агент не думал о ней, а сразу писал реализацию.
### 4B.3. Установка зависимостей
- Установить базовые зависимости согласно стеку из design-report
- Если проект использует БД — установить драйвер/ORM
- Если проект использует API — установить фреймворк (FastAPI, Express и т.д.)
- Установить dev-зависимости: линтер, тестовый раннер, type stubs
### 4B.4. Базовые тесты (scaffold)
- Создать пустой тестовый файл для каждого модуля
- Настроить тестовый раннер (pytest, jest и т.д.)
- Записать в `.agent/baseline-test-report.log`: "0 tests — greenfield, scaffold готов"
### 4B.5. Проверка сборки
- Убедиться, что проект импортируется без ошибок
- Убедиться, что линтер проходит (без кода он должен проходить)
- Убедиться, что тестовый раннер запускается (0 tests, exit code 0)
---
## Выход
- Работоспособное окружение / инициализированный проект
- `.agent/baseline-test-report.log` — результат прогона тестов
- `.agent/setup-report.log` — лог установки зависимостей и сборки
Обновить checkpoints.json: `phases.environment = "completed"`.
## Критерии завершения фазы
- [ ] Зависимости установлены / проект инициализирован
- [ ] Проект собирается / импортируется без ошибок
- [ ] Baseline-тесты запущены, результат записан
- [ ] `.agent/baseline-test-report.log` и `.agent/setup-report.log` созданы
- [ ] checkpoints.json обновлён
Если проект не собирается — **фаза считается проваленной**, checkpoints.json отмечает `phases.environment = "failed"`, управление возвращается пользователю.
-136
View File
@@ -1,136 +0,0 @@
# Протокол 05: Исполнение задач (EXECUTION)
## Цель
Выполнить задачи из `manifest.json`: реализовать код, написать тесты, закоммитить, создать request — артефакт результата.
EXECUTION — **циклическая** фаза. Работает, пока есть задачи со статусом `pending` и выполненными `depends_on`.
## Вход
- `.agent/tasks/manifest.json`
- `.agent/context/analysis-report.md`
- `.agent/context/design-report.md` (опционально)
- `.agent/decisions/*.md` (опционально)
- `.agent/rules/project-rules.md` — прочитать первым
- `.agent/checkpoints.json` (фаза execution: pending)
## Шаги (цикл)
### 5.1. Прочитать правила проекта
Прочитать `.agent/rules/project-rules.md`, применить.
### 5.2. Setup окружения (первый запуск)
Если это первый запуск EXECUTION в сессии:
- Установить зависимости через штатный пакетный менеджер.
- Запустить сборку / базовые тесты.
- Записать baseline в `.agent/context/baseline-test-report.log`.
### 5.3. Выбрать задачу
Найти в `manifest.json` задачу, удовлетворяющую:
- `status: "pending"`
- Все `depends_on` имеют `status: "completed"` или `"archived"`.
Если таких нет — EXECUTION завершён, перейти к ожиданию команды пользователя.
### 5.4. Заблокировать задачу
В `manifest.json`:
```json
{ "id": "T1", "status": "in_progress" }
```
### 5.5. Исполнить
- Следовать конвенциям проекта (из ANALYSE).
- Соблюдать `BOUNDARIES.md`.
- Если задача ссылается на ADR — следовать архитектурному решению.
- Писать код + тесты.
### 5.6. Верифицировать
- Запустить тесты (все или релевантные).
- Проверить LSP diagnostics на изменённых файлах.
- Убедиться, что acceptance criteria выполнены.
### 5.7. Закоммитить
Сделать git-коммит. Сообщение — суть задачи.
### 5.8. Создать request
Создать `.agent/requests/active/req-{task_id}.json` по шаблону `TEMPLATES/request.json`:
```json
{
"request_id": "req-T1",
"task_id": "T1",
"title": "GET /health endpoint",
"status": "ready_for_review",
"goal": "Добавить ручку GET /health с тестами",
"changes": {
"summary": "Создан health router, подключён в main.py, написаны тесты",
"commits": ["abc1234"],
"files_changed": ["app/routers/health.py", "app/main.py", "tests/test_health.py"]
},
"verification": {
"tests_passed": "24/24",
"lsp_clean": true
},
"fulfills_ac": ["Ручка возвращает 200 + {\"status\":\"ok\"}"]
}
```
Request фиксирует:
- **summary** — суть изменений (не diff).
- **commits** — ссылки на коммиты.
- **files_changed** — какие файлы.
- **verification** — тесты + LSP.
- **fulfills_ac** — какие acceptance criteria закрыты.
### 5.9. Завершить задачу
```json
{ "id": "T1", "status": "completed" }
```
### 5.10. Цикл
Перейти к шагу 5.3. Если задач больше нет — сообщить пользователю и ожидать команду (METASTATE, новая задача, или завершение).
## Request как единица результата
Не просто «задача сделана», а документированный результат. Request проходит ревью в фазе METASTATE:
- `ready_for_review` → после проверки → `approved` или `rejected`.
## Команды во время EXECUTION
В любой момент цикла пользователь может вызвать:
- **/adr** — зафиксировать архитектурное решение, появившееся в процессе.
- **/red-team** — попытаться сломать текущий подход.
- **/risk-register** — зафиксировать новый риск.
Команды не прерывают EXECUTION, но могут добавить задачи в manifest.
## Выход
- Выполненные задачи в `manifest.json` (status: completed)
- `.agent/requests/active/req-{task_id}.json` для каждой выполненной задачи
- Обновлённый `checkpoints.json`
## Критерии завершения (одна итерация)
- [ ] Acceptance criteria выполнены
- [ ] Тесты проходят
- [ ] LSP diagnostics чист
- [ ] Коммит создан
- [ ] Request создан в `.agent/requests/active/`
- [ ] Задача в `manifest.json` отмечена completed
+188
View File
@@ -0,0 +1,188 @@
# Протокол 05: Передача исполнительному агенту (HANDOFF)
## Цель
Подготовить и передать исполнительному агенту полный контекст для работы: задачи, окружение, правила.
## Вход
- `.agent/analysis-report.md`
- `.agent/design-report.md` (опционально, для greenfield)
- `.agent/layer-1/adr/*.md` (опционально)
- `.agent/layer-1/risk-register.md` (опционально)
- `.agent/layer-1/red-team-report.md` (опционально)
- `.agent/task-manifest.json`
- `.agent/task-manifest.md`
- `.agent/baseline-test-report.log`
- `.agent/checkpoints.json` (все предыдущие фазы: completed)
## Шаги
### 5.1. Архивация завершённых артефактов
Перед валидацией и передачей выполнить архивирование.
**Архивировать завершённые задачи:**
Для каждой задачи в `task-manifest.json` со статусом `completed`:
1. Создать `.agent/archive/tasks/<id>.json` — перенести полное описание задачи (все поля)
2. В `task-manifest.json` заменить задачу на one-liner:
```json
{ "id": "<id>", "title": "<title>", "status": "archived" }
```
**Архивировать чекпоинты:**
Если `checkpoints.json` уже существует — сохранить предыдущую версию в `.agent/archive/checkpoints/<last_updated>.json`.
**Создать индекс архива:**
```json
{
"version": "1.1.0",
"archived_at": "<timestamp>",
"tasks": [
{ "id": "T1", "title": "...", "archived_at": "<timestamp>" }
],
"checkpoints": [
{ "file": "checkpoints/2026-07-15T10-00-00.json", "archived_at": "<timestamp>" }
]
}
```
### 5.2. Валидация
Перед передачей проверить:
- [ ] Все фазы отмечены как `completed` в checkpoints.json
- [ ] `.agent/` содержит все обязательные файлы:
- `checkpoints.json`
- `analysis-report.md`
- `task-manifest.json` + `task-manifest.md`
- `baseline-test-report.log`
- `setup-report.log`
- `src/META_AGENT_GUIDE.md`
- `src/BOUNDARIES.md`
- `src/VERSION`
- `src/PROTOCOLS/`
- `src/TEMPLATES/`
- `rules/project-rules.md`
- `archive/index.json`
- [ ] Для greenfield: `design-report.md` присутствует
- [ ] В task-manifest.json нет циклических зависимостей
- [ ] Все acceptance criteria сформулированы измеримо
- [ ] Для каждой задачи указаны affected files
- [ ] В репозитории нет незакоммиченных изменений (кроме `.agent/`)
- [ ] `.agent/src/` содержит актуальные исходники MetaAgent (META_AGENT_GUIDE.md, PROTOCOLS/, TEMPLATES/, BOUNDARIES.md, VERSION)
- [ ] `AGENTS.md` присутствует в корне репозитория
- [ ] `.agent/rules/` содержит `project-rules.md`
**Дополнительные проверки (если config включает):**
- [ ] ADR присутствуют (если adr=yes)
- [ ] Risk Register заполнен (если risk_register=yes)
- [ ] Red Team Report есть (если red_team=yes)
- [ ] Invariant-задачи в манифесте (если invariant_tests=yes)
### 5.3. Layer-структура .agent/
Если `config.layer_structure = yes`, организовать артефакты по слоям:
```
.agent/
layer-0/
checkpoints.json # всегда (ядро)
session-summary.md # краткая сводка сессии (создаётся здесь)
layer-1/
adr/ # ADR (опционально)
risk-register.md # (опционально)
red-team-report.md # (опционально)
layer-2/
analysis-report.md
design-report.md
design-report.md
layer-3/
handoff-summary.md
task-manifest.json
task-manifest.md
baseline-test-report.log
setup-report.log
```
Если `layer_structure = no` — артефакты остаются плоскими в `.agent/`, как раньше.
### 5.4. Создать handoff-summary.md
Заполнить по шаблону `TEMPLATES/handoff-summary.md`:
- **Session Info** — ID, цель, дата
- **Configuration** — какие функции были включены, глубина
- **Repo Summary** — краткая выжимка из analysis-report
- **Environment Status** — результат сборки и тестов
- **Design Summary** (если есть design-report) — ключевые архитектурные решения
- **ADR Summary** (если adr=yes) — какие решения задокументированы
- **Risk Register** (если risk_register=yes) — основные допущения
- **Task Overview** — количество задач, типы, список
- **Next Steps** — с какой задачи начинать исполнительному агенту
- **Project Rules** — ссылка на `.agent/rules/project-rules.md` (передаётся exec-агенту)
- **Archive** — ссылка на `.agent/archive/index.json` (история завершённых задач)
- **Caveats** — известные проблемы, ограничения, неясные моменты
- **Checkpoints** — актуальное состояние чекпоинтов
### 5.5. Финализировать checkpoints
- Отметить `phases.handoff = "completed"`
- Записать финальный `last_updated`
### 5.6. Сигнал
Сообщить пользователю/оркестратору:
```
HANDOFF COMPLETE
Session: <session_id>
Target: <target_repo>
Type: <existing | greenfield | scaffold>
Config: depth=<N>, adr=<yes|no>, red_team=<yes|no>, ...
Tasks: <count> tasks ready
Исполнительный агент может начинать с задачи <T1>.
Контекст: .agent/handoff-summary.md
Манифест: .agent/task-manifest.json
```
## Что получает исполнительный агент
1. **Целевой репозиторий** — полностью настроенный, с установленными зависимостями
2. **`.agent/`** — директория со всеми артефактами (layer-структура или плоская)
3. **`task-manifest.json`** — машиночитаемый список задач
4. **`task-manifest.md`** — человекочитаемый список задач
5. **`handoff-summary.md`** — итоговая сводка
6. **`checkpoints.json`** — актуальное состояние (исполнительный агент будет его обновлять)
7. **`layer-1/adr/*.md`** (опционально) — ключевые решения
8. **`layer-1/risk-register.md`** (опционально) — допущения
9. **`layer-2/analysis-report.md`** — полный анализ репозитория (справочно)
10. **`layer-2/design-report.md`** (только для greenfield) — архитектурный план
11. **`layer-3/baseline-test-report.log`** — baseline тестов (чтобы не сломать существующее)
12. **`.agent/src/`** — полные исходники MetaAgent (справочно, всегда присутствуют)
13. **`.agent/rules/`** — пользовательские правила проекта
14. **`AGENTS.md`** — инструкция для AI-агента в корне проекта (всегда присутствует)
15. **`.agent/archive/`** — архив завершённых задач, чекпоинтов и устаревших артефактов
## Выход
- `.agent/layer-0/session-summary.md` (если layer_structure=yes)
- `.agent/layer-3/handoff-summary.md`
- `.agent/layer-0/checkpoints.json` (финальный)
- `.agent/archive/index.json` (создаётся при архивации)
## Критерии завершения
- [ ] Все артефакты на месте (с учётом layer-структуры)
- [ ] `.agent/src/` содержит актуальные исходники MetaAgent
- [ ] `.agent/rules/` содержит `project-rules.md`
- [ ] `AGENTS.md` присутствует в корне репозитория
- [ ] `.agent/archive/index.json` создан, завершённые задачи архивированы
- [ ] handoff-summary.md заполнен (включая config, design summary, ADR summary, archive)
- [ ] checkpoints.json финализирован
- [ ] Сигнал отправлен пользователю/оркестратору
-145
View File
@@ -1,145 +0,0 @@
# Протокол 06: Обновление метасостояния (METASTATE)
## Цель
По команде пользователя провести ревью накопленных requests, синхронизировать манифест, обновить слепок проекта и подготовить `.agent/` как полную картину для следующей сессии.
## Когда запускать
По команде пользователя:
- «обнови метасостояние»
- «update metastate»
- «подведи итог»
- «заверши сессию»
Может запускаться многократно — после каждой группы выполненных задач.
## Вход
- `.agent/requests/active/` — все request-ы со статусом `ready_for_review`
- `.agent/tasks/manifest.json`
- `.agent/context/project-state.md` (создан в ANALYSE, обновляется здесь)
- `.agent/roadmap/sources.md`
- `.agent/decisions/index.json`
- `.agent/checkpoints.json`
## Шаги
### 6.1. Собрать requests
Прочитать все файлы из `.agent/requests/active/` со статусом `ready_for_review`.
### 6.2. Ревью каждого request
Для каждого:
1. **Верифицировать** — тесты проходят, LSP чист, AC выполнены, коммиты на месте.
2. **Принять или отклонить:**
- ✅ **approved**:
- Переместить в `.agent/requests/archive/`.
- В `manifest.json` убедиться: `status: "completed"`.
- ❌ **rejected**:
- Оставить в `active/` с комментарием.
- В `manifest.json`: `status: "reopened"`, добавить `rejection_reason`.
- В request добавить `rejection_reason`.
### 6.3. Архивация завершённых задач
Для каждой `completed` задачи:
1. Создать `.agent/archive/tasks/{id}.json` — полное описание.
2. В `manifest.json` заменить на one-liner:
```json
{ "id": "T1", "title": "GET /health endpoint", "status": "archived", "origin": "user:direct" }
```
### 6.4. Обновить project-state
Переписать `.agent/context/project-state.md` с учётом выполненных задач:
- Обновить список модулей (добавлены / изменены).
- Обновить архитектурную схему (кратко).
- Обновить статус тестов.
- Добавить новые ADR.
- Убрать закрытые concerns.
**Цель:** следующий агент читает `project-state.md` и понимает проект, не открывая исходники.
### 6.5. Обновить roadmap
В `.agent/roadmap/sources.md`:
- Отметить выполненные пункты.
- Пересчитать приоритеты.
- Добавить новые источники (если появились).
### 6.6. Индекс архива
Создать/обновить `.agent/archive/index.json`:
```json
{
"version": "3.0.0",
"archived_at": "<timestamp>",
"tasks": [{ "id": "T1", "title": "...", "archived_at": "<timestamp>" }],
"requests": [{ "id": "req-T1", "task_id": "T1", "archived_at": "<timestamp>" }],
"checkpoints": [{ "file": "checkpoints/<ts>.json", "archived_at": "<timestamp>" }]
}
```
### 6.7. Создать handoff-summary
Создать `.agent/handoff-summary.md` — полная сводка для следующего агента:
```markdown
## Session Summary
**Session:** <id>
**Goal:** <goal>
**Completed:** N tasks
**Pending:** M tasks
**Approved requests:** req-T1, req-T2
## Project State
(краткая выжимка из project-state.md)
## Next Steps
(с чего начать следующую сессию)
## Key Artifacts
- Project state: `.agent/context/project-state.md`
- Tasks: `.agent/tasks/manifest.json`
- Roadmap: `.agent/roadmap/sources.md`
- Pending reviews: `.agent/requests/active/`
- Archive: `.agent/archive/index.json`
```
### 6.8. Обновить checkpoints
```json
{ "phases": { "metastate": "completed" }, "last_updated": "<timestamp>" }
```
## Выход
- `.agent/requests/archive/` — подтверждённые request-ы
- `.agent/archive/tasks/{id}.json` — архив задач
- Обновлённый `.agent/context/project-state.md`
- Обновлённый `.agent/roadmap/sources.md`
- `.agent/handoff-summary.md`
- `.agent/archive/index.json`
- Финальный `checkpoints.json`
## Критерии завершения
- [ ] Все `ready_for_review` requests проверены (approved / rejected)
- [ ] Approved перемещены в archive
- [ ] Completed задачи архивированы (one-liner в manifest)
- [ ] `project-state.md` отражает актуальное состояние
- [ ] `roadmap/sources.md` обновлён
- [ ] `archive/index.json` создан
- [ ] `handoff-summary.md` готов
- [ ] `checkpoints.json` финализирован
-113
View File
@@ -1,113 +0,0 @@
# Протокол 07: Завершение сессии (HANDOFF)
## Цель
Финализация сессии: валидация структуры `.agent/`, финальный `session-summary.md`, отметка `phases.handoff = "completed"`.
> Если перед HANDOFF был METASTATE — архивация, project-state, handoff-summary уже готовы. HANDOFF только валидирует и финализирует.
## Вход
- `.agent/checkpoints.json` (все фазы кроме handoff: completed или skipped)
- Все артефакты `.agent/`
## Шаги
### 7.1. Проверить: был ли METASTATE?
Если существуют `.agent/handoff-summary.md` и `.agent/context/project-state.md` (обновлён) — METASTATE выполнен. Перейти к шагу 7.3.
Если нет — выполнить лёгкую архивацию (шаг 7.2).
### 7.2. Лёгкая архивация (если METASTATE не было)
Если есть `completed` задачи в `manifest.json`:
- Архивировать в `.agent/archive/tasks/{id}.json`.
- Заменить в `manifest.json` на one-liner.
- Создать `.agent/archive/index.json`.
### 7.3. Валидация
Проверить:
- [ ] Все фазы в `checkpoints.json` отмечены `completed` или `skipped`.
- [ ] `.agent/` содержит обязательные файлы:
- `checkpoints.json`
- `context/analysis-report.md`
- `context/project-state.md`
- `tasks/manifest.json` + `manifest.md`
- `rules/project-rules.md`
- `src/GUIDE.md`
- `src/BOUNDARIES.md`
- `src/VERSION`
- `src/PROTOCOLS/`
- `src/COMMANDS/`
- `src/TEMPLATES/`
- [ ] В `manifest.json` нет циклических зависимостей.
- [ ] У каждой задачи — measurable acceptance criteria и origin.
- [ ] `AGENTS.md` присутствует в корне репозитория.
### 7.4. Создать session-summary
Создать `.agent/session-summary.md`:
```markdown
# Session Summary
**Session:** <id>
**MetaAgent version:** 3.0.0
**Date:** <timestamp>
**Goal:** <goal>
## Phases Executed
- [x] INIT
- [x] ANALYSE
- [x] ROADMAP
- [x] DESIGN (или skipped)
- [x] DECOMPOSITION
- [x] EXECUTION (N tasks)
- [x] METASTATE (или skipped)
- [x] HANDOFF
## Results
- Tasks completed: N
- Requests approved: N
- Files changed: [list]
## Next
Следующий агент: читай `.agent/handoff-summary.md`.
```
### 7.5. Финализировать checkpoints
```json
{ "phases": { "handoff": "completed" }, "last_updated": "<timestamp>" }
```
### 7.6. Сигнал
```
HANDOFF COMPLETE
Session: <session_id>
Target: <target_repo>
Type: <existing | greenfield | scaffold>
Tasks: <N> total, <M> completed, <K> pending
Следующий агент начинает с .agent/handoff-summary.md
```
## Выход
- `.agent/session-summary.md`
- Финальный `.agent/checkpoints.json`
- (если METASTATE не было) `.agent/archive/index.json`
## Критерии завершения
- [ ] Все артефакты на месте
- [ ] (если METASTATE не было) `completed` задачи архивированы
- [ ] `session-summary.md` создан
- [ ] `checkpoints.json` финализирован
- [ ] Сигнал отправлен пользователю
+26 -11
View File
@@ -15,7 +15,8 @@
- **Точка входа:** {{ entry_point }} - **Точка входа:** {{ entry_point }}
- **Система сборки:** {{ build_system }} - **Система сборки:** {{ build_system }}
## 2. Стек технологий (existing / scaffold) {% if project_type == "existing" or project_type == "scaffold" %}
## 2. Стек технологий
| Компонент | Значение | | Компонент | Значение |
|---|---| |---|---|
@@ -26,7 +27,7 @@
| Пакетный менеджер | {{ package_manager }} | | Пакетный менеджер | {{ package_manager }} |
| Линтер/форматтер | {{ linter }} | | Линтер/форматтер | {{ linter }} |
## 3. Архитектура (existing / scaffold) ## 3. Архитектура
``` ```
{{ directory_tree }} {{ directory_tree }}
@@ -40,7 +41,7 @@
|---|---| |---|---|
| {{ module }} | {{ description }} | | {{ module }} | {{ description }} |
## 4. Конвенции (existing / scaffold) ## 4. Конвенции
- **Стиль:** {{ code_style }} - **Стиль:** {{ code_style }}
- **Импорты:** {{ import_style }} - **Импорты:** {{ import_style }}
@@ -48,38 +49,52 @@
- **Обработка ошибок:** {{ error_handling }} - **Обработка ошибок:** {{ error_handling }}
- **Логирование:** {{ logging }} - **Логирование:** {{ logging }}
## 5. Тесты (existing / scaffold) ## 5. Тесты
- **Команда запуска:** `{{ test_command }}` - **Команда запуска:** `{{ test_command }}`
- **Всего тестов:** {{ total_tests }} - **Всего тестов:** {{ total_tests }}
- **Пройдено:** {{ passed }} - **Пройдено:** {{ passed }}
- **Упало:** {{ failed }} - **Упало:** {{ failed }}
- **Пропущено:** {{ skipped }} - **Пропущено:** {{ skipped }}
- **Упавшие тесты:** {{ failed_tests_list }} - **Упавшие тесты:**
{% for test in failed_tests %}
- `{{ test }}`
{% endfor %}
## 6. Базовая проверка (existing / scaffold) ## 6. Базовая проверка
- **Сборка:** {{ build_status }} - **Сборка:** {{ build_status }}
- **Запуск:** {{ run_status }} - **Запуск:** {{ run_status }}
- **Git status:** {{ git_status }} - **Git status:** {{ git_status }}
{% endif %}
## 7. Требования (greenfield / scaffold) {% if project_type == "greenfield" or project_type == "scaffold" %}
## 7. Требования (из README)
### Функциональные требования ### Функциональные требования
{{ functional_requirements_list }} {% for req in functional_requirements %}
- {{ req }}
{% endfor %}
### Нефункциональные требования ### Нефункциональные требования
{{ non_functional_requirements_list }} {% for req in non_functional_requirements %}
- {{ req }}
{% endfor %}
### Бизнес-контекст ### Бизнес-контекст
{{ business_context_list }} {% for item in business_context %}
- {{ item }}
{% endfor %}
### Неясные моменты / Вопросы ### Неясные моменты / Вопросы
{{ open_questions_list }} {% for question in open_questions %}
- {{ question }}
{% endfor %}
{% endif %}
## 8. Примечания ## 8. Примечания
+50 -10
View File
@@ -38,11 +38,36 @@
### Сущности ### Сущности
{{ entity_descriptions }} {% for entity in entities %}
### {{ entity.name }}
| Поле | Тип | Ограничения | Описание |
|---|---|---|---|
{% for field in entity.fields %}
| {{ field.name }} | {{ field.type }} | {{ field.constraints }} | {{ field.description }} |
{% endfor %}
**Связи:** {{ entity.relationships }}
{% endfor %}
## 5. API / Интерфейсы ## 5. API / Интерфейсы
{{ api_endpoints_table }} {% if has_api %}
| Метод | Путь | Описание | Request | Response |
|---|---|---|---|---|
{% for endpoint in api_endpoints %}
| {{ endpoint.method }} | {{ endpoint.path }} | {{ endpoint.description }} | {{ endpoint.request }} | {{ endpoint.response }} |
{% endfor %}
{% endif %}
{% if has_gui %}
**Экраны:** {{ gui_screens }}
{% endif %}
{% if has_cli %}
**Команды:** {{ cli_commands }}
{% endif %}
## 6. Обработка ошибок ## 6. Обработка ошибок
@@ -57,16 +82,31 @@
- **Mock-стратегия:** {{ mock_strategy }} - **Mock-стратегия:** {{ mock_strategy }}
- **Команда запуска:** `{{ test_command }}` - **Команда запуска:** `{{ test_command }}`
## 8. Дополнительные артефакты (по команде пользователя) ## 8. Alternative Architecture (если применимо)
Если пользователь вызвал соответствующие команды, добавить ссылки: | Критерий | Выбранная архитектура | Альтернатива |
|---|---|---|
| Название | {{ chosen_arch }} | {{ alt_arch }} |
| Сложность | {{ chosen_complexity }} | {{ alt_complexity }} |
| Почему не выбрана | — | {{ alt_rejection_reason }} |
- ADR: `.agent/decisions/` (команда `/adr`) ## 9. ADR Reference (если применимо)
- Alternative Architecture: `.agent/context/alt-architecture.md` (команда `/alt-arch`)
- Risk Register: `.agent/context/risk-register.md` (команда `/risk-register`)
- Red Team Review: `.agent/context/red-team-report.md` (команда `/red-team`)
## 9. Предварительная группировка задач | ID | Решение | Файл |
|---|---|---|
{% for adr in adr_list %}
| {{ adr.id }} | {{ adr.title }} | `{{ adr.path }}` |
{% endfor %}
## 10. Risk Register (если применимо)
| # | Assumption | Impact | Mitigation |
|---|---|---|---|
{% for risk in risk_list %}
| {{ risk.id }} | {{ risk.assumption }} | {{ risk.impact }} | {{ risk.mitigation }} |
{% endfor %}
## 11. Предварительная группировка задач
| Задача | Описание | Тип | | Задача | Описание | Тип |
|---|---|---| |---|---|---|
@@ -75,6 +115,6 @@
| T3 | {{ task_3 }} | feature | | T3 | {{ task_3 }} | feature |
| T4 | {{ task_4 }} | test | | T4 | {{ task_4 }} | test |
## 10. Примечания ## 12. Примечания
{{ notes }} {{ notes }}
+43 -16
View File
@@ -3,30 +3,43 @@
## Session Info ## Session Info
- **Session ID:** `{{ session_id }}` - **Session ID:** `{{ session_id }}`
- **Target Repo:** {{ target_repo }} - **Target Repo:** `{{ target_repo }}`
- **Goal:** {{ goal }} - **Goal:** {{ goal }}
- **Date:** {{ date }} - **Date:** {{ date }}
- **Project type:** {{ project_type }} - **Duration:** {{ duration }}
- **Depth:** {{ depth }}
- **Config:** {{ config_summary }}
## Repo Summary ## Repo Summary
{{ repo_summary }} {{ repo_summary }}
## Artifacts Created ## Project Type
- **Analysis report:** `.agent/context/analysis-report.md` - **Type:** {{ project_type }}
- **Project state:** `.agent/context/project-state.md` - **Design report:** {% if project_type == "greenfield" or project_type == "scaffold" %}`.agent/design-report.md`{% else %}—{% endif %}
- **Design report:** {{ design_report_path_or_dash }}
- **Roadmap:** `.agent/roadmap/sources.md` ## ADR Summary (если применимо)
- **ADR:** {{ adr_summary_or_dash }}
- **Risk Register:** {{ risk_register_path_or_dash }} {% if adr_count > 0 %}
- **Red Team Report:** {{ red_team_report_path_or_dash }} Создано ADR: {{ adr_count }}
{% for adr in adr_list %}
- `{{ adr.path }}` — {{ adr.title }}
{% endfor %}
{% endif %}
## Risk Register (если применимо)
{% if risk_count > 0 %}
Задокументировано допущений: {{ risk_count }}
Наиболее критичное: {{ top_risk }}
{% endif %}
## Environment Status ## Environment Status
- **Build:** {{ build_status }} - **Build:** {{ build_status }}
- **Tests:** {{ tests_passed }}/{{ tests_total }} passed - **Tests:** {{ tests_passed }}/{{ tests_total }} passed
- **Baseline log:** `.agent/context/baseline-test-report.log` - **Baseline log:** `.agent/baseline-test-report.log`
- **Dependencies:** {{ deps_status }} - **Dependencies:** {{ deps_status }}
## Task Overview ## Task Overview
@@ -37,21 +50,35 @@
| Pending | {{ pending }} | | Pending | {{ pending }} |
| In Progress | {{ in_progress }} | | In Progress | {{ in_progress }} |
| Completed | {{ completed }} | | Completed | {{ completed }} |
| Archived | {{ archived }} |
| Failed/Skipped | {{ failed }} | | Failed/Skipped | {{ failed }} |
**Task by type:**
{% for type, count in tasks_by_type %}
- {{ type }}: {{ count }}
{% endfor %}
## Tasks (ordered) ## Tasks (ordered)
{{ task_list_markdown }} {% for task in tasks %}
### {{ task.id }}: {{ task.title }}
- Type: {{ task.type }}
- Depends on: {{ task.depends_on | default("—") }}
- Files: {{ task.files | join(", ") }}
- Status: {{ task.status }}
{% endfor %}
## Next Steps ## Next Steps
Следующий агент: прочитай `.agent/context/project-state.md`, затем `.agent/tasks/manifest.json` и приступай к первой `pending` задаче. Исполнительный агент начинает с задачи **{{ first_task }}**.
## Caveats ## Caveats
{{ caveats_list }} {% for caveat in caveats %}
- {{ caveat }}
{% endfor %}
## Checkpoints ## Checkpoints
Файл: `.agent/checkpoints.json` — состояние фаз и список задач. Файл: `.agent/checkpoints.json`
Актуальное состояние чекпоинтов прилагается.
+38
View File
@@ -0,0 +1,38 @@
# MetaAgent Request
# Для ручного заполнения перед запуском MetaAgent.
# Поместите этот файл в .agent/metaagent-request.md целевого репозитория.
# Если файл отсутствует — MetaAgent проведёт интервью (PROTOCOLS/00_CONFIG.md).
# Ответьте "default" на любой вопрос — будет использовано значение по умолчанию.
## Параметры сессии
| Функция | Вкл | Аргументы |
|---|---|---|
| ANALYSIS | ✓ | — |
| DESIGN | ✓ | adr=yes, alternative_arch=yes |
| RED_TEAM | ✗ | — |
| RISK_REGISTER | ✗ | — |
| DECOMPOSITION | ✓ | invariant_tests=yes |
| SETUP | ✓ | — |
| HANDOFF | ✓ | layer_structure=yes |
## Глубина проработки
**Значение:** 6 (1-10)
| Уровень | Название | Описание |
|---|---|---|
| 1-2 | Scaffold | Только структура проекта + пустые модули |
| 3-4 | Light | (default) Быстрый дизайн + задачи без расширений |
| 5-6 | Standard | Полный ANALYSIS→DESIGN→DECOMP→SETUP→HANDOFF |
| 7-8 | Deep | Standard + ADR, Risk Register, Alternative Architecture |
| 9-10 | Maximum | Deep + Red Team Review, Executable Invariants |
## Цель
Сформулируйте задачу для MetaAgent.
## Дополнительно
- **Boundaries:** (опционально) ограничения, которые нельзя нарушать
- **Target:** путь к репозиторию или URL
-43
View File
@@ -1,43 +0,0 @@
# Project State
# Auto-generated — updated by ANALYSE (initial) and METASTATE (on updates)
**Last updated:** {{ timestamp }}
**Session:** {{ session_id }}
## Project Type
{{ project_type }}
## Tech Stack
| Category | Technology |
|----------|-----------|
| Language | {{ language }} |
| Framework | {{ framework }} |
| Database | {{ database }} |
| Test runner | {{ test_runner }} |
| Package manager | {{ package_manager }} |
## Current Architecture
{{ architecture_description }}
## Key Modules
| Module | Status | Description |
|--------|--------|-------------|
| {{ module_name }} | {{ existing / stub / new }} | {{ module_description }} |
## Decisions in Effect
| ADR | Decision | Status |
|-----|----------|--------|
| {{ adr_id }} | {{ decision_summary }} | {{ active / superseded }} |
## Testing Status
{{ testing_summary }}
## Open Concerns
- {{ concern_1 }}
-29
View File
@@ -1,29 +0,0 @@
{
"$schema": ".agent/src/TEMPLATES/schemas/request-schema.json",
"template_version": "1.0",
"request_id": "req-{{ task_id }}",
"task_id": "{{ task_id }}",
"title": "{{ task_title }}",
"status": "ready_for_review",
"created_at": "{{ timestamp }}",
"goal": "{{ task_goal }}",
"changes": {
"summary": "{{ changes_summary }}",
"commits": [
"{{ commit_hash }}"
],
"files_changed": [
"path/to/file.py"
]
},
"verification": {
"tests_passed": "{{ test_results }}",
"lsp_clean": true
},
"fulfills_ac": [
"{{ acceptance_criterion }}"
]
}
-42
View File
@@ -1,42 +0,0 @@
# Roadmap Sources
# Auto-generated — created by ROADMAP phase
**Created:** {{ timestamp }}
**Session:** {{ session_id }}
## Priority Legend
- **P0** — Critical, do next
- **P1** — Important, do soon
- **P2** — Nice to have
- **P3** — Future / deferred
## Sources
### FUTURE Plans
| Plan | Priority | Status | Origin File |
|------|----------|--------|-------------|
| {{ plan_title }} | {{ P0-P3 }} | {{ active / archived }} | FUTURE/{{ filename }}.md |
### ADR-Derived Tasks
| Source ADR | Task | Priority |
|------------|------|----------|
| {{ adr_id }} | {{ task_description }} | {{ P0-P3 }} |
### User Requests
| Request | Priority | Source |
|---------|----------|--------|
| {{ request }} | {{ P0-P3 }} | {{ direct / issue / feedback }} |
### Agent-Identified Improvements
| Observation | Suggested Task | Priority |
|-------------|----------------|----------|
| {{ observation }} | {{ task }} | {{ P0-P3 }} |
## Consolidated Priority Queue
1. **{{ task_title }}** ({{ origin }}) — {{ priority }}
@@ -1,66 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "metaagent/checkpoints/3.0.0",
"title": "MetaAgent Checkpoints",
"description": "Schema for .agent/checkpoints.json — session state",
"type": "object",
"properties": {
"metaagent_version": {
"type": "string",
"description": "MetaAgent version that created this checkpoint",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
},
"session_id": {
"type": "string",
"description": "Unique session identifier"
},
"target_repo": {
"type": "string",
"description": "Path to the target repository"
},
"goal": {
"type": ["string", "null"],
"description": "Session goal (set by user, may be null until first task)"
},
"project_type": {
"type": ["string", "null"],
"enum": [null, "existing", "greenfield", "scaffold"],
"description": "Type of the target project (set in ANALYSE phase)"
},
"phases": {
"type": "object",
"properties": {
"init": { "type": "string", "enum": ["pending", "in_progress", "completed", "failed", "skipped"] },
"analyse": { "type": "string", "enum": ["pending", "in_progress", "completed", "failed", "skipped"] },
"roadmap": { "type": "string", "enum": ["pending", "in_progress", "completed", "failed", "skipped"] },
"design": { "type": "string", "enum": ["pending", "in_progress", "completed", "failed", "skipped"] },
"decomposition": { "type": "string", "enum": ["pending", "in_progress", "completed", "failed", "skipped"] },
"execution": { "type": "string", "enum": ["pending", "in_progress", "completed", "failed", "skipped"] },
"metastate": { "type": "string", "enum": ["pending", "in_progress", "completed", "failed", "skipped"] },
"handoff": { "type": "string", "enum": ["pending", "in_progress", "completed", "failed", "skipped"] }
},
"additionalProperties": false
},
"tasks": {
"type": "array",
"description": "List of tasks (one-liners after archiving)",
"items": {
"type": "object",
"properties": {
"id": { "type": "string" },
"title": { "type": "string" },
"status": { "type": "string", "enum": ["pending", "in_progress", "completed", "failed", "archived"] }
},
"required": ["id", "title", "status"],
"additionalProperties": false
}
},
"last_updated": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp of last update"
}
},
"required": ["metaagent_version", "session_id", "phases", "last_updated"],
"additionalProperties": false
}
@@ -1,60 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "metaagent/decisions-index/3.0.0",
"title": "MetaAgent Decisions Index",
"description": "Schema for .agent/decisions/index.json — machine-readable index of ADRs",
"type": "object",
"properties": {
"version": {
"type": "string",
"description": "Schema version (3.0 in v3.0+, 2.0 still valid from v2.1)",
"enum": ["2.0", "3.0"]
},
"decisions": {
"type": "array",
"description": "List of architecture decision records",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9]{3,}$",
"description": "ADR number (001, 002, ...)"
},
"title": {
"type": "string",
"description": "Short title of the decision"
},
"status": {
"type": "string",
"enum": ["proposed", "accepted", "deprecated", "superseded"],
"description": "ADR status"
},
"file": {
"type": "string",
"description": "Filename in .agent/decisions/ (e.g. 001-stack.md)"
},
"date": {
"type": "string",
"format": "date",
"description": "Decision date (ISO 8601)"
}
},
"required": ["id", "title", "file"],
"additionalProperties": false
}
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp of index creation"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp of last update"
}
},
"required": ["version", "decisions"],
"additionalProperties": false
}
@@ -1,95 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "metaagent/task-manifest/3.0.0",
"title": "MetaAgent Task Manifest",
"description": "Schema for .agent/tasks/manifest.json — the global task manifest",
"type": "object",
"properties": {
"version": {
"type": "string",
"description": "Schema version",
"enum": ["3.0"]
},
"session_id": {
"type": "string",
"description": "Session ID that created this manifest"
},
"goal": {
"type": "string",
"description": "Overall goal of the session"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp of creation"
},
"tasks": {
"type": "array",
"description": "List of tasks",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^(T[0-9]+|T-INV-[0-9]+)$",
"description": "Unique task identifier (T1, T2, ... or T-INV-N for invariants)"
},
"title": {
"type": "string",
"description": "Task title"
},
"description": {
"type": "string",
"description": "Detailed description"
},
"type": {
"type": "string",
"enum": ["feature", "refactor", "test", "fix", "config", "design", "docs", "invariant"],
"description": "Task type"
},
"origin": {
"type": "string",
"description": "Task source (roadmap:file, adr:NNN, user:direct, agent:analysis, decomposition, invariant:NNN, risk:R-NNN)"
},
"files": {
"type": "array",
"items": { "type": "string" },
"description": "Files affected by this task"
},
"depends_on": {
"type": "array",
"items": { "type": "string" },
"description": "Task IDs this task depends on"
},
"acceptance_criteria": {
"type": "array",
"items": { "type": "string" },
"description": "Measurable criteria for completion"
},
"context": {
"type": "string",
"description": "Additional context or references"
},
"status": {
"type": "string",
"enum": ["pending", "in_progress", "completed", "failed", "archived"],
"description": "Current task status"
},
"claimed_by": {
"type": "string",
"description": "Worker ID if claimed"
},
"claimed_at": {
"type": "string",
"format": "date-time",
"description": "When the task was claimed"
}
},
"required": ["id", "title", "type", "status"],
"additionalProperties": false
}
}
},
"required": ["version", "tasks"],
"additionalProperties": false
}
+18 -33
View File
@@ -2,49 +2,34 @@
**Session:** {{ session_id }} **Session:** {{ session_id }}
**Target:** {{ target_repo }} **Target:** {{ target_repo }}
**MetaAgent version:** {{ version }} **Depth:** {{ depth }}
**Date:** {{ date }} **Date:** {{ date }}
## Configuration
| Функция | Статус |
|---|---|
| ADR | {{ adr_enabled }} |
| Alternative Architecture | {{ alt_arch_enabled }} |
| Red Team | {{ red_team_enabled }} |
| Risk Register | {{ risk_register_enabled }} |
| Invariant Tests | {{ invariant_tests_enabled }} |
| Layer Structure | {{ layer_structure_enabled }} |
## Phase Status ## Phase Status
| Phase | Status | | Phase | Status |
|---|---| |---|---|
| INIT | {{ init_status }} | | ANALYSIS | {{ analysis_status }} |
| ANALYSE | {{ analyse_status }} |
| ROADMAP | {{ roadmap_status }} |
| DESIGN | {{ design_status }} | | DESIGN | {{ design_status }} |
| RED_TEAM | {{ red_team_status }} |
| DECOMPOSITION | {{ decomposition_status }} | | DECOMPOSITION | {{ decomposition_status }} |
| EXECUTION | {{ execution_status }} | | SETUP | {{ setup_status }} |
| METASTATE | {{ metastate_status }} |
| HANDOFF | {{ handoff_status }} | | HANDOFF | {{ handoff_status }} |
## Tasks
| Status | Count |
|---|---|
| Total | {{ total }} |
| Pending | {{ pending }} |
| In Progress | {{ in_progress }} |
| Completed | {{ completed }} |
| Archived | {{ archived }} |
| Failed/Skipped | {{ failed }} |
**By origin:**
- user:direct: {{ user_direct_count }}
- roadmap: {{ roadmap_count }}
- adr: {{ adr_count }}
- decomposition: {{ decomposition_count }}
- (другое): {{ other_count }}
## Commands Invoked (если были)
{{ commands_invoked_list }}
## Quick Links ## Quick Links
- Task Manifest: `.agent/tasks/manifest.json` - Task Manifest: `.agent/task-manifest.json`
- Handoff Summary: `.agent/handoff-summary.md` - Handoff Summary: `.agent/handoff-summary.md`
- Project State: `.agent/context/project-state.md` - Design Report: `.agent/analysis-report.md`
- ADR: `.agent/decisions/` - ADR: `.agent/layer-1/adr/` (если есть)
- Risk Register: `.agent/context/risk-register.md`
- Red Team Report: `.agent/context/red-team-report.md`
+3 -4
View File
@@ -1,6 +1,6 @@
{ {
"$schema": ".agent/src/TEMPLATES/schemas/task-manifest-schema.json", "$schema": "metaagent-task-manifest",
"version": "3.0", "version": "1.0",
"session_id": "{{ session_id }}", "session_id": "{{ session_id }}",
"goal": "{{ goal }}", "goal": "{{ goal }}",
"created_at": "{{ timestamp }}", "created_at": "{{ timestamp }}",
@@ -9,8 +9,7 @@
"id": "T1", "id": "T1",
"title": "{{ task_title }}", "title": "{{ task_title }}",
"description": "{{ task_description }}", "description": "{{ task_description }}",
"type": "feature|refactor|test|fix|config|design|docs|invariant", "type": "feature|refactor|test|fix|config|docs",
"origin": "user:direct",
"files": ["path/to/file1.py", "path/to/file2.py"], "files": ["path/to/file1.py", "path/to/file2.py"],
"depends_on": [], "depends_on": [],
"acceptance_criteria": [ "acceptance_criteria": [
+1 -1
View File
@@ -1 +1 @@
3.0.0 1.1.0
+298 -182
View File
@@ -1,240 +1,356 @@
# WORKFLOW — Сквозной пример сессии v3.0 # WORKFLOW — Сквозной пример сессии
--- ---
## Сценарий: рефакторинг auth-модуля ## Сценарий A: Existing проект
**Цель:** Вынести логику из `auth/login.py` (450 строк, монолит) в отдельные модули `auth/router.py`, `auth/schemas.py`, `auth/deps.py`. **Цель:** Добавить в существующий FastAPI-проект ручку GET /health с тестами.
**Целевой репозиторий:** `github.com/example/fastapi-app` **Целевой репозиторий:** `github.com/example/fastapi-app`
**Пользователь:** «Вынеси авторизацию в отдельные модули». **Пользователь:** "Добавь health-check endpoint и тесты к нему"
**MetaAgent:** v3.0.0
--- ---
### PROJECT LOOP ### Фаза INIT
#### INIT Мета-агент читает `.agent/metaagent-request.md`, клонирует репозиторий, создаёт `.agent/`, пишет начальный чекпоинт:
Агент читает `AGENTS.md`, переходит в `.agent/src/GUIDE.md`. Понимает цикл. Создаёт `.agent/`, копирует исходники, инициализирует `checkpoints.json`:
```json ```json
{ {
"metaagent_version": "3.0.0", "metaagent_version": "1.1.0",
"session_id": "ses_v30_001", "session_id": "ses_abc123",
"target_repo": "/tmp/fastapi-app", "target_repo": "/tmp/fastapi-app",
"goal": "Вынести авторизацию в auth/{router,schemas,deps}.py", "goal": "Добавить GET /health с тестами",
"project_type": null, "project_type": "existing",
"config": {
"depth": 6,
"design": { "adr": false, "alternative_arch": false },
"red_team": false,
"risk_register": false,
"decomposition": { "invariant_tests": false },
"handoff": { "layer_structure": false }
},
"phases": { "phases": {
"init": "completed", "analysis": "pending",
"analyse": "pending",
"roadmap": "pending",
"design": "pending", "design": "pending",
"red_team": "pending",
"decomposition": "pending", "decomposition": "pending",
"execution": "pending", "environment": "pending",
"metastate": "pending",
"handoff": "pending" "handoff": "pending"
}, },
"tasks": [], "tasks": [],
"last_updated": "2026-10-08T15:00:00Z" "last_updated": "2026-07-12T15:00:00Z"
} }
``` ```
#### ANALYSE ---
Агент сканирует проект: ### Фаза ANALYSE
- Стек: Python 3.12, FastAPI, SQLAlchemy, pytest. Мета-агент выполняет `PROTOCOLS/01_ANALYSIS.md`. Определяет тип проекта: `existing`.
- `auth/login.py` — 450 строк, монолит (цель рефакторинга).
- Тесты: 48 passed (baseline).
Создаёт: Результат `.agent/analysis-report.md`:
- `.agent/context/analysis-report.md`
- `.agent/context/project-state.md` (начальный)
`checkpoints.json`: `project_type = "existing"`, `phases.analyse = "completed"`.
#### ROADMAP
- `FUTURE/` — пусто.
- `.agent/decisions/` — пусто.
- Единственный источник — пользовательский запрос.
Создаёт `.agent/roadmap/sources.md`:
```markdown ```markdown
## User Requests ## 2. Стек технологий
| Вынести авторизацию | P0 | user:direct | | Язык | Python 3.12 |
| Фреймворк | FastAPI |
| Тестовый раннер | pytest + httpx |
| Пакетный менеджер | pip + requirements.txt |
## Consolidated Priority Queue ## 3. Архитектура
1. Вынести auth/ (user:direct) — P0 ├── app/
│ ├── main.py
│ ├── routers/
│ │ └── users.py
│ ├── models/
│ │ └── user.py
│ └── schemas/
│ └── user.py
├── tests/
│ └── test_users.py
``` ```
`phases.roadmap = "completed"`. Тесты запущены: **12 passed, 0 failed**.
#### DESIGN Чекпоинт обновлён: `analysis = "completed"`, `project_type = "existing"`.
Фаза DESIGN пропускается.
**Пропускается** (existing-проект). `phases.design = "skipped"`.
#### DECOMPOSITION
Задачи:
```json
{
"tasks": [
{
"id": "T1",
"title": "Создать auth/router.py",
"origin": "user:direct",
"files": ["app/auth/router.py"],
"depends_on": [],
"acceptance_criteria": [
"Роуты авторизации вынесены из auth/login.py",
"auth/router.py экспортирует router",
"Существующие тесты проходят"
],
"status": "pending"
},
{
"id": "T2",
"title": "Создать auth/schemas.py",
"origin": "user:direct",
"files": ["app/auth/schemas.py"],
"depends_on": ["T1"],
"acceptance_criteria": [
"Pydantic схемы вынесены в auth/schemas.py",
"Существующие тесты проходят"
],
"status": "pending"
},
{
"id": "T3",
"title": "Создать auth/deps.py",
"origin": "user:direct",
"files": ["app/auth/deps.py"],
"depends_on": ["T1"],
"acceptance_criteria": [
"Dependency injection функции вынесены в auth/deps.py",
"Существующие тесты проходят"
],
"status": "pending"
}
]
}
```
`phases.decomposition = "completed"`.
--- ---
### WORK LOOP (первая итерация) ### Фаза DECOMPOSITION
#### EXECUTION — задача T1 Мета-агент выполняет `PROTOCOLS/03_DECOMPOSITION.md`.
1. Берёт T1 (`pending`, нет зависимостей). Декомпозиция цели "Добавить GET /health с тестами":
2. `status = "in_progress"`.
3. Создаёт `app/auth/router.py` — переносит роуты. | ID | Задача | Тип | Зависит от | AC |
4. Тесты: 48/48. |---|---|---|---|---|
5. Коммит: `abc1234 — refactor: extract auth router`. | T1 | Создать health-check router | feature | — | Ручка возвращает 200 + {"status":"ok"} |
6. Создаёт request: | T2 | Подключить router в main.py | config | T1 | Ручка доступна по /health |
| T3 | Написать тесты для /health | test | T2 | Тесты проверяют 200 и структуру ответа |
Создан `.agent/task-manifest.json` и `.agent/task-manifest.md`.
Чекпоинт обновлён: `decomposition = "completed"`. Tasks: T1-T3 со статусом `pending`.
---
### Фаза SETUP
Мета-агент выполняет `PROTOCOLS/04_ENVIRONMENT_SETUP.md` (ветка A: existing).
- `pip install -r requirements.txt` — OK
- Запуск pytest — OK, 12 passed (базовый тест)
- Результат в `.agent/baseline-test-report.log`
Чекпоинт обновлён: `environment = "completed"`.
---
### Фаза HANDOFF
Мета-агент выполняет `PROTOCOLS/05_HANDOFF.md`.
Создан `.agent/handoff-summary.md`:
```markdown
## Next Steps
Исполнительный агент начинает с задачи T1: "Создать health-check router".
## Caveats
- Придерживаться стиля существующего роутера users.py
- Не менять существующие тесты
- Убедиться, что response model соответствует JSON: {"status": "ok"}
```
Чекпоинт финализирован:
```json ```json
{ {
"request_id": "req-T1", "metaagent_version": "1.1.0",
"task_id": "T1", "session_id": "ses_abc123",
"title": "Создать auth/router.py", "goal": "Добавить GET /health с тестами",
"status": "ready_for_review", "project_type": "existing",
"goal": "Вынести роуты авторизации", "config": {
"changes": { "depth": 6,
"summary": "Роуты авторизации вынесены из auth/login.py в auth/router.py", "design": { "adr": false, "alternative_arch": false },
"commits": ["abc1234"], "red_team": false,
"files_changed": ["app/auth/router.py", "app/auth/__init__.py", "tests/test_auth_router.py"] "risk_register": false,
"decomposition": { "invariant_tests": false },
"handoff": { "layer_structure": false }
}, },
"verification": { "tests_passed": "48/48", "lsp_clean": true }, "phases": {
"fulfills_ac": ["Роуты вынесены", "Тесты проходят"] "analysis": "completed",
"design": "skipped",
"red_team": "skipped",
"decomposition": "completed",
"environment": "completed",
"handoff": "completed"
},
"tasks": [
{ "id": "T1", "title": "Создать health-check router", "status": "pending" },
{ "id": "T2", "title": "Подключить router в main.py", "status": "pending" },
{ "id": "T3", "title": "Написать тесты для /health", "status": "pending" }
],
"last_updated": "2026-07-12T15:15:00Z"
} }
``` ```
7. `T1 → completed`. Сигнал пользователю:
#### EXECUTION — задача T2
Создаёт `auth/schemas.py`, request `req-T2`. T2 → completed.
#### EXECUTION — задача T3
Создаёт `auth/deps.py`, request `req-T3`. T3 → completed.
Задачи закончились. Агент ждёт команду.
---
### METASTATE (по команде пользователя)
**Пользователь:** «обнови метасостояние».
1. **Ревью requests:** три request-а, все approved.
- `req-T1`, `req-T2`, `req-T3` → `.agent/requests/archive/`.
2. **Архивация задач:**
- T1, T2, T3 → `.agent/archive/tasks/`.
- В `manifest.json` — one-liner: `status: "archived"`.
3. **Обновление project-state.md:**
```markdown
## Key Modules
| Module | Status | Description |
|--------|--------|-------------|
| app/auth/router.py | new | Вынесенные роуты |
| app/auth/schemas.py | new | Pydantic схемы |
| app/auth/deps.py | new | Dependency injection |
```
4. **Создание handoff-summary.md:**
```markdown
## Session Summary
**Goal:** Рефакторинг авторизации
**Completed:** 3/3 tasks
**Approved requests:** req-T1, req-T2, req-T3
## Project State
auth разбит на router + schemas + deps.
Исходный auth/login.py: 450 → 120 строк.
## Next Steps
- Проверить, не осталось ли прямых импортов из старого login.py
- Обновить main.py если нужно
```
---
### HANDOFF
``` ```
HANDOFF COMPLETE HANDOFF COMPLETE
Session: ses_abc123
Session: ses_v30_001
Target: /tmp/fastapi-app Target: /tmp/fastapi-app
Type: existing Type: existing
Tasks: 3/3 completed Tasks: 3 tasks ready
Следующий агент начинает с .agent/handoff-summary.md Исполнительный агент может начинать с задачи T1.
``` ```
--- ---
## Использование команд в процессе ## Сценарий B: Greenfield проект (Cashflow Forecasting)
В любой момент сессии пользователь мог вызвать: **Цель:** Спроектировать и реализовать MVP сервиса прогнозирования денежных потоков.
- **«запиши это как ADR»** → `COMMANDS/adr.md` создал бы `.agent/decisions/001-modular-auth.md`. **Целевой репозиторий:** `github.com/example/cashflow-app`
- **«red team»** → `COMMANDS/red-team.md` создал бы `.agent/context/red-team-report.md` с попыткой сломать новую структуру.
- **«risk register»** → `COMMANDS/risk-register.md` зафиксировал бы допущения (например, «считаем, что порядок middleware не важен»).
Команды **не обязательны**. Если не вызваны — `.agent/decisions/`, `risk-register.md`, `red-team-report.md` не создаются. **README:** README содержит описание:
> Сервис для прогнозирования движения денежных средств (cashflow forecasting).
> Пользователь загружает CSV с транзакциями, сервис строит прогноз на N дней вперёд.
> Стек: Python, FastAPI, SQLite, matplotlib для графиков.
---
### Фаза INIT
```json
{
"metaagent_version": "1.1.0",
"session_id": "ses_def456",
"target_repo": "/tmp/cashflow-app",
"goal": "Спроектировать и реализовать MVP сервиса прогнозирования денежных потоков",
"project_type": "greenfield",
"config": {
"depth": 7,
"design": { "adr": true, "alternative_arch": true },
"red_team": false,
"risk_register": true,
"decomposition": { "invariant_tests": true },
"handoff": { "layer_structure": true }
},
"phases": {
"analysis": "pending",
"design": "pending",
"red_team": "pending",
"decomposition": "pending",
"environment": "pending",
"handoff": "pending"
},
"tasks": [],
"last_updated": "2026-07-12T16:00:00Z"
}
```
---
### Фаза ANALYSE
Мета-агент выполняет `PROTOCOLS/01_ANALYSIS.md`. Определяет тип проекта: `greenfield`.
Сканирование корня: пусто (кроме README.md, LICENSE, .gitignore).
Извлечение требований из README:
| Тип | Требование |
|---|---|
| Функциональное | Загрузка CSV с транзакциями |
| Функциональное | Прогноз на N дней вперёд |
| Нефункциональное | Python, FastAPI |
| Нефункциональное | SQLite |
| Нефункциональное | matplotlib для графиков |
Чекпоинт: `analysis = "completed"`, `project_type = "greenfield"`.
Так как проект greenfield — мета-агент переходит к фазе DESIGN.
---
### Фаза DESIGN
Мета-агент выполняет `PROTOCOLS/02_DESIGN.md`.
Результат `.agent/design-report.md`:
```markdown
## 1. Технологический стек
| Язык | Python 3.12 |
| Фреймворк | FastAPI + Pydantic |
| БД | SQLite + SQLAlchemy |
| Визуализация | matplotlib |
| Тесты | pytest |
## 2. Архитектура
[Client] → HTTP → [FastAPI] → [CashflowService] → [SQLite]
↓
[ForecastEngine] → [matplotlib]
## 3. Модули
| Модуль | Ответственность |
|---|---|
| app/main.py | Точка входа, роуты |
| app/models/transaction.py | Модель транзакции |
| app/services/cashflow.py | Бизнес-логика |
| app/services/forecast.py | Алгоритм прогноза |
| app/services/upload.py | Парсинг CSV |
| app/schemas/ | Pydantic схемы |
## 4. Модели
Transaction: id, date, amount, category, description
## 5. API
POST /upload — загрузить CSV
GET /forecast?days=30 — прогноз + график
## 6. Задачи (pre-grouped)
T1: init — проект, зависимости, scaffold
T2: models — модели + миграции
T3: upload — загрузка CSV
T4: forecast — алгоритм прогноза
T5: API — endpoints
T6: tests — тесты
```
Чекпоинт: `design = "completed"`.
---
### Фаза DECOMPOSITION
Мета-агент выполняет `PROTOCOLS/03_DECOMPOSITION.md`, используя design-report.
Итоговые задачи:
| ID | Задача | Тип | Зависит от |
|---|---|---|---|
| T1 | Инициализация проекта + зависимости | config | — |
| T2 | Модель Transaction + SQLAlchemy + SQLite | feature | T1 |
| T3 | Сервис загрузки и парсинга CSV | feature | T2 |
| T4 | ForecastEngine — алгоритм прогноза | feature | T2 |
| T5 | API endpoints + документация | feature | T3, T4 |
| T6 | Тесты (unit + integration) | test | T5 |
---
### Фаза SETUP
Мета-агент выполняет `PROTOCOLS/04_ENVIRONMENT_SETUP.md` (ветка B: greenfield).
- `poetry init` + создание pyproject.toml
- Установка fastapi, uvicorn, sqlalchemy, matplotlib, pytest
- Создание scaffold-структуры: `app/models/`, `app/services/`, `app/schemas/`, `tests/`
- Пустые заглушки модулей
- `.agent/baseline-test-report.log`: "0 tests — greenfield, scaffold готов"
---
### Фаза HANDOFF
```markdown
HANDOFF COMPLETE
Session: ses_def456
Target: /tmp/cashflow-app
Type: greenfield
Config: depth=7, adr=yes, risk_register=yes, invariant_tests=yes
Tasks: 6 tasks ready
Исполнительный агент может начинать с задачи T1 (init).
Архитектурный план: .agent/design-report.md
ADR: .agent/layer-1/adr/
```
---
## После HANDOFF: работа исполнительного агента
Исполнительный агент читает `.agent/handoff-summary.md`, `.agent/task-manifest.json`, выполняет задачи по порядку, обновляя checkpoints.json после каждой.
После завершения всех задач:
```
ALL TASKS COMPLETE
Session: ses_def456
Tasks: 6/6 completed
T1: Инициализация проекта ✓
T2: Модель Transaction ✓
T3: Сервис загрузки CSV ✓
T4: ForecastEngine ✓
T5: API endpoints ✓
T6: Тесты ✓
Все тесты проходят: 24/24 passed.
```
+80 -282
View File
@@ -1,45 +1,29 @@
#!/usr/bin/env pwsh #!/usr/bin/env pwsh
# MetaAgent — установка исходников в целевой проект # MetaAgent — установка исходников в целевой проект
# Usage: .\install.ps1 [[-Path] target_path] [-Check] [-Update] # Usage: .\install.ps1 [[-Path] target_path] [-Update]
param( param(
[string]$Path = "", [string]$Path = "",
[switch]$Check,
[switch]$Update, [switch]$Update,
[switch]$Help [switch]$Help
) )
$MetaAgentSrc = Split-Path -Parent $MyInvocation.MyCommand.Path $MetaAgentSrc = Split-Path -Parent $MyInvocation.MyCommand.Path
# --- helpers ---
function Write-Info { Write-Host " →" -NoNewline -ForegroundColor Blue; Write-Host " $args" }
function Write-Ok { Write-Host " ✓" -NoNewline -ForegroundColor Green; Write-Host " $args" }
function Write-Skip { Write-Host " −" -NoNewline -ForegroundColor Yellow; Write-Host " $args" }
function Write-Warn { Write-Host " ⚠" -NoNewline -ForegroundColor Yellow; Write-Host " $args" }
function Write-Fail { Write-Host " ✗" -NoNewline -ForegroundColor Red; Write-Host " $args" }
function Write-Header { param([string]$Label)
Write-Host ""
Write-Host ("─" * 40)
Write-Host " $Label"
Write-Host ("─" * 40)
}
function Show-Usage { function Show-Usage {
@" @"
Usage: install.ps1 [[-Path] target_path] [-Check] [-Update] [-Help] Usage: install.ps1 [[-Path] target_path] [-Update] [-Help]
Install MetaAgent sources into <target>/.agent/src/ Install MetaAgent sources into <target>/.agent/src/
Options: Options:
-Path Path to target project (default: interactive prompt) -Path Path to target project (default: interactive prompt)
-Check Dry-run: only check target readiness, no install
-Update Overwrite existing files in .agent/src/ -Update Overwrite existing files in .agent/src/
-Help Show this help -Help Show this help
Examples: Examples:
.\install.ps1 .\install.ps1
.\install.ps1 -Path C:\Projects\MyApp .\install.ps1 -Path C:\Projects\MyApp
.\install.ps1 -Path C:\Projects\MyApp -Check
.\install.ps1 -Path C:\Projects\MyApp -Update .\install.ps1 -Path C:\Projects\MyApp -Update
"@ "@
exit 0 exit 0
@@ -47,319 +31,133 @@ Examples:
if ($Help) { Show-Usage } if ($Help) { Show-Usage }
# --- resolve target ---
$TargetPath = $Path $TargetPath = $Path
if (-not $TargetPath) { if (-not $TargetPath) {
$TargetPath = Read-Host "Enter path to target project" $TargetPath = Read-Host "Enter path to target project"
} }
$TargetPath = $TargetPath.Trim() $TargetPath = $TargetPath.Trim()
# --- pre-flight -----------------------------------------------------------
Write-Header "Pre-flight"
# 1. target exists?
if (-not (Test-Path $TargetPath -PathType Container)) { if (-not (Test-Path $TargetPath -PathType Container)) {
Write-Fail "Target directory '$TargetPath' does not exist." Write-Error "Directory '$TargetPath' does not exist."
exit 1 exit 1
} }
$TargetPath = (Resolve-Path $TargetPath).Path $TargetPath = (Resolve-Path $TargetPath).Path
Write-Ok "Target: $TargetPath"
# 2. write permission? (try to create a temp file as probe)
$probe = [System.IO.Path]::Combine($TargetPath, ".metaagent_probe.tmp")
try {
[System.IO.File]::WriteAllBytes($probe, [byte[]]@())
Remove-Item $probe -Force
Write-Ok "Write permission: yes"
} catch {
Write-Fail "No write permission on '$TargetPath'."
exit 1
}
# 3. already installed? compare versions
$AgentDir = Join-Path $TargetPath ".agent" $AgentDir = Join-Path $TargetPath ".agent"
$SrcDir = Join-Path $AgentDir "src" $SrcDir = Join-Path $AgentDir "src"
$VersionFile = Join-Path $MetaAgentSrc "VERSION"
$Version = if (Test-Path $VersionFile -PathType Leaf) {
(Get-Content $VersionFile -Raw -Encoding UTF8).Trim()
} else { "?" }
$oldVerPath = Join-Path $SrcDir "VERSION"
if (Test-Path $oldVerPath -PathType Leaf) {
$oldVer = (Get-Content $oldVerPath -Raw -Encoding UTF8).Trim()
if ($oldVer -ne $Version) {
Write-Info "Existing MetaAgent v$oldVer found → upgrading to v$Version"
} else {
Write-Skip "MetaAgent v${Version} already installed (use -Update to reinstall)"
if (-not $Check) {
Write-Warn "No changes applied. Run with -Update to overwrite existing files."
}
}
} else {
Write-Info "Fresh install: MetaAgent v$Version"
}
# 4. summary
$AgentsMd = Join-Path $TargetPath "AGENTS.md"
$RulesDir = Join-Path $AgentDir "rules" $RulesDir = Join-Path $AgentDir "rules"
$DecisionsDir = Join-Path $AgentDir "decisions" $ArchiveDir = Join-Path $AgentDir "archive"
$TasksDir = Join-Path $AgentDir "tasks" $VersionFile = Join-Path $MetaAgentSrc "VERSION"
$ContextDir = Join-Path $AgentDir "context" $Version = if (Test-Path $VersionFile) { Get-Content $VersionFile -Raw | ForEach-Object { $_.Trim() } } else { "?" }
$ArchiveDir = Join-Path $AgentDir "archive"
$RequestsDir = Join-Path $AgentDir "requests"
$RoadmapDir = Join-Path $AgentDir "roadmap"
$TempDir = Join-Path $TargetPath ".temp"
$DirList = @( New-Item -ItemType Directory -Path $SrcDir -Force | Out-Null
$SrcDir, $RulesDir, $DecisionsDir, $TasksDir, New-Item -ItemType Directory -Path $RulesDir -Force | Out-Null
(Join-Path $TasksDir "backlog"), $ContextDir, New-Item -ItemType Directory -Path $ArchiveDir -Force | Out-Null
$ArchiveDir, Write-Host "Installing MetaAgent v$Version → $SrcDir"
(Join-Path $ArchiveDir "tasks"),
(Join-Path $ArchiveDir "decisions"),
(Join-Path $ArchiveDir "checkpoints"),
(Join-Path $RequestsDir "active"),
(Join-Path $RequestsDir "archive"),
$RoadmapDir,
(Join-Path $RoadmapDir "archive"),
$TempDir
)
if ($Check) {
Write-Host ""
Write-Info "--check mode: all checks passed, no changes applied."
exit 0
}
# --- phase 1: directories ------------------------------------------------
Write-Header "Directories"
foreach ($d in $DirList) {
$null = New-Item -ItemType Directory -Path $d -Force
$short = $d.Replace("$TargetPath\", "")
if (Test-Path $d -PathType Container) {
Write-Ok $short
} else {
Write-Fail "$short (creation failed)"
}
}
# --- phase 2: files ------------------------------------------------------
Write-Header "Files"
$copyCount = 0
$skipCount = 0
$failCount = 0
# --- copy files ---
function Copy-File { function Copy-File {
param([string]$Src, [string]$DstDir) param([string]$Src, [string]$DstDir)
$name = Split-Path $Src -Leaf $name = Split-Path $Src -Leaf
$dst = Join-Path $DstDir $name
if (-not (Test-Path $Src -PathType Leaf)) { if (-not (Test-Path $Src -PathType Leaf)) {
Write-Skip "$name (source not found)" Write-Host " [skip] $name (not found)"
$script:skipCount++
return return
} }
$dst = Join-Path $DstDir $name
if ($Update -or -not (Test-Path $dst)) { if ($Update -or -not (Test-Path $dst)) {
try { Copy-Item $Src $dst -Force
Copy-Item $Src $dst -Force -ErrorAction Stop Write-Host " [copy] $name"
Write-Ok $name
$script:copyCount++
} catch {
Write-Fail $name
$script:failCount++
}
} else { } else {
Write-Skip "$name (exists, use -Update to overwrite)" Write-Host " [skip] $name (exists, use -Update to overwrite)"
$script:skipCount++
} }
} }
function Copy-Dir { function Copy-Dir {
param([string]$Src, [string]$DstDir) param([string]$Src, [string]$DstDir)
$name = Split-Path $Src -Leaf $name = Split-Path $Src -Leaf
$dst = Join-Path $DstDir $name
if (-not (Test-Path $Src -PathType Container)) { if (-not (Test-Path $Src -PathType Container)) {
Write-Skip "$name/ (source not found)" Write-Host " [skip] $name/ (not found)"
$script:skipCount++
return return
} }
$null = New-Item -ItemType Directory -Path $dst -Force $dst = Join-Path $DstDir $name
try { New-Item -ItemType Directory -Path $dst -Force | Out-Null
if ($Update) { if ($Update) {
Get-ChildItem $Src | ForEach-Object { Get-ChildItem $Src | ForEach-Object {
Copy-Item $_.FullName $dst -Recurse -Force -ErrorAction Stop Copy-Item $_.FullName $dst -Recurse -Force
} }
} else { } else {
Get-ChildItem $Src | ForEach-Object { Get-ChildItem $Src | ForEach-Object {
$targetPath = Join-Path $dst $_.Name $targetPath = Join-Path $dst $_.Name
if (-not (Test-Path $targetPath)) { if (-not (Test-Path $targetPath)) {
Copy-Item $_.FullName $dst -Recurse -ErrorAction Stop Copy-Item $_.FullName $dst -Recurse
}
} }
} }
Write-Ok "$name/"
$script:copyCount++
} catch {
Write-Fail "$name/ (partial copy)"
$script:failCount++
} }
Write-Host " [copy] $name/"
} }
Copy-File (Join-Path $MetaAgentSrc "GUIDE.md") $SrcDir Copy-File (Join-Path $MetaAgentSrc "META_AGENT_GUIDE.md") $SrcDir
Copy-File (Join-Path $MetaAgentSrc "BOUNDARIES.md") $SrcDir Copy-File (Join-Path $MetaAgentSrc "BOUNDARIES.md") $SrcDir
Copy-File (Join-Path $MetaAgentSrc "CHANGELOG.md") $SrcDir
Copy-File (Join-Path $MetaAgentSrc "WORKFLOW.md") $SrcDir Copy-File (Join-Path $MetaAgentSrc "WORKFLOW.md") $SrcDir
Copy-File (Join-Path $MetaAgentSrc "VERSION") $SrcDir Copy-File (Join-Path $MetaAgentSrc "VERSION") $SrcDir
Copy-Dir (Join-Path $MetaAgentSrc "PROTOCOLS") $SrcDir Copy-Dir (Join-Path $MetaAgentSrc "PROTOCOLS") $SrcDir
Copy-Dir (Join-Path $MetaAgentSrc "COMMANDS") $SrcDir
Copy-Dir (Join-Path $MetaAgentSrc "TEMPLATES") $SrcDir Copy-Dir (Join-Path $MetaAgentSrc "TEMPLATES") $SrcDir
Copy-File (Join-Path $MetaAgentSrc "install.sh") $SrcDir Copy-File (Join-Path $MetaAgentSrc "install.sh") $SrcDir
Copy-File (Join-Path $MetaAgentSrc "install.ps1") $SrcDir Copy-File (Join-Path $MetaAgentSrc "install.ps1") $SrcDir
# --- phase 3: AGENTS.md -------------------------------------------------- # --- create / update AGENTS.md in root of target ---
Write-Header "AGENTS.md" $AgentsMd = Join-Path $TargetPath "AGENTS.md"
function New-AgentsMd {
param([string]$Path)
@"
# MetaAgent
Этот проект использует [MetaAgent](.agent/src/META_AGENT_GUIDE.md) v$Version —
набор инструкций для AI-агента.
## Контекст MetaAgent
| Ресурс | Путь |
|--------|------|
| Главная инструкция | `.agent/src/META_AGENT_GUIDE.md` |
| Протоколы фаз | `.agent/src/PROTOCOLS/` |
| Шаблоны артефактов | `.agent/src/TEMPLATES/` |
| Границы (что разрешено/запрещено) | `.agent/src/BOUNDARIES.md` |
| Правила проекта | `.agent/rules/project-rules.md` |
| Примеры работы | `.agent/src/WORKFLOW.md` |
| Версия | `.agent/src/VERSION` |
## Состояние сессии (если инициализировано)
| Артефакт | Путь |
|----------|------|
| Чекпоинты сессии | `.agent/checkpoints.json` |
| Манифест задач | `.agent/task-manifest.json` |
| Сводка для exec-агента | `.agent/handoff-summary.md` |
| Анализ репозитория | `.agent/analysis-report.md` |
## Для исполнительного агента
1. **Прочитай** `.agent/src/META_AGENT_GUIDE.md` — пойми жизненный цикл MetaAgent.
2. **Прочитай** `.agent/src/BOUNDARIES.md` — соблюдай границы.
3. **Прочитай** `.agent/rules/project-rules.md` — выполни пользовательские правила.
4. **Проверь** `.agent/checkpoints.json` — если существует, используй как состояние сессии.
5. **Проверь** `.agent/task-manifest.json` — если существует, выполняй задачи по порядку.
6. Если `.agent/` не инициализирован или устарел — запусти `install.ps1 -Update` для
обновления исходников MetaAgent до актуальной версии.
"@
}
if (-not (Test-Path $AgentsMd -PathType Leaf)) { if (-not (Test-Path $AgentsMd -PathType Leaf)) {
$content = @" New-AgentsMd $AgentsMd | Out-File -FilePath $AgentsMd -Encoding utf8
# MetaAgent Write-Host " [create] AGENTS.md"
Этот проект использует [MetaAgent](.agent/src/GUIDE.md) v$Version —
набор инструкций для AI-агента.
## Контекст MetaAgent
| Ресурс | Путь |
|--------|------|
| Главная инструкция | `.agent/src/GUIDE.md` |
| Протоколы фаз | `.agent/src/PROTOCOLS/` |
| Команды (on-demand) | `.agent/src/COMMANDS/` |
| Шаблоны артефактов | `.agent/src/TEMPLATES/` |
| Границы (что разрешено/запрещено) | `.agent/src/BOUNDARIES.md` |
| История версий | `.agent/src/CHANGELOG.md` |
| Правила проекта | `.agent/rules/project-rules.md` |
| Пример работы | `.agent/src/WORKFLOW.md` |
| Версия | `.agent/src/VERSION` |
## Состояние сессии (если инициализировано)
| Артефакт | Путь |
|----------|------|
| Чекпоинты сессии | `.agent/checkpoints.json` |
| Слепок проекта | `.agent/context/project-state.md` |
| Анализ репозитория | `.agent/context/analysis-report.md` |
| Дорожная карта | `.agent/roadmap/sources.md` |
| Манифест задач | `.agent/tasks/manifest.json` |
| Сводка для следующего агента | `.agent/handoff-summary.md` |
| Сводка сессии | `.agent/session-summary.md` |
## Для агента
Жизненный цикл MetaAgent v$Version:
```
INIT → ANALYSE → ROADMAP → [DESIGN] → DECOMPOSITION → EXECUTION → METASTATE → HANDOFF
```
1. **Прочитай** `.agent/src/GUIDE.md` — пойми цикл и доступные команды.
2. **Прочитай** `.agent/src/BOUNDARIES.md` — соблюдай границы.
3. **Прочитай** `.agent/rules/project-rules.md` — выполни правила пользователя.
4. **Проверь** `.agent/checkpoints.json` — если существует, используй как состояние сессии.
5. **Проверь** `.agent/context/project-state.md` — получи актуальную картину.
6. **Проверь** `.agent/tasks/manifest.json` — если существует, выполняй задачи по порядку.
7. Если `.agent/` не инициализирован или устарел — запусти `install.sh --update` для
обновления исходников MetaAgent до актуальной версии.
## Команды (on-demand)
В любой момент пользователь может вызвать:
- `/adr` — записать архитектурное решение
- `/red-team` — попытаться сломать дизайн
- `/risk-register` — зафиксировать допущения
- `/alt-arch` — описать альтернативу
- `/invariant-tests` — тесты-инварианты для ADR
"@
$utf8 = [System.Text.Encoding]::UTF8
[System.IO.File]::WriteAllBytes($AgentsMd, $utf8.GetBytes($content))
Write-Ok "AGENTS.md created"
} elseif ($Update) { } elseif ($Update) {
$content = @" New-AgentsMd $AgentsMd | Out-File -FilePath $AgentsMd -Encoding utf8
# MetaAgent Write-Host " [update] AGENTS.md"
Этот проект использует [MetaAgent](.agent/src/GUIDE.md) v$Version —
набор инструкций для AI-агента.
## Контекст MetaAgent
| Ресурс | Путь |
|--------|------|
| Главная инструкция | `.agent/src/GUIDE.md` |
| Протоколы фаз | `.agent/src/PROTOCOLS/` |
| Команды (on-demand) | `.agent/src/COMMANDS/` |
| Шаблоны артефактов | `.agent/src/TEMPLATES/` |
| Границы (что разрешено/запрещено) | `.agent/src/BOUNDARIES.md` |
| История версий | `.agent/src/CHANGELOG.md` |
| Правила проекта | `.agent/rules/project-rules.md` |
| Пример работы | `.agent/src/WORKFLOW.md` |
| Версия | `.agent/src/VERSION` |
## Состояние сессии (если инициализировано)
| Артефакт | Путь |
|----------|------|
| Чекпоинты сессии | `.agent/checkpoints.json` |
| Слепок проекта | `.agent/context/project-state.md` |
| Анализ репозитория | `.agent/context/analysis-report.md` |
| Дорожная карта | `.agent/roadmap/sources.md` |
| Манифест задач | `.agent/tasks/manifest.json` |
| Сводка для следующего агента | `.agent/handoff-summary.md` |
| Сводка сессии | `.agent/session-summary.md` |
## Для агента
Жизненный цикл MetaAgent v$Version:
```
INIT → ANALYSE → ROADMAP → [DESIGN] → DECOMPOSITION → EXECUTION → METASTATE → HANDOFF
```
1. **Прочитай** `.agent/src/GUIDE.md` — пойми цикл и доступные команды.
2. **Прочитай** `.agent/src/BOUNDARIES.md` — соблюдай границы.
3. **Прочитай** `.agent/rules/project-rules.md` — выполни правила пользователя.
4. **Проверь** `.agent/checkpoints.json` — если существует, используй как состояние сессии.
5. **Проверь** `.agent/context/project-state.md` — получи актуальную картину.
6. **Проверь** `.agent/tasks/manifest.json` — если существует, выполняй задачи по порядку.
7. Если `.agent/` не инициализирован или устарел — запусти `install.sh --update` для
обновления исходников MetaAgent до актуальной версии.
## Команды (on-demand)
В любой момент пользователь может вызвать:
- `/adr` — записать архитектурное решение
- `/red-team` — попытаться сломать дизайн
- `/risk-register` — зафиксировать допущения
- `/alt-arch` — описать альтернативу
- `/invariant-tests` — тесты-инварианты для ADR
"@
$utf8 = [System.Text.Encoding]::UTF8
[System.IO.File]::WriteAllBytes($AgentsMd, $utf8.GetBytes($content))
Write-Ok "AGENTS.md updated"
} else { } else {
Write-Skip "AGENTS.md (exists, use -Update to overwrite)" Write-Host " [skip] AGENTS.md (exists, use -Update to overwrite)"
$script:skipCount++
} }
# --- summary -------------------------------------------------------------
Write-Header "Summary"
Write-Host " MetaAgent v$Version → $SrcDir"
Write-Host "" Write-Host ""
if ($copyCount -gt 0) { Write-Ok "$copyCount file(s) copied" } Write-Host "Done! MetaAgent v$Version installed at $SrcDir"
if ($skipCount -gt 0) { Write-Skip "$skipCount file(s) skipped" }
if ($failCount -gt 0) { Write-Fail "$failCount file(s) failed" }
Write-Host ""
if ($failCount -eq 0) {
Write-Ok "Installation completed successfully."
} else {
Write-Fail "Installation completed with $failCount error(s)."
exit 1
}
Executable → Regular
+38 -198
View File
@@ -1,242 +1,120 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# MetaAgent — установка исходников в целевой проект # MetaAgent — установка исходников в целевой проект
# Usage: ./install.sh [--check|--update] [target_path] # Usage: ./install.sh [--update] [target_path]
set -euo pipefail set -euo pipefail
METAAGENT_SRC="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" METAAGENT_SRC="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# --- helpers ---
red=; grn=; ylw=; blu=; rst=
if [[ -t 1 ]] && command -v tput >/dev/null 2>&1; then
red=$(tput setaf 1); grn=$(tput setaf 2)
ylw=$(tput setaf 3); blu=$(tput setaf 4)
rst=$(tput sgr0)
fi
info() { echo " ${blu}→${rst} $*"; }
ok() { echo " ${grn}✓${rst} $*"; }
skip() { echo " ${ylw}−${rst} $*"; }
warn() { echo " ${ylw}⚠${rst} $*"; }
fail() { echo " ${red}✗${rst} $*"; }
header(){ echo; echo "────────────────────────────────────────"; echo " $*"; echo "────────────────────────────────────────"; }
usage() { usage() {
cat <<EOF cat <<EOF
Usage: $0 [--check|--update] [target_path] Usage: $0 [--update] [target_path]
Install MetaAgent sources into <target>/.agent/src/ Install MetaAgent sources into <target>/.agent/src/
Options: Options:
--check, -c Dry-run: only check target readiness, no install
--update, -u Overwrite existing files in .agent/src/ --update, -u Overwrite existing files in .agent/src/
--help, -h Show this help --help, -h Show this help
Examples: Examples:
$0 $0
$0 /path/to/project $0 /path/to/project
$0 --check /path/to/project
$0 --update /path/to/project $0 --update /path/to/project
EOF EOF
exit 0 exit 0
} }
# --- arg parsing ---
CHECK=false
UPDATE=false UPDATE=false
TARGET_PATH="" TARGET_PATH=""
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
case "$1" in case "$1" in
--check|-c) CHECK=true; shift ;; --update|-u) UPDATE=true; shift ;;
--update|-u) UPDATE=true; shift ;; --help|-h) usage ;;
--help|-h) usage ;; --*) echo "Unknown option: $1"; usage ;;
--*) echo "${red}Unknown option:${rst} $1"; usage ;;
*) TARGET_PATH="$1"; shift ;; *) TARGET_PATH="$1"; shift ;;
esac esac
done done
# --- resolve target ---
if [[ -z "$TARGET_PATH" ]]; then if [[ -z "$TARGET_PATH" ]]; then
read -r -p "Enter path to target project: " TARGET_PATH read -r -p "Enter path to target project: " TARGET_PATH
fi fi
TARGET_PATH="${TARGET_PATH/#\~/$HOME}" TARGET_PATH="${TARGET_PATH/#\~/$HOME}"
# --- pre-flight -----------------------------------------------------------
header "Pre-flight"
# 1. target exists?
if [[ ! -d "$TARGET_PATH" ]]; then
fail "Target directory '$TARGET_PATH' does not exist."
exit 1
fi
# resolve to absolute path
TARGET_PATH="$(cd "$TARGET_PATH" 2>/dev/null && pwd)" || { TARGET_PATH="$(cd "$TARGET_PATH" 2>/dev/null && pwd)" || {
fail "Cannot access '$TARGET_PATH'." echo "Error: Directory '$TARGET_PATH' does not exist."
exit 1 exit 1
} }
ok "Target: $TARGET_PATH"
# 2. write permission?
if [[ ! -w "$TARGET_PATH" ]]; then
fail "No write permission on '$TARGET_PATH'."
exit 1
fi
ok "Write permission: yes"
# 3. already installed? compare versions
AGENT_DIR="$TARGET_PATH/.agent" AGENT_DIR="$TARGET_PATH/.agent"
SRC_DIR="$AGENT_DIR/src" SRC_DIR="$AGENT_DIR/src"
VERSION="$(cat "$METAAGENT_SRC/VERSION" 2>/dev/null || echo '?')" VERSION="$(cat "$METAAGENT_SRC/VERSION" 2>/dev/null || echo '?')"
if [[ -f "$SRC_DIR/VERSION" ]]; then
OLD_VER="$(cat "$SRC_DIR/VERSION" 2>/dev/null || echo '?')"
if [[ "$OLD_VER" != "$VERSION" ]]; then
info "Existing MetaAgent v${OLD_VER} found → upgrading to v${VERSION}"
else
skip "MetaAgent v${VERSION} already installed (use --update to reinstall)"
if [[ "$CHECK" == false ]]; then
warn "No changes applied. Run with --update to overwrite existing files."
fi
fi
else
info "Fresh install: MetaAgent v$VERSION"
fi
# 4. summary
AGENTS_MD="$TARGET_PATH/AGENTS.md"
RULES_DIR="$AGENT_DIR/rules" RULES_DIR="$AGENT_DIR/rules"
DECISIONS_DIR="$AGENT_DIR/decisions"
TASKS_DIR="$AGENT_DIR/tasks"
CONTEXT_DIR="$AGENT_DIR/context"
ARCHIVE_DIR="$AGENT_DIR/archive" ARCHIVE_DIR="$AGENT_DIR/archive"
ARCHIVE_TASKS_DIR="$ARCHIVE_DIR/tasks" mkdir -p "$SRC_DIR" "$RULES_DIR" "$ARCHIVE_DIR"
ARCHIVE_DECISIONS_DIR="$ARCHIVE_DIR/decisions" echo "Installing MetaAgent v$VERSION → $SRC_DIR"
ARCHIVE_CHECKPOINTS_DIR="$ARCHIVE_DIR/checkpoints"
REQUESTS_DIR="$AGENT_DIR/requests"
REQUESTS_ACTIVE_DIR="$REQUESTS_DIR/active"
REQUESTS_ARCHIVE_DIR="$REQUESTS_DIR/archive"
ROADMAP_DIR="$AGENT_DIR/roadmap"
ROADMAP_ARCHIVE_DIR="$ROADMAP_DIR/archive"
TEMP_DIR="$TARGET_PATH/.temp"
if [[ "$CHECK" == true ]]; then
echo ""
info "${ylw}--check mode:${rst} all checks passed, no changes applied."
exit 0
fi
# --- phase 1: directories ------------------------------------------------
header "Directories"
mkdir -p "$SRC_DIR" "$RULES_DIR" "$DECISIONS_DIR" "$TASKS_DIR" "$TASKS_DIR/backlog" \
"$CONTEXT_DIR" "$ARCHIVE_DIR" "$ARCHIVE_TASKS_DIR" "$ARCHIVE_DECISIONS_DIR" \
"$ARCHIVE_CHECKPOINTS_DIR" \
"$REQUESTS_ACTIVE_DIR" "$REQUESTS_ARCHIVE_DIR" \
"$ROADMAP_DIR" "$ROADMAP_ARCHIVE_DIR" \
"$TEMP_DIR"
for d in "$SRC_DIR" "$RULES_DIR" "$DECISIONS_DIR" "$TASKS_DIR" "$TASKS_DIR/backlog" \
"$CONTEXT_DIR" "$ARCHIVE_DIR" "$ARCHIVE_TASKS_DIR" "$ARCHIVE_DECISIONS_DIR" \
"$ARCHIVE_CHECKPOINTS_DIR" \
"$REQUESTS_ACTIVE_DIR" "$REQUESTS_ARCHIVE_DIR" \
"$ROADMAP_DIR" "$ROADMAP_ARCHIVE_DIR" \
"$TEMP_DIR"; do
short="${d#$TARGET_PATH/}"
if [[ -d "$d" ]]; then
ok "$short"
else
fail "$short (creation failed)"
fi
done
# --- phase 2: files ------------------------------------------------------
header "Files"
COPY_COUNT=0
SKIP_COUNT=0
FAIL_COUNT=0
# --- copy files ---
copy_file() { copy_file() {
local src="$1" dst_dir="$2" local src="$1" dst_dir="$2"
local name; name="$(basename "$src")" local name; name="$(basename "$src")"
local dst="$dst_dir/$name"
if [[ ! -f "$src" ]]; then if [[ ! -f "$src" ]]; then
skip "$name (source not found)" echo " [skip] $name (not found)"
SKIP_COUNT=$((SKIP_COUNT + 1))
return return
fi fi
if [[ "$UPDATE" == true ]] || [[ ! -f "$dst" ]]; then if [[ "$UPDATE" == true ]] || [[ ! -f "$dst_dir/$name" ]]; then
if cp "$src" "$dst"; then cp "$src" "$dst_dir/$name"
ok "$name" echo " [copy] $name"
COPY_COUNT=$((COPY_COUNT + 1))
else
fail "$name"
FAIL_COUNT=$((FAIL_COUNT + 1))
fi
else else
skip "$name (exists, use --update to overwrite)" echo " [skip] $name (exists, use --update to overwrite)"
SKIP_COUNT=$((SKIP_COUNT + 1))
fi fi
} }
copy_dir() { copy_dir() {
local src="$1" dst_dir="$2" local src="$1" dst_dir="$2"
local name; name="$(basename "$src")" local name; name="$(basename "$src")"
local dst="$dst_dir/$name"
if [[ ! -d "$src" ]]; then if [[ ! -d "$src" ]]; then
skip "$name/ (source not found)" echo " [skip] $name/ (not found)"
SKIP_COUNT=$((SKIP_COUNT + 1))
return return
fi fi
mkdir -p "$dst" mkdir -p "$dst_dir/$name"
if [[ "$UPDATE" == true ]]; then if [[ "$UPDATE" == true ]]; then
if cp -rf "$src"/* "$dst/" 2>/dev/null; then cp -rf "$src"/* "$dst_dir/$name/" 2>/dev/null || true
ok "$name/"
COPY_COUNT=$((COPY_COUNT + 1))
else
fail "$name/ (partial copy)"
FAIL_COUNT=$((FAIL_COUNT + 1))
fi
else else
cp -rn "$src"/* "$dst/" 2>/dev/null || true cp -rn "$src"/* "$dst_dir/$name/" 2>/dev/null || true
ok "$name/"
COPY_COUNT=$((COPY_COUNT + 1))
fi fi
echo " [copy] $name/"
} }
copy_file "$METAAGENT_SRC/GUIDE.md" "$SRC_DIR" copy_file "$METAAGENT_SRC/META_AGENT_GUIDE.md" "$SRC_DIR"
copy_file "$METAAGENT_SRC/BOUNDARIES.md" "$SRC_DIR" copy_file "$METAAGENT_SRC/BOUNDARIES.md" "$SRC_DIR"
copy_file "$METAAGENT_SRC/CHANGELOG.md" "$SRC_DIR"
copy_file "$METAAGENT_SRC/WORKFLOW.md" "$SRC_DIR" copy_file "$METAAGENT_SRC/WORKFLOW.md" "$SRC_DIR"
copy_file "$METAAGENT_SRC/VERSION" "$SRC_DIR" copy_file "$METAAGENT_SRC/VERSION" "$SRC_DIR"
copy_dir "$METAAGENT_SRC/PROTOCOLS" "$SRC_DIR" copy_dir "$METAAGENT_SRC/PROTOCOLS" "$SRC_DIR"
copy_dir "$METAAGENT_SRC/COMMANDS" "$SRC_DIR"
copy_dir "$METAAGENT_SRC/TEMPLATES" "$SRC_DIR" copy_dir "$METAAGENT_SRC/TEMPLATES" "$SRC_DIR"
copy_file "$METAAGENT_SRC/install.sh" "$SRC_DIR" copy_file "$METAAGENT_SRC/install.sh" "$SRC_DIR"
copy_file "$METAAGENT_SRC/install.ps1" "$SRC_DIR" copy_file "$METAAGENT_SRC/install.ps1" "$SRC_DIR"
# --- phase 3: AGENTS.md -------------------------------------------------- # --- create / update AGENTS.md in root of target ---
header "AGENTS.md" AGENTS_MD="$TARGET_PATH/AGENTS.md"
create_agents_md() { create_agents_md() {
cat > "$1" << AGENTS_EOF cat > "$1" << AGENTS_EOF
# MetaAgent # MetaAgent
Этот проект использует [MetaAgent](.agent/src/GUIDE.md) v$VERSION — Этот проект использует [MetaAgent](.agent/src/META_AGENT_GUIDE.md) v$VERSION —
набор инструкций для AI-агента. набор инструкций для AI-агента.
## Контекст MetaAgent ## Контекст MetaAgent
| Ресурс | Путь | | Ресурс | Путь |
|--------|------| |--------|------|
| Главная инструкция | \`.agent/src/GUIDE.md\` | | Главная инструкция | \`.agent/src/META_AGENT_GUIDE.md\` |
| Протоколы фаз | \`.agent/src/PROTOCOLS/\` | | Протоколы фаз | \`.agent/src/PROTOCOLS/\` |
| Команды (on-demand) | \`.agent/src/COMMANDS/\` |
| Шаблоны артефактов | \`.agent/src/TEMPLATES/\` | | Шаблоны артефактов | \`.agent/src/TEMPLATES/\` |
| Границы (что разрешено/запрещено) | \`.agent/src/BOUNDARIES.md\` | | Границы (что разрешено/запрещено) | \`.agent/src/BOUNDARIES.md\` |
| История версий | \`.agent/src/CHANGELOG.md\` |
| Правила проекта | \`.agent/rules/project-rules.md\` | | Правила проекта | \`.agent/rules/project-rules.md\` |
| Пример работы | \`.agent/src/WORKFLOW.md\` | | Примеры работы | \`.agent/src/WORKFLOW.md\` |
| Версия | \`.agent/src/VERSION\` | | Версия | \`.agent/src/VERSION\` |
## Состояние сессии (если инициализировано) ## Состояние сессии (если инициализировано)
@@ -244,69 +122,31 @@ create_agents_md() {
| Артефакт | Путь | | Артефакт | Путь |
|----------|------| |----------|------|
| Чекпоинты сессии | \`.agent/checkpoints.json\` | | Чекпоинты сессии | \`.agent/checkpoints.json\` |
| Слепок проекта | \`.agent/context/project-state.md\` | | Манифест задач | \`.agent/task-manifest.json\` |
| Анализ репозитория | \`.agent/context/analysis-report.md\` | | Сводка для exec-агента | \`.agent/handoff-summary.md\` |
| Дорожная карта | \`.agent/roadmap/sources.md\` | | Анализ репозитория | \`.agent/analysis-report.md\` |
| Манифест задач | \`.agent/tasks/manifest.json\` |
| Сводка для следующего агента | \`.agent/handoff-summary.md\` |
| Сводка сессии | \`.agent/session-summary.md\` |
## Для агента ## Для исполнительного агента
Жизненный цикл MetaAgent v$VERSION: 1. **Прочитай** \`.agent/src/META_AGENT_GUIDE.md\` — пойми жизненный цикл MetaAgent.
\`\`\`
INIT → ANALYSE → ROADMAP → [DESIGN] → DECOMPOSITION → EXECUTION → METASTATE → HANDOFF
\`\`\`
1. **Прочитай** \`.agent/src/GUIDE.md\` — пойми цикл и доступные команды.
2. **Прочитай** \`.agent/src/BOUNDARIES.md\` — соблюдай границы. 2. **Прочитай** \`.agent/src/BOUNDARIES.md\` — соблюдай границы.
3. **Прочитай** \`.agent/rules/project-rules.md\` — выполни правила пользователя. 3. **Прочитай** \`.agent/rules/project-rules.md\` — выполни пользовательские правила.
4. **Проверь** \`.agent/checkpoints.json\` — если существует, используй как состояние сессии. 4. **Проверь** \`.agent/checkpoints.json\` — если существует, используй как состояние сессии.
5. **Проверь** \`.agent/context/project-state.md\` — получи актуальную картину. 5. **Проверь** \`.agent/task-manifest.json\` — если существует, выполняй задачи по порядку.
6. **Проверь** \`.agent/tasks/manifest.json\` — если существует, выполняй задачи по порядку. 6. Если \`.agent/\` не инициализирован или устарел — запусти \`install.sh --update\` для
7. Если \`.agent/\` не инициализирован или устарел — запусти \`install.sh --update\` для
обновления исходников MetaAgent до актуальной версии. обновления исходников MetaAgent до актуальной версии.
## Команды (on-demand)
В любой момент пользователь может вызвать:
- \`/adr\` — записать архитектурное решение
- \`/red-team\` — попытаться сломать дизайн
- \`/risk-register\` — зафиксировать допущения
- \`/alt-arch\` — описать альтернативу
- \`/invariant-tests\` — тесты-инварианты для ADR
AGENTS_EOF AGENTS_EOF
} }
if [[ ! -f "$AGENTS_MD" ]]; then if [[ ! -f "$AGENTS_MD" ]]; then
create_agents_md "$AGENTS_MD" create_agents_md "$AGENTS_MD"
ok "AGENTS.md created" echo " [create] AGENTS.md"
elif [[ "$UPDATE" == true ]]; then elif [[ "$UPDATE" == true ]]; then
create_agents_md "$AGENTS_MD" create_agents_md "$AGENTS_MD"
ok "AGENTS.md updated" echo " [update] AGENTS.md"
else else
skip "AGENTS.md (exists, use --update to overwrite)" echo " [skip] AGENTS.md (exists, use --update to overwrite)"
SKIP_COUNT=$((SKIP_COUNT + 1))
fi fi
# --- summary -------------------------------------------------------------
header "Summary"
echo " MetaAgent v$VERSION → $SRC_DIR"
echo "" echo ""
if (( COPY_COUNT > 0 )); then echo "Done! MetaAgent v$VERSION installed at $SRC_DIR"
ok "${COPY_COUNT} file(s) copied"
fi
if (( SKIP_COUNT > 0 )); then
skip "${SKIP_COUNT} file(s) skipped"
fi
if (( FAIL_COUNT > 0 )); then
fail "${FAIL_COUNT} file(s) failed"
fi
echo ""
if (( FAIL_COUNT == 0 )); then
ok "Installation completed successfully."
else
fail "Installation completed with ${FAIL_COUNT} error(s)."
exit 1
fi
+171
View File
@@ -0,0 +1,171 @@
{
"$schema": "metaagent-task-manifest",
"version": "1.0",
"session_id": "metaagent-002",
"goal": "Обновление metaagent-артефактов до v1.0.0, валидация существующего кода и окружения",
"created_at": "2026-07-12T20:00:00Z",
"tasks": [
{
"id": "T1",
"title": "Инициализация проекта и зависимостей",
"description": "Создать структуру директорий, pyproject.toml, venv, установить зависимости",
"type": "config",
"files": [
"pyproject.toml",
"cashflow_model/__init__.py",
"sync/__init__.py",
"engine/__init__.py",
"ai/__init__.py",
"cli/__init__.py",
"data/.gitkeep",
"exports/.gitkeep"
],
"depends_on": [],
"acceptance_criteria": [
"pyproject.toml создан с правильными зависимостями",
"Все директории модулей созданы с __init__.py",
"ruff lint проходит без ошибок",
"pytest запускается"
],
"status": "completed"
},
{
"id": "T2",
"title": "Модель данных (dataclass + JSON serialization)",
"description": "Реализовать все сущности: Account, Transaction, RecurringCashflow, Asset, Liability, ForecastScenario, FinancialModel",
"type": "feature",
"files": [
"cashflow_model/__init__.py",
"cashflow_model/account.py",
"cashflow_model/transaction.py",
"cashflow_model/recurring.py",
"cashflow_model/asset.py",
"cashflow_model/liability.py",
"cashflow_model/scenario.py",
"cashflow_model/model.py"
],
"depends_on": ["T1"],
"acceptance_criteria": [
"Все сущности — dataclass с правильными полями и типами",
"FinancialModel корректно сохраняется и загружается из JSON",
"Создание Account, Transaction, Asset, Liability через конструктор работает"
],
"status": "completed"
},
{
"id": "T3",
"title": "Forecast Engine (базовый прогноз)",
"description": "Реализовать ForecastService с методами forecast_cashflow, apply_recurring, project_balance",
"type": "feature",
"files": [
"engine/__init__.py",
"engine/forecast.py"
],
"depends_on": ["T2"],
"acceptance_criteria": [
"forecast_cashflow(months=12) возвращает список помесячных балансов",
"Регулярные платежи корректно проецируются на будущие периоды",
"Активы учитываются с ростом (growth_rate)",
"Обязательства учитываются с процентами и платежами"
],
"status": "completed"
},
{
"id": "T4",
"title": "Scenario Analysis",
"description": "Реализовать ScenarioService с методами: сценарии, what-if, сравнение",
"type": "feature",
"files": [
"engine/__init__.py",
"engine/scenarios.py"
],
"depends_on": ["T3"],
"acceptance_criteria": [
"Три предустановленных сценария (baseline, optimistic, pessimistic)",
"What-if: изменение параметров (доход +10%, расход -5%)",
"Сравнение сценариев возвращает сводку различий"
],
"status": "completed"
},
{
"id": "T5",
"title": "Excel Sync (import/export)",
"description": "Реализовать ExcelSync: чтение модели из .xlsx, запись результатов прогноза в .xlsx",
"type": "feature",
"files": [
"sync/__init__.py",
"sync/excel_sync.py"
],
"depends_on": ["T2"],
"acceptance_criteria": [
"Импорт из Excel заполняет FinancialModel",
"Экспорт FinancialModel в Excel создаёт корректный .xlsx",
"Обработка ошибок при невалидном формате Excel"
],
"status": "completed"
},
{
"id": "T6",
"title": "CLI (Typer) — все команды",
"description": "Реализовать CLI через Typer с командами: init, import, export, forecast, scenario, analyze, whatif, compare",
"type": "feature",
"files": [
"cli/__init__.py",
"cli/main.py",
"pyproject.toml"
],
"depends_on": ["T2", "T3", "T4", "T5", "T7"],
"acceptance_criteria": [
"Команда 'cf init' создаёт пустую модель и JSON",
"Команда 'cf forecast --months 12' выводит таблицу прогноза",
"Команда 'cf analyze' вызывает AI Assistant",
"Команда 'cf import' и 'cf export' работают с Excel",
"Команда 'cf scenario' применяет и выводит сценарий",
"Команда 'cf whatif' выполняет what-if анализ",
"Команда 'cf compare' сравнивает сценарии"
],
"status": "completed"
},
{
"id": "T7",
"title": "AI Assistant (промпты + интерфейс)",
"description": "Реализовать AssistantService: генерация промптов, заглушка для вызова AI API",
"type": "feature",
"files": [
"ai/__init__.py",
"ai/prompts.py",
"ai/assistant.py"
],
"depends_on": ["T3"],
"acceptance_criteria": [
"Промпт 'analyze' включает модель и прогноз в JSON",
"Промпт 'advice' формирует запрос на финансовые рекомендации",
"AssistantService возвращает структурированный ответ (заглушка)"
],
"status": "completed"
},
{
"id": "T8",
"title": "Тесты на все модули",
"description": "Написать pytest-тесты для всех модулей",
"type": "test",
"files": [
"tests/test_model.py",
"tests/test_forecast.py",
"tests/test_scenarios.py",
"tests/test_excel_sync.py",
"tests/test_cli.py",
"tests/test_ai.py",
"tests/conftest.py"
],
"depends_on": ["T2", "T3", "T4", "T5", "T6", "T7"],
"acceptance_criteria": [
"pytest запускается и все тесты проходят",
"Покрытие базовых сценариев для каждой сущности",
"Roundtrip-тест Excel: export → import → compare",
"Forecast-тест: известные входные данные → ожидаемый результат"
],
"status": "completed"
}
]
}
+22
View File
@@ -0,0 +1,22 @@
# Task Manifest
**Session:** metaagent-002
**Goal:** Обновление metaagent-артефактов до v1.0.0, валидация существующего кода и окружения
**Date:** 2026-07-12T20:00:00Z
---
## Task Overview
| ID | Title | Type | Depends On | Status |
|---|---|---|---|---|
| T1 | Инициализация проекта и зависимостей | config | — | completed |
| T2 | Модель данных (dataclass + JSON serialization) | feature | T1 | completed |
| T3 | Forecast Engine (базовый прогноз) | feature | T2 | completed |
| T4 | Scenario Analysis | feature | T3 | completed |
| T5 | Excel Sync (import/export) | feature | T2 | completed |
| T6 | CLI (Typer) — все команды | feature | T2, T3, T4, T5, T7 | completed |
| T7 | AI Assistant (промпты + интерфейс) | feature | T3 | completed |
| T8 | Тесты на все модули | test | T2, T3, T4, T5, T6, T7 | completed |
**Total tasks:** 8 — all completed
-16
View File
@@ -1,16 +0,0 @@
{
"$schema": "metaagent-task-manifest",
"version": "3.0",
"session_id": "metaagent-005",
"goal": "Серьёзный архитектурный рефактор: A1+A10 (слои+version), A2+A3 (pydantic), A4 (decimal), A7+A8+A9 (DI+repo), A5 (CLI decompose)",
"created_at": "2026-10-08T15:58:00Z",
"tasks": [
{ "id": "T1", "title": "Реструктуризация в domain/application/infrastructure + version=1", "status": "archived", "origin": "user:direct" },
{ "id": "T2", "title": "Pydantic v2 — миграция моделей", "status": "archived", "origin": "user:direct" },
{ "id": "T3", "title": "Decimal для денег", "status": "archived", "origin": "user:direct" },
{ "id": "T4", "title": "Repository pattern — ModelRepository", "status": "archived", "origin": "user:direct" },
{ "id": "T5", "title": "Dependency Injection в сервисах", "status": "archived", "origin": "user:direct" },
{ "id": "T6", "title": "Декомпозиция CLI", "status": "archived", "origin": "user:direct" },
{ "id": "T7", "title": "Финальная валидация", "status": "archived", "origin": "user:direct" }
]
}
-123
View File
@@ -1,123 +0,0 @@
# Task Manifest
**Session:** `metaagent-005`
**Goal:** Серьёзный архитектурный рефактор
**Date:** 2026-10-08
**Total tasks:** 7
---
## T1: Реструктуризация в domain/application/infrastructure + version=1
**Зависимости:** —
**Файлы:** domain/ (new), application/ (new), infrastructure/{cli,sync,ai}/ (new), tests/
**Что:** Ввести явные слои. Переместить пакеты. Добавить version: 1 в FinancialModel.
**Acceptance:**
- [ ] Структура domain/application/infrastructure создана
- [ ] Все исходные файлы перемещены
- [ ] Все импорты обновлены
- [ ] `FinancialModel.to_dict()` → `{'version': 1, ...}`
- [ ] `from_dict()` поддерживает v0 (без version) и v1
- [ ] pytest 63/63
---
## T2: Pydantic v2 — миграция моделей
**Зависимости:** T1
**Файлы:** domain/*.py, pyproject.toml, infrastructure/sync/excel_sync.py
**Что:** `@dataclass` → `pydantic.BaseModel`. Удалить ручные `to_dict`/`from_dict`.
**Acceptance:**
- [ ] Все модели — `BaseModel`
- [ ] Удалены ручные to_dict/from_dict
- [ ] UUID в JSON как str
- [ ] Валидация (balance >= 0, и т.п.)
- [ ] Excel-sync адаптирован
- [ ] pytest 63/63
---
## T3: Decimal для денег
**Зависимости:** T2
**Файлы:** domain/*.py, application/*.py, infrastructure/sync/excel_sync.py, infrastructure/cli/{main,config}.py
**Что:** `float` → `Decimal` для всех monetary полей. Арифметика engine, форматирование.
**Acceptance:**
- [ ] monetary поля — `Decimal`
- [ ] CurrencyConverter с Decimal
- [ ] ForecastService арифметика — Decimal
- [ ] Excel-sync читает числа как Decimal
- [ ] rich.print форматирует Decimal (2 знака)
- [ ] JSON-сериализация Decimal работает
- [ ] pytest 63/63
---
## T4: Repository pattern — ModelRepository
**Зависимости:** T1
**Файлы:** application/repositories/model_repository.py, infrastructure/repositories/{json_file,excel}_repository.py, infrastructure/sync/excel_sync.py
**Что:** `ModelRepository` Protocol + `JsonFileRepository` + `ExcelRepository` (адаптер над ExcelSync).
**Acceptance:**
- [ ] `ModelRepository` Protocol (load/save)
- [ ] `JsonFileRepository` реализует Protocol
- [ ] `ExcelRepository` реализует Protocol
- [ ] `FinancialModel.save/load` удалены
- [ ] Тесты на каждый репозиторий
- [ ] pytest 63/63
---
## T5: Dependency Injection в сервисах
**Зависимости:** T4
**Файлы:** application/forecast.py, scenarios.py, infrastructure/ai/assistant.py, infrastructure/cli/{main,config}.py
**Что:** Зависимости через конструктор. Composition root в CLI.
**Acceptance:**
- [ ] `ForecastService.__init__(model, repository, converter)`
- [ ] ScenarioService, AssistantService — то же
- [ ] Нет `new ForecastService()` внутри других сервисов
- [ ] CLI собирает граф зависимостей
- [ ] pytest 63/63
---
## T6: Декомпозиция CLI
**Зависимости:** T5
**Файлы:** infrastructure/cli/main.py → app.py, infrastructure/cli/commands/*.py, infrastructure/cli/{paths,services}.py
**Что:** 8 команд в отдельных файлах. config.py → paths.py + services.py.
**Acceptance:**
- [ ] Каждая команда в cli/commands/*.py
- [ ] cli/paths.py — только пути
- [ ] cli/services.py — composition root
- [ ] Размер файлов < 100-150 LOC
- [ ] Поведение идентично
- [ ] pytest 63/63
---
## T7: Финальная валидация
**Зависимости:** T6
**Файлы:** tests/, README.md, pyproject.toml
**Что:** Прогнать pytest, ручная проверка CLI, обновить README.
**Acceptance:**
- [ ] pytest 63/63+
- [ ] cf init, cf forecast, cf scenario, cf compare — работают
- [ ] cf import data.xlsx → cf export — round-trip
- [ ] README.md обновлён под новую структуру
-6
View File
@@ -174,9 +174,3 @@ poetry.toml
pyrightconfig.json pyrightconfig.json
# End of https://www.toptal.com/developers/gitignore/api/python # End of https://www.toptal.com/developers/gitignore/api/python
# MetaAgent temp files
.temp/
# opencode local state
.omo/
+11 -32
View File
@@ -1,20 +1,18 @@
# MetaAgent # MetaAgent
Этот проект использует [MetaAgent](.agent/src/GUIDE.md) v3.0.0 — Этот проект использует [MetaAgent](.agent/src/META_AGENT_GUIDE.md) v1.1.0 —
набор инструкций для AI-агента. набор инструкций для AI-агента.
## Контекст MetaAgent ## Контекст MetaAgent
| Ресурс | Путь | | Ресурс | Путь |
|--------|------| |--------|------|
| Главная инструкция | `.agent/src/GUIDE.md` | | Главная инструкция | `.agent/src/META_AGENT_GUIDE.md` |
| Протоколы фаз | `.agent/src/PROTOCOLS/` | | Протоколы фаз | `.agent/src/PROTOCOLS/` |
| Команды (on-demand) | `.agent/src/COMMANDS/` |
| Шаблоны артефактов | `.agent/src/TEMPLATES/` | | Шаблоны артефактов | `.agent/src/TEMPLATES/` |
| Границы (что разрешено/запрещено) | `.agent/src/BOUNDARIES.md` | | Границы (что разрешено/запрещено) | `.agent/src/BOUNDARIES.md` |
| История версий | `.agent/src/CHANGELOG.md` |
| Правила проекта | `.agent/rules/project-rules.md` | | Правила проекта | `.agent/rules/project-rules.md` |
| Пример работы | `.agent/src/WORKFLOW.md` | | Примеры работы | `.agent/src/WORKFLOW.md` |
| Версия | `.agent/src/VERSION` | | Версия | `.agent/src/VERSION` |
## Состояние сессии (если инициализировано) ## Состояние сессии (если инициализировано)
@@ -22,35 +20,16 @@
| Артефакт | Путь | | Артефакт | Путь |
|----------|------| |----------|------|
| Чекпоинты сессии | `.agent/checkpoints.json` | | Чекпоинты сессии | `.agent/checkpoints.json` |
| Слепок проекта | `.agent/context/project-state.md` | | Манифест задач | `.agent/task-manifest.json` |
| Анализ репозитория | `.agent/context/analysis-report.md` | | Сводка для exec-агента | `.agent/handoff-summary.md` |
| Дорожная карта | `.agent/roadmap/sources.md` | | Анализ репозитория | `.agent/analysis-report.md` |
| Манифест задач | `.agent/tasks/manifest.json` |
| Сводка для следующего агента | `.agent/handoff-summary.md` |
| Сводка сессии | `.agent/session-summary.md` |
## Для агента ## Для исполнительного агента
Жизненный цикл MetaAgent v3.0.0: 1. **Прочитай** `.agent/src/META_AGENT_GUIDE.md` — пойми жизненный цикл MetaAgent.
```
INIT → ANALYSE → ROADMAP → [DESIGN] → DECOMPOSITION → EXECUTION → METASTATE → HANDOFF
```
1. **Прочитай** `.agent/src/GUIDE.md` — пойми цикл и доступные команды.
2. **Прочитай** `.agent/src/BOUNDARIES.md` — соблюдай границы. 2. **Прочитай** `.agent/src/BOUNDARIES.md` — соблюдай границы.
3. **Прочитай** `.agent/rules/project-rules.md` — выполни правила пользователя. 3. **Прочитай** `.agent/rules/project-rules.md` — выполни пользовательские правила.
4. **Проверь** `.agent/checkpoints.json` — если существует, используй как состояние сессии. 4. **Проверь** `.agent/checkpoints.json` — если существует, используй как состояние сессии.
5. **Проверь** `.agent/context/project-state.md` — получи актуальную картину. 5. **Проверь** `.agent/task-manifest.json` — если существует, выполняй задачи по порядку.
6. **Проверь** `.agent/tasks/manifest.json` — если существует, выполняй задачи по порядку. 6. Если `.agent/` не инициализирован или устарел — запусти `install.sh --update` для
7. Если `.agent/` не инициализирован или устарел — запусти `install.sh --update` для
обновления исходников MetaAgent до актуальной версии. обновления исходников MetaAgent до актуальной версии.
## Команды (on-demand)
В любой момент пользователь может вызвать:
- `/adr` — записать архитектурное решение
- `/red-team` — попытаться сломать дизайн
- `/risk-register` — зафиксировать допущения
- `/alt-arch` — описать альтернативу
- `/invariant-tests` — тесты-инварианты для ADR
-21
View File
@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2026 Jor Oqyude
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+39 -99
View File
@@ -1,8 +1,8 @@
# CashFlow Forecast # CashFlow Forecast
Личная финансовая модель с прогнозом денежных потоков, сценарным анализом. Личная финансовая модель с прогнозом денежных потоков, сценарным анализом и AI-ассистентом.
Python + Pydantic + JSON + Excel. Python + JSON + Excel + AI.
## Установка ## Установка
@@ -35,17 +35,12 @@ cf whatif --income 1.2 --expense 0.9 --growth 1.0 --months 12
# Сравнение всех сценариев # Сравнение всех сценариев
cf compare --months 12 cf compare --months 12
# Сводка модели
cf info
# Редактирование модели
cf config account-add --name "Main" --balance 5000
cf config transaction-add --account Main --amount -1200 --category rent
cf config rate-set USD RUB 80.0
# Импорт/экспорт Excel # Импорт/экспорт Excel
cf import-xlsx data.xlsx cf import data.xlsx
cf export-xlsx exports/report.xlsx cf export exports/report.xlsx
# AI-анализ (заглушка, генерация промпта)
cf analyze
``` ```
### Пример: создание тестовых данных ### Пример: создание тестовых данных
@@ -53,87 +48,44 @@ cf export-xlsx exports/report.xlsx
Подготовьте Excel-файл с листами: `Accounts`, `Transactions`, `Recurring`, `Assets`, `Liabilities`. Заголовки колонок соответствуют полям моделей. Затем импортируйте: Подготовьте Excel-файл с листами: `Accounts`, `Transactions`, `Recurring`, `Assets`, `Liabilities`. Заголовки колонок соответствуют полям моделей. Затем импортируйте:
```bash ```bash
cf import-xlsx my_finances.xlsx cf import my_finances.xlsx
cf forecast --months 12 cf forecast --months 12
``` ```
## Архитектура
Проект разделён на три слоя по принципам Clean Architecture:
```
┌─────────────────────────────────────────────┐
│ domain/ — бизнес-модели │
│ Account, Transaction, Asset, Liability, │
│ Recurring, Scenario, FinancialModel, │
│ ExchangeRate, CurrencyConverter │
│ (pydantic.BaseModel, Decimal) │
└──────────────────┬──────────────────────────┘
│
┌──────────────────▼──────────────────────────┐
│ application/ — прикладные сервисы │
│ ForecastService, ScenarioService, │
│ ModelRepository (Protocol) │
└──────────────────┬──────────────────────────┘
│
┌──────────────────▼──────────────────────────┐
│ infrastructure/ — внешний мир │
│ cli/ (Typer), ai/ (Assistant), │
│ repositories/ (JsonFile, Excel) │
└─────────────────────────────────────────────┘
```
## Структура проекта ## Структура проекта
``` ```
cashflow-forecast/ ├── cashflow_model/ # Модели данных (dataclass + JSON)
├── domain/ # Бизнес-модели (pydantic + Decimal) │ ├── account.py # Account
│ ├── account.py # Account │ ├── transaction.py # Transaction
│ ├── transaction.py # Transaction │ ├── recurring.py # RecurringCashflow
│ ├── recurring.py # RecurringCashflow │ ├── asset.py # Asset
│ ├── asset.py # Asset │ ├── liability.py # Liability
│ ├── liability.py # Liability │ ├── scenario.py # ForecastScenario
│ ├── scenario.py # ForecastScenario │ └── model.py # FinancialModel (корень, save/load JSON)
│ ├── currency.py # ExchangeRate + CurrencyConverter ├── engine/ # Вычислительное ядро
│ └── model.py # FinancialModel (корень) │ ├── forecast.py # ForecastService — прогноз
│ │ └── scenarios.py # ScenarioService — сценарии + what-if
├── application/ # Прикладные сервисы ├── sync/ # Синхронизация с Excel
│ ├── forecast.py # ForecastService — прогноз │ └── excel_sync.py # ExcelSync — import/export .xlsx
│ ├── scenarios.py # ScenarioService — сценарии + what-if ├── ai/ # AI-ассистент
│ └── repositories/ │ ├── prompts.py # Шаблоны промптов
│ └── model_repository.py # ModelRepository Protocol │ └── assistant.py # AssistantService (заглушка)
│ ├── cli/ # CLI (Typer)
├── infrastructure/ # Адаптеры к внешнему миру │ └── main.py # Команды: cf init/forecast/scenario/...
│ ├── cli/ # Typer CLI (cf ...) ├── tests/ # Тесты pytest
│ │ ├── app.py # Entry point │ ├── conftest.py # Фикстуры
│ │ ├── commands/ # 9 файлов команд + config sub-typer
│ │ ├── paths.py # DATA_DIR, MODEL_PATH
│ │ ├── services.py # Composition root + helpers
│ │ └── i18n.py # ru/en переводы
│ ├── ai/ # AI-ассистент (заглушка)
│ │ ├── prompts.py
│ │ └── assistant.py # AssistantService
│ └── repositories/ # Реализации ModelRepository
│ ├── json_file_repository.py
│ └── excel_repository.py
│
├── tests/ # pytest, 67 тестов
│ ├── conftest.py
│ ├── test_model.py │ ├── test_model.py
│ ├── test_forecast.py │ ├── test_forecast.py
│ ├── test_scenarios.py │ ├── test_scenarios.py
│ ├── test_currency.py │ ├── test_excel_sync.py
│ ├── test_ai.py │ ├── test_ai.py
│ ├── test_cli.py │ └── test_cli.py
│ ├── test_excel_sync.py # Тесты ExcelRepository ├── data/ # JSON-модели
│ ├── test_i18n.py ├── exports/ # Экспортированные .xlsx
│ └── test_repositories.py # Тесты репозиториев ├── .agent/ # Артефакты MetaAgent (планирование)
│ ├── pyproject.toml # Зависимости и конфигурация
├── data/ # JSON-модели (runtime, версионируется SCHEMA_VERSION=1) └── README.arch.md # Оригинальная архитектурная концепция
├── exports/ # Экспортированные .xlsx
├── .agent/ # Артефакты MetaAgent v3.0
├── pyproject.toml # Зависимости + entry point `cf`
└── README.arch.md # Оригинальная архитектурная концепция
``` ```
## Разработка ## Разработка
@@ -142,7 +94,7 @@ cashflow-forecast/
# Тесты # Тесты
pytest pytest
# Линтер (если доступен ruff) # Линтер
ruff check . ruff check .
# Автоформат # Автоформат
@@ -155,24 +107,12 @@ ruff format .
- openpyxl — работа с Excel - openpyxl — работа с Excel
- typer — CLI - typer — CLI
- rich — форматирование вывода - rich — форматирование вывода
- pydantic >= 2.0 — валидация моделей
- pytest — тесты - pytest — тесты
- ruff — линтер (опционально) - ruff — линтер
## Архитектурные решения
- **Слои**: `domain/` (модели), `application/` (сервисы), `infrastructure/` (адаптеры).
- **Pydantic v2**: все модели — `pydantic.BaseModel` с валидацией (balance >= 0, amount != 0, и т.п.).
- **Decimal**: все денежные поля — `Decimal`, арифметика без потери точности.
- **Repository pattern**: `ModelRepository` Protocol, реализации `JsonFileRepository` и `ExcelRepository`.
- **DI**: Composition root в `infrastructure/cli/services.py:build_services()`.
- **Schema versioning**: `FinancialModel.to_dict()` пишет `version: 1`; `from_dict()` поддерживает legacy v0.
- **i18n**: `infrastructure/cli/i18n.py`, ru (default) + en (fallback).
## Известные ограничения (MVP) ## Известные ограничения (MVP)
- **AI-ассистент** — заглушка (`ai_response: None`). Промпты готовы, но не подключены к API. - **AI-ассистент** — заглушка. Промпты готовы, но не подключены к API.
- **Хранилище** — JSON-файлы (не подходит для многопользовательской работы). - **База данных** — JSON-файлы (не подходит для многопользовательской работы).
- **Excel** — только `.xlsx` через openpyxl. - **Excel** — только `.xlsx` через openpyxl.
- **Лицензия** — не выбрана. - **Лицензия** — не выбрана.
- **CI/CD** — не настроен.
+4
View File
@@ -0,0 +1,4 @@
from ai import prompts
from ai.assistant import AssistantError, AssistantService
__all__ = ["AssistantService", "AssistantError", "prompts"]
+56
View File
@@ -0,0 +1,56 @@
import json
from ai import prompts
from cashflow_model import FinancialModel
from engine.forecast import ForecastService
class AssistantError(Exception):
pass
class AssistantService:
def __init__(self, model: FinancialModel):
self.model = model
def analyze(self, months: int = 12) -> dict:
forecast_service = ForecastService(self.model)
forecast_result = forecast_service.forecast_cashflow(months)
summary = forecast_service.summary(months)
prompt = prompts.format_context(
model_json=json.dumps(self.model.to_dict(), indent=2, ensure_ascii=False),
forecast_json=json.dumps(forecast_result, indent=2, ensure_ascii=False),
months=months,
)
return {
"prompt": prompt,
"summary": summary,
"forecast": forecast_result,
"ai_response": None,
}
def advice(self, question: str, months: int = 12) -> dict:
forecast_service = ForecastService(self.model)
forecast_result = forecast_service.forecast_cashflow(months)
prompt = prompts.ADVICE_PROMPT.format(
model_json=json.dumps(self.model.to_dict(), indent=2, ensure_ascii=False),
forecast_json=json.dumps(forecast_result, indent=2, ensure_ascii=False),
question=question,
)
return {
"prompt": prompt,
"ai_response": None,
}
def compare_scenarios(self, scenarios_json: str) -> dict:
prompt = prompts.SCENARIO_COMPARISON_PROMPT.format(
scenarios_json=scenarios_json,
)
return {
"prompt": prompt,
"ai_response": None,
}
+46
View File
@@ -0,0 +1,46 @@
ANALYZE_PROMPT = """
Ты — финансовый AI-ассистент. Проанализируй финансовую модель пользователя.
### Модель (JSON):
{model_json}
### Прогноз на {months} месяцев:
{forecast_json}
Дай анализ по пунктам:
1. Общее финансовое состояние
2. Тренд денежного потока (рост/падение)
3. Достаточность ликвидности
4. Рекомендации по улучшению
"""
ADVICE_PROMPT = """
Ты — финансовый AI-ассистент. Дай персональные рекомендации.
### Модель:
{model_json}
### Прогноз:
{forecast_json}
Вопрос пользователя: {question}
Ответь как опытный финансовый консультант.
"""
SCENARIO_COMPARISON_PROMPT = """
Ты — финансовый AI-ассистент. Сравни сценарии прогноза.
### Результаты сценариев:
{scenarios_json}
Дай рекомендацию: какой сценарий наиболее вероятен и почему.
"""
def format_context(model_json: str, forecast_json: str, months: int = 12) -> str:
return ANALYZE_PROMPT.format(
model_json=model_json,
forecast_json=forecast_json,
months=months,
)
-10
View File
@@ -1,10 +0,0 @@
from application.forecast import ForecastError, ForecastService
from application.scenarios import DEFAULT_SCENARIOS, ScenarioError, ScenarioService
__all__ = [
"ForecastService",
"ForecastError",
"ScenarioService",
"ScenarioError",
"DEFAULT_SCENARIOS",
]
-3
View File
@@ -1,3 +0,0 @@
from application.repositories.model_repository import ModelRepository
__all__ = ["ModelRepository"]
@@ -1,20 +0,0 @@
"""Repository protocol для хранения FinancialModel.
Определяет контракт: load(path) -> FinancialModel, save(model, path) -> None.
Реализации: JsonFileRepository, ExcelRepository.
"""
from __future__ import annotations
from pathlib import Path
from typing import Protocol, runtime_checkable
from domain import FinancialModel
@runtime_checkable
class ModelRepository(Protocol):
"""Любой storage, способный прочитать и записать FinancialModel."""
def load(self, path: str | Path) -> FinancialModel: ...
def save(self, model: FinancialModel, path: str | Path) -> None: ...
+17
View File
@@ -0,0 +1,17 @@
from cashflow_model.account import Account
from cashflow_model.asset import Asset
from cashflow_model.liability import Liability
from cashflow_model.model import FinancialModel
from cashflow_model.recurring import RecurringCashflow
from cashflow_model.scenario import ForecastScenario
from cashflow_model.transaction import Transaction
__all__ = [
"Account",
"Transaction",
"RecurringCashflow",
"Asset",
"Liability",
"ForecastScenario",
"FinancialModel",
]
+27
View File
@@ -0,0 +1,27 @@
from dataclasses import dataclass, field
from uuid import UUID, uuid4
@dataclass
class Account:
id: UUID = field(default_factory=uuid4)
name: str = ""
currency: str = "USD"
balance: float = 0.0
def to_dict(self) -> dict:
return {
"id": str(self.id),
"name": self.name,
"currency": self.currency,
"balance": self.balance,
}
@classmethod
def from_dict(cls, data: dict) -> "Account":
return cls(
id=UUID(data["id"]),
name=data["name"],
currency=data.get("currency", "USD"),
balance=data.get("balance", 0.0),
)
+27
View File
@@ -0,0 +1,27 @@
from dataclasses import dataclass, field
from uuid import UUID, uuid4
@dataclass
class Asset:
id: UUID = field(default_factory=uuid4)
name: str = ""
value: float = 0.0
growth_rate: float = 0.0
def to_dict(self) -> dict:
return {
"id": str(self.id),
"name": self.name,
"value": self.value,
"growth_rate": self.growth_rate,
}
@classmethod
def from_dict(cls, data: dict) -> "Asset":
return cls(
id=UUID(data["id"]),
name=data["name"],
value=data.get("value", 0.0),
growth_rate=data.get("growth_rate", 0.0),
)
+30
View File
@@ -0,0 +1,30 @@
from dataclasses import dataclass, field
from uuid import UUID, uuid4
@dataclass
class Liability:
id: UUID = field(default_factory=uuid4)
name: str = ""
balance: float = 0.0
interest: float = 0.0
payment: float = 0.0
def to_dict(self) -> dict:
return {
"id": str(self.id),
"name": self.name,
"balance": self.balance,
"interest": self.interest,
"payment": self.payment,
}
@classmethod
def from_dict(cls, data: dict) -> "Liability":
return cls(
id=UUID(data["id"]),
name=data["name"],
balance=data.get("balance", 0.0),
interest=data.get("interest", 0.0),
payment=data.get("payment", 0.0),
)
+54
View File
@@ -0,0 +1,54 @@
import json
from dataclasses import dataclass, field
from pathlib import Path
from cashflow_model.account import Account
from cashflow_model.asset import Asset
from cashflow_model.liability import Liability
from cashflow_model.recurring import RecurringCashflow
from cashflow_model.scenario import ForecastScenario
from cashflow_model.transaction import Transaction
@dataclass
class FinancialModel:
accounts: list[Account] = field(default_factory=list)
transactions: list[Transaction] = field(default_factory=list)
recurring: list[RecurringCashflow] = field(default_factory=list)
assets: list[Asset] = field(default_factory=list)
liabilities: list[Liability] = field(default_factory=list)
scenarios: list[ForecastScenario] = field(default_factory=list)
def to_dict(self) -> dict:
return {
"accounts": [a.to_dict() for a in self.accounts],
"transactions": [t.to_dict() for t in self.transactions],
"recurring": [r.to_dict() for r in self.recurring],
"assets": [a.to_dict() for a in self.assets],
"liabilities": [li.to_dict() for li in self.liabilities],
"scenarios": [s.to_dict() for s in self.scenarios],
}
@classmethod
def from_dict(cls, data: dict) -> "FinancialModel":
return cls(
accounts=[Account.from_dict(a) for a in data.get("accounts", [])],
transactions=[Transaction.from_dict(t) for t in data.get("transactions", [])],
recurring=[RecurringCashflow.from_dict(r) for r in data.get("recurring", [])],
assets=[Asset.from_dict(a) for a in data.get("assets", [])],
liabilities=[Liability.from_dict(li) for li in data.get("liabilities", [])],
scenarios=[ForecastScenario.from_dict(s) for s in data.get("scenarios", [])],
)
def save(self, path: str | Path) -> None:
path = Path(path)
path.parent.mkdir(parents=True, exist_ok=True)
with open(path, "w", encoding="utf-8") as f:
json.dump(self.to_dict(), f, indent=2, ensure_ascii=False)
@classmethod
def load(cls, path: str | Path) -> "FinancialModel":
path = Path(path)
with open(path, "r", encoding="utf-8") as f:
data = json.load(f)
return cls.from_dict(data)
+33
View File
@@ -0,0 +1,33 @@
from dataclasses import dataclass, field
from uuid import UUID, uuid4
@dataclass
class RecurringCashflow:
id: UUID = field(default_factory=uuid4)
start_date: str = ""
end_date: str = ""
frequency: str = "monthly"
amount: float = 0.0
category: str = ""
def to_dict(self) -> dict:
return {
"id": str(self.id),
"start_date": self.start_date,
"end_date": self.end_date,
"frequency": self.frequency,
"amount": self.amount,
"category": self.category,
}
@classmethod
def from_dict(cls, data: dict) -> "RecurringCashflow":
return cls(
id=UUID(data["id"]),
start_date=data.get("start_date", ""),
end_date=data.get("end_date", ""),
frequency=data.get("frequency", "monthly"),
amount=data.get("amount", 0.0),
category=data.get("category", ""),
)
+33
View File
@@ -0,0 +1,33 @@
from dataclasses import dataclass, field
from uuid import UUID, uuid4
@dataclass
class ForecastScenario:
id: UUID = field(default_factory=uuid4)
name: str = "baseline"
income_multiplier: float = 1.0
expense_multiplier: float = 1.0
growth_multiplier: float = 1.0
description: str = ""
def to_dict(self) -> dict:
return {
"id": str(self.id),
"name": self.name,
"income_multiplier": self.income_multiplier,
"expense_multiplier": self.expense_multiplier,
"growth_multiplier": self.growth_multiplier,
"description": self.description,
}
@classmethod
def from_dict(cls, data: dict) -> "ForecastScenario":
return cls(
id=UUID(data["id"]),
name=data["name"],
income_multiplier=data.get("income_multiplier", 1.0),
expense_multiplier=data.get("expense_multiplier", 1.0),
growth_multiplier=data.get("growth_multiplier", 1.0),
description=data.get("description", ""),
)
+33
View File
@@ -0,0 +1,33 @@
from dataclasses import dataclass, field
from uuid import UUID, uuid4
@dataclass
class Transaction:
id: UUID = field(default_factory=uuid4)
date: str = ""
account: str = ""
category: str = ""
amount: float = 0.0
description: str = ""
def to_dict(self) -> dict:
return {
"id": str(self.id),
"date": self.date,
"account": self.account,
"category": self.category,
"amount": self.amount,
"description": self.description,
}
@classmethod
def from_dict(cls, data: dict) -> "Transaction":
return cls(
id=UUID(data["id"]),
date=data["date"],
account=data.get("account", ""),
category=data.get("category", ""),
amount=data.get("amount", 0.0),
description=data.get("description", ""),
)
+201
View File
@@ -0,0 +1,201 @@
import sys
from pathlib import Path
import typer
from rich.console import Console
from rich.table import Table
from ai.assistant import AssistantService
from cashflow_model import FinancialModel
from engine.forecast import ForecastService
from engine.scenarios import DEFAULT_SCENARIOS, ScenarioService
from sync.excel_sync import ExcelSync
try:
sys.stdout.reconfigure(encoding="utf-8")
except (AttributeError, OSError):
pass
app = typer.Typer(name="cf", help="CashFlow Forecast - personal finance model")
console = Console()
DATA_DIR = Path("data")
MODEL_PATH = DATA_DIR / "model.json"
def _load_model() -> FinancialModel:
if MODEL_PATH.exists():
return FinancialModel.load(MODEL_PATH)
return FinancialModel()
def _save_model(model: FinancialModel) -> None:
model.save(MODEL_PATH)
@app.command()
def init() -> None:
"""Создать пустую финансовую модель"""
model = FinancialModel()
_save_model(model)
console.print("[green]OK[/green] Пустая модель создана в data/model.json")
@app.command()
def forecast(
months: int = typer.Option(12, "--months", "-m", help="Количество месяцев прогноза"),
) -> None:
"""Запустить прогноз денежных потоков"""
model = _load_model()
service = ForecastService(model)
results = service.forecast_cashflow(months)
summary = service.summary(months)
if results:
table = Table(title=f"Прогноз на {months} мес.")
table.add_column("Счёт", style="cyan")
table.add_column("Месяц", style="white")
table.add_column("Баланс", justify="right", style="green")
table.add_column("Доход", justify="right")
table.add_column("Расход", justify="right")
for r in results:
table.add_row(
r["account"], str(r["month"]),
f"${r['balance']:.2f}",
f"${r['income']:.2f}",
f"${r['expenses']:.2f}",
)
console.print(table)
console.print(f"\n[bold]Итог:[/bold] Баланс: ${summary['total_balance']:.2f} | "
f"Доход: ${summary['total_income']:.2f} | "
f"Расход: ${summary['total_expenses']:.2f}")
@app.command()
def scenario(
name: str = typer.Argument("baseline", help="Имя сценария: baseline, optimistic, pessimistic"),
months: int = typer.Option(12, "--months", "-m", help="Количество месяцев"),
) -> None:
"""Применить сценарий и показать прогноз"""
model = _load_model()
service = ScenarioService(model)
if name in DEFAULT_SCENARIOS:
scenario_obj = DEFAULT_SCENARIOS[name]
else:
console.print(f"[red]Неизвестный сценарий: {name}[/red]")
console.print(f"Доступны: {', '.join(DEFAULT_SCENARIOS.keys())}")
raise typer.Exit(1)
result = service.apply(scenario_obj, months)
console.print(f"[bold]Сценарий:[/bold] {result['scenario']}")
console.print(f"[dim]{result['scenario_description']}[/dim]")
console.print(f"Баланс: ${result['total_balance']:.2f}")
console.print(f"Доход: ${result['total_income']:.2f}")
console.print(f"Расход: ${result['total_expenses']:.2f}")
@app.command()
def whatif(
income_mult: float = typer.Option(1.0, "--income", "-i", help="Множитель дохода"),
expense_mult: float = typer.Option(1.0, "--expense", "-e", help="Множитель расхода"),
growth_mult: float = typer.Option(1.0, "--growth", "-g", help="Множитель роста активов"),
months: int = typer.Option(12, "--months", "-m", help="Количество месяцев"),
) -> None:
"""What-if анализ с произвольными множителями"""
model = _load_model()
service = ScenarioService(model)
result = service.what_if(income_mult, expense_mult, growth_mult, months)
console.print("[bold]What-if анализ[/bold]")
console.print(f"Доход x{income_mult} | Расход x{expense_mult} | Рост x{growth_mult}")
console.print(f"Баланс: ${result['total_balance']:.2f}")
console.print(f"Доход: ${result['total_income']:.2f}")
console.print(f"Расход: ${result['total_expenses']:.2f}")
@app.command()
def compare(
months: int = typer.Option(12, "--months", "-m", help="Количество месяцев"),
) -> None:
"""Сравнить все сценарии"""
model = _load_model()
service = ScenarioService(model)
results = service.compare(months)
table = Table(title="Сравнение сценариев")
table.add_column("Сценарий", style="cyan")
table.add_column("Баланс", justify="right")
table.add_column("Доход", justify="right")
table.add_column("Расход", justify="right")
for name, r in results.items():
table.add_row(
name,
f"${r['total_balance']:.2f}",
f"${r['total_income']:.2f}",
f"${r['total_expenses']:.2f}",
)
console.print(table)
@app.command()
def import_xlsx(
path: str = typer.Argument(..., help="Путь к .xlsx файлу"),
) -> None:
"""Импорт данных из Excel"""
sync = ExcelSync()
try:
model = sync.import_model(path)
_save_model(model)
console.print(f"[green]OK[/green] Импортировано: {len(model.accounts)} счетов, "
f"{len(model.transactions)} транзакций, "
f"{len(model.recurring)} регулярных платежей, "
f"{len(model.assets)} активов, "
f"{len(model.liabilities)} обязательств")
except Exception as e:
console.print(f"[red]Ошибка импорта: {e}[/red]")
raise typer.Exit(1)
@app.command()
def export_xlsx(
path: str = typer.Argument("exports/forecast.xlsx", help="Путь для .xlsx файла"),
) -> None:
"""Экспорт модели в Excel"""
model = _load_model()
sync = ExcelSync()
try:
sync.export_model(model, path)
console.print(f"[green]OK[/green] Модель экспортирована в {path}")
except Exception as e:
console.print(f"[red]Ошибка экспорта: {e}[/red]")
raise typer.Exit(1)
@app.command()
def analyze(
months: int = typer.Option(12, "--months", "-m", help="Количество месяцев для анализа"),
) -> None:
"""AI-анализ финансовой модели"""
model = _load_model()
assistant = AssistantService(model)
result = assistant.analyze(months)
console.print("[bold]Промпт для AI:[/bold]")
console.print(result["prompt"][:500] + "...\n")
console.print("[bold]Сводка:[/bold]")
s = result["summary"]
console.print(f"Баланс: ${s['total_balance']:.2f}")
console.print(f"Доход: ${s['total_income']:.2f}")
console.print(f"Расход: ${s['total_expenses']:.2f}")
console.print(
"\n[yellow]AI-ответ: заглушка. Подключите реальный API в ai/assistant.py[/yellow]"
)
if __name__ == "__main__":
app()
BIN
View File
Binary file not shown.
+7 -30
View File
@@ -1,31 +1,8 @@
{ {
"version": 1, "accounts": [],
"base_currency": "RUB", "transactions": [],
"accounts": [ "recurring": [],
{ "assets": [],
"id": "633c38bd-acdf-4e40-b7ef-64188e3a741d", "liabilities": [],
"name": "Основной", "scenarios": []
"currency": "RUB",
"balance": "50000.0"
}
],
"transactions": [],
"recurring": [],
"assets": [
{
"id": "d15f81dd-8235-4f93-8452-ba0db359d843",
"name": "Акции",
"value": "100000.0",
"growth_rate": "8.0"
}
],
"liabilities": [],
"scenarios": [],
"exchange_rates": [
{
"from_currency": "USD",
"to_currency": "RUB",
"rate": "80"
}
]
} }
-22
View File
@@ -1,22 +0,0 @@
from domain.account import Account
from domain.asset import Asset
from domain.currency import CURRENCY_SYMBOLS, CurrencyConverter, CurrencyError, ExchangeRate
from domain.liability import Liability
from domain.model import FinancialModel
from domain.recurring import RecurringCashflow
from domain.scenario import ForecastScenario
from domain.transaction import Transaction
__all__ = [
"Account",
"Transaction",
"RecurringCashflow",
"Asset",
"Liability",
"ForecastScenario",
"FinancialModel",
"ExchangeRate",
"CurrencyConverter",
"CurrencyError",
"CURRENCY_SYMBOLS",
]
-18
View File
@@ -1,18 +0,0 @@
from decimal import Decimal
from uuid import UUID, uuid4
from pydantic import BaseModel, Field, field_validator
class Account(BaseModel):
id: UUID = Field(default_factory=uuid4)
name: str = ""
currency: str = "USD"
balance: Decimal = Field(default=Decimal("0"))
@field_validator("balance")
@classmethod
def _balance_non_negative(cls, v: Decimal) -> Decimal:
if v < 0:
raise ValueError("balance must be non-negative")
return v
-11
View File
@@ -1,11 +0,0 @@
from decimal import Decimal
from uuid import UUID, uuid4
from pydantic import BaseModel, Field
class Asset(BaseModel):
id: UUID = Field(default_factory=uuid4)
name: str = ""
value: Decimal = Field(default=Decimal("0"))
growth_rate: Decimal = Field(default=Decimal("0"))
-83
View File
@@ -1,83 +0,0 @@
from decimal import Decimal, ROUND_HALF_UP
from pydantic import BaseModel, Field, field_validator
CURRENCY_SYMBOLS = {
"RUB": "₽",
"USD": "$",
"EUR": "€",
"GBP": "£",
"CNY": "¥",
"JPY": "¥",
"KZT": "₸",
"UAH": "₴",
}
class ExchangeRate(BaseModel):
from_currency: str = "USD"
to_currency: str = "RUB"
rate: Decimal = Field(default=Decimal("80"))
@field_validator("rate")
@classmethod
def _rate_positive(cls, v: Decimal) -> Decimal:
if v <= 0:
raise ValueError("rate must be positive")
return v
DEFAULT_RATES: list[ExchangeRate] = [
ExchangeRate(from_currency="USD", to_currency="RUB", rate=Decimal("80")),
]
class CurrencyError(Exception):
pass
class CurrencyConverter:
def __init__(self, rates: list[ExchangeRate] | None = None):
self._rates: dict[tuple[str, str], Decimal] = {}
if rates:
for r in rates:
self.set_rate(r.from_currency, r.to_currency, r.rate)
def set_rate(
self,
from_currency: str,
to_currency: str,
rate: Decimal | float | int | str,
) -> None:
d = Decimal(str(rate)) if not isinstance(rate, Decimal) else rate
if d <= 0:
raise CurrencyError(f"Rate must be positive: {d}")
self._rates[(from_currency, to_currency)] = d
self._rates[(to_currency, from_currency)] = Decimal("1") / d
def get_rate(self, from_currency: str, to_currency: str) -> Decimal:
if from_currency == to_currency:
return Decimal("1")
try:
return self._rates[(from_currency, to_currency)]
except KeyError:
raise CurrencyError(f"No exchange rate: {from_currency} → {to_currency}")
def convert(
self,
amount: Decimal | float | int | str,
from_currency: str,
to_currency: str,
) -> Decimal:
a = Decimal(str(amount)) if not isinstance(amount, Decimal) else amount
if from_currency == to_currency:
return a
rate = self.get_rate(from_currency, to_currency)
return (a * rate).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
def get_symbol(self, currency: str) -> str:
return CURRENCY_SYMBOLS.get(currency, currency)
@classmethod
def with_defaults(cls) -> "CurrencyConverter":
return cls(DEFAULT_RATES)
-19
View File
@@ -1,19 +0,0 @@
from decimal import Decimal
from uuid import UUID, uuid4
from pydantic import BaseModel, Field, field_validator
class Liability(BaseModel):
id: UUID = Field(default_factory=uuid4)
name: str = ""
balance: Decimal = Field(default=Decimal("0"))
interest: Decimal = Field(default=Decimal("0"))
payment: Decimal = Field(default=Decimal("0"))
@field_validator("interest", "payment")
@classmethod
def _non_negative(cls, v: Decimal) -> Decimal:
if v < 0:
raise ValueError("must be non-negative")
return v
-71
View File
@@ -1,71 +0,0 @@
from pydantic import BaseModel, Field
from domain.account import Account
from domain.asset import Asset
from domain.currency import DEFAULT_RATES, ExchangeRate
from domain.liability import Liability
from domain.recurring import RecurringCashflow
from domain.scenario import ForecastScenario
from domain.transaction import Transaction
class FinancialModel(BaseModel):
"""Корневая модель финансового плана.
Сериализация (save/load) вынесена в `application.repositories.ModelRepository` —
JsonFileRepository и ExcelRepository. Сам класс хранит только данные.
"""
SCHEMA_VERSION: int = 1 # NB: не Field — это class-level metadata, не pydantic field
base_currency: str = "RUB"
accounts: list[Account] = Field(default_factory=list)
transactions: list[Transaction] = Field(default_factory=list)
recurring: list[RecurringCashflow] = Field(default_factory=list)
assets: list[Asset] = Field(default_factory=list)
liabilities: list[Liability] = Field(default_factory=list)
scenarios: list[ForecastScenario] = Field(default_factory=list)
exchange_rates: list[ExchangeRate] = Field(
default_factory=lambda: [r.model_copy() for r in DEFAULT_RATES]
)
def to_dict(self) -> dict:
"""Сериализация в dict с version и UUID-as-str (для JSON)."""
return {
"version": self.SCHEMA_VERSION,
"base_currency": self.base_currency,
"accounts": [a.model_dump(mode="json") for a in self.accounts],
"transactions": [t.model_dump(mode="json") for t in self.transactions],
"recurring": [r.model_dump(mode="json") for r in self.recurring],
"assets": [a.model_dump(mode="json") for a in self.assets],
"liabilities": [li.model_dump(mode="json") for li in self.liabilities],
"scenarios": [s.model_dump(mode="json") for s in self.scenarios],
"exchange_rates": [e.model_dump(mode="json") for e in self.exchange_rates],
}
@classmethod
def from_dict(cls, data: dict) -> "FinancialModel":
version = data.get("version", 0)
if version == 0:
return cls._from_legacy(data)
if version == 1:
return cls._from_v1(data)
raise ValueError(f"Unsupported FinancialModel version: {version}")
@classmethod
def _from_v1(cls, data: dict) -> "FinancialModel":
return cls(
base_currency=data.get("base_currency", "RUB"),
accounts=[Account.model_validate(a) for a in data.get("accounts", [])],
transactions=[Transaction.model_validate(t) for t in data.get("transactions", [])],
recurring=[RecurringCashflow.model_validate(r) for r in data.get("recurring", [])],
assets=[Asset.model_validate(a) for a in data.get("assets", [])],
liabilities=[Liability.model_validate(li) for li in data.get("liabilities", [])],
scenarios=[ForecastScenario.model_validate(s) for s in data.get("scenarios", [])],
exchange_rates=[ExchangeRate.model_validate(r) for r in data.get("exchange_rates", [])],
)
@classmethod
def _from_legacy(cls, data: dict) -> "FinancialModel":
# Legacy: файлы без version. Структура совпадает с v1.
return cls._from_v1(data)
-27
View File
@@ -1,27 +0,0 @@
from decimal import Decimal
from uuid import UUID, uuid4
from pydantic import BaseModel, Field, field_validator
class RecurringCashflow(BaseModel):
id: UUID = Field(default_factory=uuid4)
start_date: str = ""
end_date: str = ""
frequency: str = "monthly"
amount: Decimal = Field(default=Decimal("0"))
category: str = ""
@field_validator("frequency")
@classmethod
def _frequency_known(cls, v: str) -> str:
if v not in {"daily", "weekly", "monthly", "yearly"}:
raise ValueError(f"unknown frequency: {v}")
return v
@field_validator("amount")
@classmethod
def _amount_nonzero(cls, v: Decimal) -> Decimal:
if v == 0:
raise ValueError("amount must be non-zero")
return v
-20
View File
@@ -1,20 +0,0 @@
from decimal import Decimal
from uuid import UUID, uuid4
from pydantic import BaseModel, Field, field_validator
class ForecastScenario(BaseModel):
id: UUID = Field(default_factory=uuid4)
name: str = "baseline"
income_multiplier: Decimal = Field(default=Decimal("1"))
expense_multiplier: Decimal = Field(default=Decimal("1"))
growth_multiplier: Decimal = Field(default=Decimal("1"))
description: str = ""
@field_validator("income_multiplier", "expense_multiplier", "growth_multiplier")
@classmethod
def _non_negative(cls, v: Decimal) -> Decimal:
if v < 0:
raise ValueError("multiplier must be non-negative")
return v
-20
View File
@@ -1,20 +0,0 @@
from decimal import Decimal
from uuid import UUID, uuid4
from pydantic import BaseModel, Field, field_validator
class Transaction(BaseModel):
id: UUID = Field(default_factory=uuid4)
date: str = ""
account: str = ""
category: str = ""
amount: Decimal = Field(default=Decimal("0"))
description: str = ""
@field_validator("amount")
@classmethod
def _amount_nonzero(cls, v: Decimal) -> Decimal:
if v == 0:
raise ValueError("amount must be non-zero")
return v

Some files were not shown because too many files have changed in this diff Show More