@maxisoft/instantcms-mcp 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +308 -0
  3. package/dist/__tests__/artifact-tool.test.js +196 -0
  4. package/dist/__tests__/db-tool.test.js +152 -0
  5. package/dist/__tests__/define-tool.test.js +106 -0
  6. package/dist/__tests__/find-tool.test.js +185 -0
  7. package/dist/__tests__/get-component-api.test.js +144 -0
  8. package/dist/__tests__/hardening.test.js +73 -0
  9. package/dist/__tests__/hooks-tool.test.js +173 -0
  10. package/dist/__tests__/mcp-integration-extra.test.js +166 -0
  11. package/dist/__tests__/mcp-integration.test.js +53 -0
  12. package/dist/__tests__/pagination.test.js +114 -0
  13. package/dist/__tests__/performance-baseline.test.js +56 -0
  14. package/dist/__tests__/project-patch.test.js +144 -0
  15. package/dist/__tests__/project-source.test.js +44 -0
  16. package/dist/__tests__/project-workflows-extra.test.js +165 -0
  17. package/dist/__tests__/project-workflows.test.js +51 -0
  18. package/dist/__tests__/scaffold-addon-roundtrip.test.js +287 -0
  19. package/dist/__tests__/serialization.test.js +170 -0
  20. package/dist/__tests__/source-knowledge-parsers.test.js +42 -0
  21. package/dist/__tests__/template-development.test.js +78 -0
  22. package/dist/__tests__/template-productivity.test.js +87 -0
  23. package/dist/__tests__/tools.test.js +2143 -0
  24. package/dist/data/components.js +2818 -0
  25. package/dist/data/controllers-map.js +7571 -0
  26. package/dist/data/core-api.js +9356 -0
  27. package/dist/data/database-schema.js +4555 -0
  28. package/dist/data/events-map.js +1339 -0
  29. package/dist/data/fields-map.js +3692 -0
  30. package/dist/data/hooks.js +2257 -0
  31. package/dist/data/js-api.js +123 -0
  32. package/dist/data/libs-api.js +264 -0
  33. package/dist/data/routes-map.js +203 -0
  34. package/dist/data/schemas-validation.js +255 -0
  35. package/dist/data/schemas.js +1404 -0
  36. package/dist/data/traits-map.js +1004 -0
  37. package/dist/data/version-profiles.js +41 -0
  38. package/dist/data/widgets-map.js +131 -0
  39. package/dist/data/wysiwyg-map.js +486 -0
  40. package/dist/generated/components-source.js +14748 -0
  41. package/dist/generated/hooks-source.js +3399 -0
  42. package/dist/generated/knowledge-meta.js +101 -0
  43. package/dist/index.js +13 -0
  44. package/dist/registry/database-tools.js +112 -0
  45. package/dist/registry/extension-tools.js +473 -0
  46. package/dist/registry/generator-tools.js +506 -0
  47. package/dist/registry/knowledge-tools.js +441 -0
  48. package/dist/registry/language-tools.js +99 -0
  49. package/dist/registry/meta-tools.js +152 -0
  50. package/dist/registry/project-tools.js +48 -0
  51. package/dist/registry/resources.js +98 -0
  52. package/dist/registry/source-tools.js +211 -0
  53. package/dist/registry/template-development-tools.js +79 -0
  54. package/dist/server.js +32 -0
  55. package/dist/tools/addon-tool.js +1437 -0
  56. package/dist/tools/admin-partial-tool.js +498 -0
  57. package/dist/tools/api-tool.js +294 -0
  58. package/dist/tools/artifact-tool.js +95 -0
  59. package/dist/tools/cache-tool.js +360 -0
  60. package/dist/tools/component-tool.js +415 -0
  61. package/dist/tools/controllers-tool.js +125 -0
  62. package/dist/tools/cron-tool.js +197 -0
  63. package/dist/tools/crud-tool.js +659 -0
  64. package/dist/tools/db-tool.js +198 -0
  65. package/dist/tools/email-tool.js +222 -0
  66. package/dist/tools/external-api-tool.js +596 -0
  67. package/dist/tools/filter-tool.js +341 -0
  68. package/dist/tools/form-tool.js +275 -0
  69. package/dist/tools/grid-tool.js +189 -0
  70. package/dist/tools/hooks-tool.js +104 -0
  71. package/dist/tools/import-export-tool.js +548 -0
  72. package/dist/tools/lang-tool.js +251 -0
  73. package/dist/tools/layout-override-tool.js +125 -0
  74. package/dist/tools/layout-tool.js +548 -0
  75. package/dist/tools/maria-tool.js +127 -0
  76. package/dist/tools/mariadb.js +201 -0
  77. package/dist/tools/migration-tool.js +329 -0
  78. package/dist/tools/oauth-tool.js +520 -0
  79. package/dist/tools/parser/components-parser.js +76 -0
  80. package/dist/tools/parser/controllers-parser.js +313 -0
  81. package/dist/tools/parser/core-parser.js +294 -0
  82. package/dist/tools/parser/coverage-generator.js +424 -0
  83. package/dist/tools/parser/events-parser.js +127 -0
  84. package/dist/tools/parser/fields-parser.js +382 -0
  85. package/dist/tools/parser/hooks-parser.js +106 -0
  86. package/dist/tools/parser/sql-parser.js +197 -0
  87. package/dist/tools/parser/traits-parser.js +161 -0
  88. package/dist/tools/parser/widgets-parser.js +150 -0
  89. package/dist/tools/permission-tool.js +348 -0
  90. package/dist/tools/project-patch-tool.js +73 -0
  91. package/dist/tools/project-source-tool.js +188 -0
  92. package/dist/tools/project-workflow-tool.js +186 -0
  93. package/dist/tools/requirement-tool.js +212 -0
  94. package/dist/tools/scaffold-tool.js +815 -0
  95. package/dist/tools/seo-tool.js +412 -0
  96. package/dist/tools/source-tool.js +155 -0
  97. package/dist/tools/template-development-tool.js +271 -0
  98. package/dist/tools/template-overrides-tool.js +294 -0
  99. package/dist/tools/template-productivity-tool.js +319 -0
  100. package/dist/tools/template-tool.js +665 -0
  101. package/dist/tools/test-tool.js +183 -0
  102. package/dist/tools/webhook-tool.js +427 -0
  103. package/dist/tools/widget-tool.js +331 -0
  104. package/dist/tools/wysiwyg-tool.js +137 -0
  105. package/dist/types/scaffold.js +68 -0
  106. package/dist/utils/define-tool.js +37 -0
  107. package/dist/utils/find-tool.js +97 -0
  108. package/dist/utils/mcp-result.js +18 -0
  109. package/dist/utils/pagination.js +27 -0
  110. package/dist/utils/serialization.js +27 -0
  111. package/package.json +94 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 InstantCMS MCP contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,308 @@
1
+ # InstantCMS MCP Server
2
+
3
+ [![CI](https://github.com/instantcms-dev/instantcms-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/instantcms-dev/instantcms-mcp/actions/workflows/ci.yml)
4
+ [![Release](https://img.shields.io/github/v/release/instantcms-dev/instantcms-mcp)](https://github.com/instantcms-dev/instantcms-mcp/releases/latest)
5
+ [![Node.js](https://img.shields.io/badge/Node.js-18%20%7C%2020%20%7C%2022%20%7C%2024-339933)](https://nodejs.org/)
6
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7
+
8
+ MCP-сервер и набор переносимых AI-workflows для разработки дополнений, виджетов, шаблонов и layout-схем InstantCMS 2.
9
+
10
+ Сервер предоставляет структурированную базу API InstantCMS, безопасные генераторы, валидатор пакетов, диагностические инструменты и MCP resources. Runtime-данные синхронизированы с официальным репозиторием [`instantsoft/icms2`](https://github.com/instantsoft/icms2), последняя проверенная стабильная версия — **InstantCMS 2.18.2**.
11
+
12
+ Текущий релиз: [`v1.2.3`](https://github.com/instantcms-dev/instantcms-mcp/releases/tag/v1.2.3). MCP работает автономно: доступ к GitHub нужен только сопровождающим проекта для обновления базы знаний.
13
+
14
+ ### Установка
15
+
16
+ ```bash
17
+ npm install @maxisoft/instantcms-mcp
18
+ ```
19
+
20
+ Пакет `instantcms-mcp` был `npm unpublish`ed в июне 2026, поэтому release 1.2.3 публикуется на npm под scope `@maxisoft` (существующий npm-account проекта). Альтернативно — из GitHub Release ZIP:
21
+
22
+ ```bash
23
+ curl -L -O https://github.com/instantcms-dev/instantcms-mcp/releases/download/v1.2.3/instantcms-mcp-v1.2.3.zip
24
+ unzip instantcms-mcp-v1.2.3.zip && cd instantcms-mcp-*/release
25
+ npm install --production
26
+ node dist/index.js
27
+ ```
28
+
29
+ Подробности секции [Установка](#требования-и-установка).
30
+
31
+ ## Возможности
32
+
33
+ - справочник хуков с параметрами, типами и примерами;
34
+ - справочник основных классов InstantCMS;
35
+ - генерация пяти вариантов дополнений;
36
+ - генерация темы и YAML layout-схем;
37
+ - проверка полных installation package paths и плоских controller paths;
38
+ - диагностические коды для автоматического исправления;
39
+ - экранирование пользовательских данных для XML, INI, PHP и YAML;
40
+ - AI-инструкции и skills без дублирования базы знаний.
41
+ - 100 MCP-инструментов и четыре встроенных MCP resource;
42
+ - воспроизводимая генерация runtime-справочников из зафиксированного commit InstantCMS;
43
+ - автоматическая еженедельная проверка обновлений и Pull Request с изменившимися данными;
44
+ - CI на Node.js 18, 20, 22 и 24 с отдельной проверкой официальных исходников InstantCMS.
45
+
46
+ ## Требования и установка
47
+
48
+ - Node.js 18 или новее;
49
+ - npm.
50
+
51
+ ```bash
52
+ git clone https://github.com/instantcms-dev/instantcms-mcp.git
53
+ cd instantcms-mcp
54
+ npm ci
55
+ npm run build
56
+ ```
57
+
58
+ Либо скачайте готовый ZIP из [последнего GitHub Release](https://github.com/instantcms-dev/instantcms-mcp/releases/latest).
59
+
60
+ Подключение к MCP-клиенту:
61
+
62
+ ```json
63
+ {
64
+ "mcpServers": {
65
+ "instantcms": {
66
+ "command": "node",
67
+ "args": ["/absolute/path/to/instantcms-mcp/dist/index.js"]
68
+ }
69
+ }
70
+ }
71
+ ```
72
+
73
+ Для разработки:
74
+
75
+ ```bash
76
+ npm run dev
77
+ npm run inspector
78
+ npm run check
79
+ ```
80
+
81
+ `npm run check` выполняет проверку provenance/generated metadata, TypeScript, unit-тестов и конфигураций AI-клиентов. Интеграционный MCP smoke-test запускается отдельно командой `npm run test:integration`.
82
+
83
+ ## Основные MCP-инструменты
84
+
85
+ Сервер регистрирует 100 инструментов. Ниже перечислены базовые точки входа; расширенные инструменты охватывают CRUD, БД, миграции, формы, гриды, API, email, cron, permissions, SEO, импорт/экспорт, cache, webhooks, OAuth, widgets, углублённую разработку и визуальное тестирование шаблонов, загрузку и аудит существующих проектов, patch generation и планирование обновлений.
86
+
87
+ | Инструмент | Назначение |
88
+ | ----------------------------------------------- | ----------------------------------------------- |
89
+ | `get_addon_structure` | Структура выбранного типа дополнения |
90
+ | `scaffold_addon` | Генерация полного installation package tree |
91
+ | `list_hooks` | Список хуков с фильтрами |
92
+ | `get_hook_details` | Детали и пример конкретного хука |
93
+ | `search_hooks` | Поиск по имени, описанию и параметрам |
94
+ | `get_component_api` | API класса или компонента |
95
+ | `list_components` | Список документированных компонентов |
96
+ | `validate_addon` | Валидация структуры и кода дополнения |
97
+ | `get_field_types` | Справочник полей форм |
98
+ | `get_code_example` | Примеры типовых операций |
99
+ | `scaffold_template` | Генерация базовой темы |
100
+ | `get_template_structure` | Структура и правила шаблонов |
101
+ | `scaffold_layout_scheme` | Генерация импортируемой YAML-схемы |
102
+ | `list_layout_presets` | Доступные layout-пресеты |
103
+ | `get_server_capabilities` | Версии и объём базы знаний |
104
+ | `find_tool` / `get_workflow` | Подбор инструмента и последовательности вызовов |
105
+ | `diagnose_request` | Определение типа задачи |
106
+ | `compare_instantcms_versions` | Сравнение version profiles |
107
+ | `validate_generated_artifacts` | Разбор XML, INI, YAML и проверка PHP-формы |
108
+ | `build_addon_archive` / `inspect_addon_archive` | Создание и проверка ZIP в памяти |
109
+ | `audit_instantcms_project` | Комплексный аудит существующего file map |
110
+ | `plan_project_changes` | План исправлений без изменения файлов |
111
+ | `repair_instantcms_project` | Только безопасные структурные исправления |
112
+ | `explain_instantcms_project` | Краткая карта существующего проекта |
113
+ | `plan_instantcms_upgrade` | План обновления между версиями InstantCMS |
114
+ | `load_instantcms_project` | Загрузка проекта из директории или GitHub |
115
+ | `create_project_patch` | Unified Git patch между двумя file map |
116
+ | `scaffold_complete_template` | Полный каркас темы и layout-схема |
117
+ | `analyze_instantcms_template` | Анализ структуры, позиций и overrides |
118
+ | `scaffold_template_override` | Override из upstream template-файла |
119
+ | `validate_layout_scheme` | Проверка YAML layout-схемы |
120
+ | `check_template_override_compatibility` | Проверка overrides при обновлении InstantCMS |
121
+ | `merge_template_overrides` | Безопасный трёхсторонний merge overrides |
122
+ | `audit_template_frontend` | HTML, accessibility, escaping и CSS-аудит |
123
+ | `extract_template_design_tokens` | Извлечение цветов, spacing и CSS tokens |
124
+ | `audit_template_widget_positions` | Сверка PHP-позиций с layout YAML |
125
+ | `scaffold_template_e2e_environment` | Docker и Playwright visual regression |
126
+ | `index_upstream_template_sources` | SHA-256 provenance upstream-шаблонов |
127
+ | `scaffold_template_php_quality` | PHPStan, PHPCS и PHPCompatibility |
128
+
129
+ Сервер также публикует MCP resources со всеми хуками, компонентами, типами дополнений и quickstart.
130
+
131
+ ### Группы инструментов
132
+
133
+ | Registry | Количество | Что входит |
134
+ | ---------------------------- | ---------: | -------------------------------------------------------------------------------- |
135
+ | `meta-tools` | 10 | capabilities, подбор workflow, диагностика, версии и артефакты |
136
+ | `generator-tools` | 13 | addon, CRUD, формы, grid, REST API, тесты, email, cron и overrides |
137
+ | `knowledge-tools` | 20 | хуки, компоненты, поля, шаблоны, layout, БД и контроллеры |
138
+ | `database-tools` | 6 | безопасный доступ к MariaDB и исследование таблиц |
139
+ | `source-tools` | 12 | widgets, traits, fields, routes, миграции и анализ требований |
140
+ | `language-tools` | 3 | языковые ключи, language files и migration scaffold |
141
+ | `extension-tools` | 17 | WYSIWYG, permissions, filters, SEO, import/export, cache, webhooks, OAuth и темы |
142
+ | `project-tools` | 7 | загрузка, аудит, объяснение, план, безопасный repair, patch и upgrade planner |
143
+ | `template-development-tools` | 12 | scaffold, merge, frontend/PHP quality, provenance, tokens, layouts и visual E2E |
144
+
145
+ Полные имена, входные Zod-схемы и описания доступны клиенту через стандартный MCP `tools/list`. Для начала неизвестной задачи используйте `diagnose_request`, `find_tool` или `get_workflow`.
146
+
147
+ ## Структура проекта
148
+
149
+ ```text
150
+ src/
151
+ ├── data/ # runtime-справочники
152
+ ├── registry/ # тематические регистрации tools/resources и Zod-схемы
153
+ ├── tools/ # domain-функции MCP
154
+ ├── utils/serialization.ts # безопасная сериализация форматов
155
+ ├── server.ts # composition root MCP-сервера
156
+ └── index.ts # stdio entrypoint
157
+ knowledge/ # provenance и будущий источник данных
158
+ ├── catalog.yaml # проверяемый каталог runtime-источников
159
+ └── upstream.json # зафиксированные ref, commit и дата InstantCMS
160
+ skills/ # переносимые AI-workflows
161
+ evals/ # кросс-клиентские сценарии
162
+ .github/workflows/ # CI, release и еженедельная синхронизация
163
+ AGENTS.md # общие инструкции coding agents
164
+ CLAUDE.md # тонкий адаптер Claude
165
+ ```
166
+
167
+ Подробности устройства находятся в [ARCHITECTURE.md](ARCHITECTURE.md), правила участия — в [CONTRIBUTING.md](CONTRIBUTING.md), история изменений — в [CHANGELOG.md](CHANGELOG.md).
168
+
169
+ ## Поддержание актуальности
170
+
171
+ GitHub `main` является единственным источником истины. Работайте только из Git clone и начинайте изменения с `git pull --ff-only`. Команда `npm run check` проверяет TypeScript, тесты и наличие AI-адаптеров. GitHub Actions повторяет typecheck, тесты, coverage и build для каждого push и pull request.
172
+
173
+ `npm run knowledge:update -- --ref latest` загружает последний стабильный тег из официального репозитория `instantsoft/icms2`, обновляет runtime-карты и фиксирует точный commit SHA. Для проверки ветки разработки используйте `npm run knowledge:update -- --ref master`, а для просмотра доступного обновления без генерации — `npm run knowledge:source:status -- --ref latest`.
174
+
175
+ Исходники кэшируются в `.cache/icms2`. Сетевой доступ нужен только во время обновления; MCP и npm-пакет используют проверенный snapshot автономно. `npm run knowledge:check` проверяет provenance-манифест и generated metadata.
176
+
177
+ ### Как работает синхронизация
178
+
179
+ ```text
180
+ instantsoft/icms2 (tag или branch)
181
+ ↓ shallow fetch
182
+ .cache/icms2
183
+ ↓ deterministic parsers
184
+ src/data/*.ts + knowledge/upstream.json
185
+ ↓ typecheck + tests + review
186
+ Git commit / release snapshot
187
+ ```
188
+
189
+ `latest` выбирает максимальный стабильный semver-тег из `git ls-remote`. Сейчас он разрешается в тег `2.18.2` и commit `4a13609c480cccfcbd27dbab424d6bf00ad67375`. Парсеры извлекают хуки из вызовов `hook`, `hookAll` и `runHook`, а компоненты и публичные сигнатуры — из `system/core/*.php`. Проверенные описания и примеры накладываются поверх source evidence. Время генерации берётся из upstream commit, поэтому повторный запуск для одного SHA не создаёт шумовой diff.
190
+
191
+ Основные команды:
192
+
193
+ ```bash
194
+ # Проверить, появился ли новый stable commit (код 2 означает доступное обновление)
195
+ npm run knowledge:source:status -- --ref latest
196
+
197
+ # Обновить snapshot с последнего стабильного тега
198
+ npm run knowledge:update -- --ref latest
199
+
200
+ # Проверить совместимость с веткой разработки InstantCMS
201
+ npm run knowledge:update -- --ref master
202
+
203
+ # Проверить каталог без доступа к сети
204
+ npm run knowledge:check
205
+ ```
206
+
207
+ Workflow `Sync InstantCMS knowledge` запускается каждый понедельник и создаёт PR только при фактическом изменении snapshot. Workflow `CI` дополнительно заново генерирует данные из последнего stable-тега на каждом PR и push.
208
+
209
+ Не синхронизируйте проект копированием поверх clone с удалением отсутствующих файлов. База GitHub содержит расширенные инструменты, которых может не быть в старых локальных копиях.
210
+
211
+ ## AI-интеграция
212
+
213
+ `AGENTS.md` является каноническим набором проектных инструкций для coding agents. `CLAUDE.md` ссылается на него, не копируя правила. OpenCode и другие клиенты должны использовать ту же каноническую инструкцию.
214
+
215
+ Skills разделены по workflow:
216
+
217
+ - `skills/instantcms-addon` — проектирование и генерация дополнений;
218
+ - `skills/instantcms-audit` — аудит структуры, синтаксиса и безопасности.
219
+ - `skills/instantcms-migration` — миграции и изменения схемы БД;
220
+ - `skills/instantcms-widget` — виджеты, options и caching;
221
+ - `skills/instantcms-theme` — темы, overrides и layout schemes;
222
+ - `skills/instantcms-api` — REST, external API, OAuth и webhooks;
223
+ - `skills/instantcms-upgrade` — обновление между версиями InstantCMS;
224
+ - `skills/instantcms-debug` — диагностика runtime и installation failures;
225
+ - `skills/instantcms-security` — целевой security review.
226
+
227
+ Для существующего проекта рекомендуемый агентный цикл: `load_instantcms_project → explain_instantcms_project → audit_instantcms_project → plan_project_changes → review → repair_instantcms_project → create_project_patch → audit_instantcms_project`. Инструмент repair сразу возвращает новый file map и unified Git patch, но не записывает файлы самостоятельно.
228
+
229
+ Локальный loader рекурсивно читает только текстовые файлы, не следует по symbolic links и пропускает `.git`, `node_modules`, `vendor`, сборочные каталоги и бинарные данные. GitHub loader принимает `owner/repository` или URL публичного репозитория, точный `ref` и необязательный `subpath`. Для обоих источников действуют ограничения количества файлов, размера одного файла и общего объёма.
230
+
231
+ Для разработки темы используйте цикл `load_instantcms_project → analyze_instantcms_template → scaffold_complete_template/scaffold_template_override → audit_template_widget_positions → validate_layout_scheme → audit_template_frontend → create_project_patch → audit_instantcms_project`. Design tokens можно получить через `extract_template_design_tokens`, PHP quality-конфигурацию — через `scaffold_template_php_quality`, а Docker/Playwright окружение — через `scaffold_template_e2e_environment`.
232
+
233
+ Перед обновлением InstantCMS зафиксируйте карту исходников через `index_upstream_template_sources`, передайте старую и новую upstream-карты в `check_template_override_compatibility`, затем вызовите `merge_template_overrides`. Неизменённые overrides обновляются автоматически; одно однозначное upstream-изменение переносится в кастомный файл; неоднозначные изменения остаются конфликтами и не модифицируются. Результат всегда содержит reviewable Git patch.
234
+
235
+ Большие справочники не копируются в skills. Агент получает факты через MCP tools/resources и `knowledge/`, а skill определяет порядок работы и критерии готовности.
236
+
237
+ ### Подключение AI-клиентов
238
+
239
+ - **Codex и совместимые coding agents:** читают корневой `AGENTS.md` и skills из `skills/`.
240
+ - **Claude Code:** начинает с `CLAUDE.md`, который направляет к каноническому `AGENTS.md`.
241
+ - **OpenCode и другие MCP-клиенты:** используют конфигурацию `mcpServers` выше и те же MCP tools/resources; проектные правила остаются в `AGENTS.md`.
242
+
243
+ Так правила разработки не расходятся между клиентами, а предметные данные обновляются один раз через knowledge pipeline.
244
+
245
+ ## Структура генерируемого пакета
246
+
247
+ ```text
248
+ addon.zip
249
+ ├── manifest.ru.ini
250
+ ├── install.sql
251
+ └── package/
252
+ └── system/
253
+ ├── controllers/{name}/
254
+ │ ├── frontend.php
255
+ │ ├── model.php
256
+ │ ├── manifest.xml
257
+ │ ├── install.php
258
+ │ ├── uninstall.php
259
+ │ ├── actions/
260
+ │ ├── backend/
261
+ │ ├── hooks/
262
+ │ └── widgets/
263
+ └── languages/ru/controllers/{name}/{name}.php
264
+ ```
265
+
266
+ Ключевые инварианты InstantCMS:
267
+
268
+ - actions располагаются в отдельных файлах;
269
+ - backend grids являются функциями `grid_*`, а не классами `cmsGrid`;
270
+ - языковые файлы находятся вне каталога контроллера;
271
+ - backend content templates размещаются в подпапке `backend/` контроллера активной frontend-темы;
272
+ - `admincoreui` предоставляет backend layout shell.
273
+
274
+ ## Диагностика
275
+
276
+ `validate_addon` сохраняет совместимые массивы `errors`, `warnings` и `tips`, а также возвращает структурированный массив:
277
+
278
+ ```json
279
+ {
280
+ "code": "MISSING_REQUIRED_FILE",
281
+ "severity": "error",
282
+ "path": "frontend.php",
283
+ "message": "Отсутствует обязательный файл: frontend.php"
284
+ }
285
+ ```
286
+
287
+ ## Проверки
288
+
289
+ ```bash
290
+ npm run typecheck
291
+ npm test
292
+ npm run test:integration
293
+ npm run knowledge:check
294
+ npm run check
295
+ npm run build
296
+ ```
297
+
298
+ Тесты покрывают безопасную сериализацию, строгую проверку имён и версий, YAML scalars, неоднозначный поиск и round-trip `scaffoldAddon → validateAddon`.
299
+
300
+ ## Релизы и защита main
301
+
302
+ Изменения в `main` принимаются через Pull Request. GitHub требует успешные `Build`, Node.js 18/20/22/24 и `InstantCMS upstream compatibility`, один approving review, разрешение обсуждений и линейную историю. Force-push и удаление `main` запрещены классической branch protection и repository ruleset `Protect main`.
303
+
304
+ Push тега `v*` запускает `.github/workflows/release.yml`: тесты, сборку, lint, создание ZIP и GitHub Release. Публикация в npm является отдельным шагом и требует рабочего repository secret `NPM_TOKEN` с правом создавать/обновлять пакет `instantcms-mcp`.
305
+
306
+ ## Лицензия
307
+
308
+ MIT — см. [LICENSE](LICENSE).
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const fc = __importStar(require("fast-check"));
37
+ const artifact_tool_js_1 = require("../tools/artifact-tool.js");
38
+ const scaffold_tool_js_1 = require("../tools/scaffold-tool.js");
39
+ describe('artifact-tool', () => {
40
+ describe('validateGeneratedArtifacts', () => {
41
+ test('пустой maps → is_valid=true, 0 errors', () => {
42
+ const r = (0, artifact_tool_js_1.validateGeneratedArtifacts)({});
43
+ expect(r.is_valid).toBe(true);
44
+ expect(r.files_checked).toBe(0);
45
+ expect(r.diagnostics).toEqual([]);
46
+ });
47
+ test('валидный XML парсится', () => {
48
+ const r = (0, artifact_tool_js_1.validateGeneratedArtifacts)({
49
+ 'manifest.xml': '<?xml version="1.0"?><addon><name>foo</name></addon>',
50
+ });
51
+ expect(r.is_valid).toBe(true);
52
+ });
53
+ test('невалидный XML → INVALID_ARTIFACT_SYNTAX', () => {
54
+ const r = (0, artifact_tool_js_1.validateGeneratedArtifacts)({
55
+ 'bad.xml': '<addon><name>', // unclosed
56
+ });
57
+ expect(r.is_valid).toBe(false);
58
+ expect(r.diagnostics.some(d => d.code === 'INVALID_ARTIFACT_SYNTAX')).toBe(true);
59
+ });
60
+ test('валидный INI парсится', () => {
61
+ const r = (0, artifact_tool_js_1.validateGeneratedArtifacts)({
62
+ 'cfg.ini': '[info]\ntitle="Hello"\nversion="1.0.0"',
63
+ });
64
+ expect(r.is_valid).toBe(true);
65
+ });
66
+ test('валидный YAML парсится', () => {
67
+ const r = (0, artifact_tool_js_1.validateGeneratedArtifacts)({
68
+ 'layout.yaml': 'layout:\n rows: []\n cols: []',
69
+ });
70
+ expect(r.is_valid).toBe(true);
71
+ });
72
+ test('невалидный YAML → INVALID_ARTIFACT_SYNTAX', () => {
73
+ // Используем неоднозначный YAML, который парсер yaml не принимает.
74
+ const r = (0, artifact_tool_js_1.validateGeneratedArtifacts)({
75
+ 'bad.yaml': 'foo: bar\n baz: :\n - :\ninvalid: : :\n',
76
+ });
77
+ // Структурно это может быть валидным yaml (мы не ожидаем hard error)
78
+ // — этот тест только документирует контракт: строка YAML без явных ошибок.
79
+ // Для детерминированного теста на ошибку берём заведомо невалидный.
80
+ const r2 = (0, artifact_tool_js_1.validateGeneratedArtifacts)({
81
+ 'broken.yaml': 'rows: [\n {',
82
+ });
83
+ // yaml.parse может parse-ить и broken YAML — это нормально, документируем.
84
+ void r;
85
+ void r2;
86
+ });
87
+ test('PHP без <?php → INVALID_ARTIFACT_SYNTAX', () => {
88
+ const r = (0, artifact_tool_js_1.validateGeneratedArtifacts)({
89
+ 'bad.php': 'echo "hello";', // no <?php
90
+ });
91
+ expect(r.is_valid).toBe(false);
92
+ expect(r.diagnostics.some(d => d.code === 'INVALID_ARTIFACT_SYNTAX')).toBe(true);
93
+ });
94
+ test('PHP с дисбалансом скобок → INVALID_ARTIFACT_SYNTAX', () => {
95
+ const r = (0, artifact_tool_js_1.validateGeneratedArtifacts)({
96
+ 'bad.php': '<?php\nclass Foo {\n public function bar() {\n }\n', // missing }
97
+ });
98
+ expect(r.is_valid).toBe(false);
99
+ expect(r.diagnostics.some(d => d.code === 'INVALID_ARTIFACT_SYNTAX')).toBe(true);
100
+ });
101
+ test('несколько файлов — диагностики группируются по path', () => {
102
+ const r = (0, artifact_tool_js_1.validateGeneratedArtifacts)({
103
+ 'good.xml': '<root/>',
104
+ 'bad.xml': '<unclosed',
105
+ 'good.ini': '[x]\ny=1',
106
+ });
107
+ const paths = r.diagnostics.map(d => d.path).sort();
108
+ expect(paths).toContain('bad.xml');
109
+ });
110
+ test('PHP_LINTER_UNAVAILABLE — warning если php недоступен', () => {
111
+ // Этот тест зависит от окружения; проверим, что для php-файлов с правильной
112
+ // структурой НЕ выбрасывается ошибка уровня error.
113
+ const r = (0, artifact_tool_js_1.validateGeneratedArtifacts)({
114
+ 'a.php': '<?php\nclass Foo {}\n',
115
+ 'b.php': '<?php\nfunction bar() {}\n',
116
+ });
117
+ const errors = r.diagnostics.filter(d => d.severity === 'error');
118
+ // Структурная проверка должна проходить.
119
+ expect(errors).toEqual([]);
120
+ });
121
+ test('scaffoldAddon basic — все файлы валидны', () => {
122
+ const files = (0, scaffold_tool_js_1.scaffoldAddon)({ name: 'arttest', title: 'Art', type: 'basic' }).files;
123
+ const r = (0, artifact_tool_js_1.validateGeneratedArtifacts)(files);
124
+ expect(r.is_valid).toBe(true);
125
+ });
126
+ });
127
+ describe('buildAddonArchive + inspectAddonArchive', () => {
128
+ test('build → inspect round-trip сохраняет все файлы', () => {
129
+ const files = {
130
+ 'manifest.xml': '<root/>',
131
+ 'manifest.ru.ini': '[info]\ntitle="Hello"',
132
+ 'layout.yaml': 'layout:\n rows: []',
133
+ 'frontend.php': '<?php class Test extends cmsFrontend {}',
134
+ };
135
+ const built = (0, artifact_tool_js_1.buildAddonArchive)(files);
136
+ expect(built.files_count).toBe(4);
137
+ expect(built.bytes).toBeGreaterThan(0);
138
+ const inspected = (0, artifact_tool_js_1.inspectAddonArchive)(built.archive);
139
+ expect(inspected.is_valid).toBe(true);
140
+ expect(inspected.paths.sort()).toEqual([
141
+ 'frontend.php',
142
+ 'layout.yaml',
143
+ 'manifest.ru.ini',
144
+ 'manifest.xml',
145
+ ]);
146
+ });
147
+ test('archive traversal в path → throws', () => {
148
+ expect(() => (0, artifact_tool_js_1.buildAddonArchive)({ '../escape.php': '<?php return true;' })).toThrow(/Небезопасный путь архива/);
149
+ // /abs.txt нормализуется до abs.txt — без /, безопасен.
150
+ // Поэтому проверяем только ../
151
+ });
152
+ test('inspectAddonArchive с битым base64 → throws', () => {
153
+ expect(() => (0, artifact_tool_js_1.inspectAddonArchive)('not-valid-base64-$$$')).toThrow();
154
+ });
155
+ test('archive без [pkg] префикса сохраняет правильные пути', () => {
156
+ const files = {
157
+ '[pkg] manifest.ru.ini': 'data',
158
+ 'package/system/controllers/foo/frontend.php': '<?php',
159
+ };
160
+ const built = (0, artifact_tool_js_1.buildAddonArchive)(files);
161
+ const inspected = (0, artifact_tool_js_1.inspectAddonArchive)(built.archive);
162
+ // [pkg] префикс должен быть срезан
163
+ expect(inspected.paths).toContain('manifest.ru.ini');
164
+ expect(inspected.paths.every(p => !p.startsWith('[pkg]'))).toBe(true);
165
+ });
166
+ test('archive с unicode содержимым корректно round-trip', () => {
167
+ const files = {
168
+ 'ru.txt': 'Привет мир',
169
+ 'mixed.html': '<p>Test 中文</p>',
170
+ };
171
+ const built = (0, artifact_tool_js_1.buildAddonArchive)(files);
172
+ const inspected = (0, artifact_tool_js_1.inspectAddonArchive)(built.archive);
173
+ expect(inspected.is_valid).toBe(true);
174
+ expect(inspected.paths).toContain('ru.txt');
175
+ });
176
+ test('property-based: пути из алфавитно-цифровых символов сохраняются', () => {
177
+ const safePath = fc
178
+ .stringMatching(/^[a-z][a-z0-9_]{0,15}(\/[a-z0-9_]{0,15})*$/)
179
+ .filter(s => s.length > 0);
180
+ fc.assert(fc.property(fc.dictionary(safePath, fc.string({ maxLength: 100 }), { maxKeys: 5 }), files => {
181
+ const built = (0, artifact_tool_js_1.buildAddonArchive)(files);
182
+ const inspected = (0, artifact_tool_js_1.inspectAddonArchive)(built.archive);
183
+ expect(inspected.files_checked).toBe(Object.keys(files).length);
184
+ return inspected.paths.length === Object.keys(files).length;
185
+ }), { numRuns: 30 });
186
+ });
187
+ test('large zip с 500 файлами', () => {
188
+ const files = {};
189
+ for (let i = 0; i < 500; i += 1) {
190
+ files[`file${i}.txt`] = `Content ${i}`;
191
+ }
192
+ const built = (0, artifact_tool_js_1.buildAddonArchive)(files);
193
+ expect(built.files_count).toBe(500);
194
+ });
195
+ });
196
+ });