@rsconcept/rstool 1.9.0 → 2.0.0

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 (105) hide show
  1. package/README.md +3 -3
  2. package/dist/mappers/model-adapter.d.ts +1 -2
  3. package/dist/mappers/schema-adapter.d.ts +1 -2
  4. package/dist/mappers/types.d.ts +4 -5
  5. package/dist/models/rstool-agent.js +1 -2
  6. package/dist/session/session-store.d.ts +3 -3
  7. package/dist/session/session-store.js +1 -2
  8. package/dist/wrapper/client.d.ts +3 -4
  9. package/docs/BRIEF.md +93 -0
  10. package/docs/CONCEPTUAL-SCHEMA.md +16 -1
  11. package/docs/CONSTRUCTIONS.md +14 -2
  12. package/docs/DIAGNOSTICS.md +3 -2
  13. package/docs/DOMAIN.md +12 -0
  14. package/docs/METHOD.md +208 -0
  15. package/docs/PORTAL-API.md +38 -285
  16. package/docs/PORTAL-MODELS.md +24 -0
  17. package/docs/PORTAL-OSS.md +56 -0
  18. package/docs/PORTAL-PUBLISH.md +39 -0
  19. package/docs/PORTAL-READ.md +301 -0
  20. package/docs/README.md +7 -4
  21. package/docs/REQUIREMENTS.md +61 -0
  22. package/docs/SYNTAX.md +4 -3
  23. package/docs/TYPIFICATION.md +1 -1
  24. package/docs/brief.schema.json +173 -0
  25. package/examples/README.md +16 -2
  26. package/examples/access-control/NOTES.md +23 -0
  27. package/examples/access-control/anti/collapsed.json +439 -0
  28. package/examples/access-control/anti/weakened.json +439 -0
  29. package/examples/access-control/brief-v1.json +231 -0
  30. package/examples/access-control/brief.json +310 -0
  31. package/examples/access-control/build-rsform.ts +151 -0
  32. package/examples/access-control/requirements-v1.md +9 -0
  33. package/examples/access-control/requirements-v2.md +4 -0
  34. package/examples/access-control/rsform-session-v1.json +439 -0
  35. package/examples/access-control/rsform-session.json +523 -0
  36. package/examples/audit-diagnostics.ts +9 -1
  37. package/examples/briefs.test.ts +126 -0
  38. package/examples/clinic-booking/NOTES.md +24 -0
  39. package/examples/clinic-booking/anti/collapsed.json +615 -0
  40. package/examples/clinic-booking/anti/species-as-genus.json +568 -0
  41. package/examples/clinic-booking/brief-v1.json +332 -0
  42. package/examples/clinic-booking/brief.json +405 -0
  43. package/examples/clinic-booking/build-rsform.ts +174 -0
  44. package/examples/clinic-booking/requirements-v1.md +9 -0
  45. package/examples/clinic-booking/requirements-v2.md +4 -0
  46. package/examples/clinic-booking/rsform-session-v1.json +615 -0
  47. package/examples/clinic-booking/rsform-session.json +700 -0
  48. package/examples/diagnostics-utils.ts +26 -0
  49. package/examples/kinship/brief.json +337 -0
  50. package/examples/kinship/build-rsform.ts +7 -4
  51. package/examples/kinship/rsform-session.json +20 -63
  52. package/examples/kinship/rsmodel-session.json +14 -14
  53. package/examples/kinship-subordination/NOTES.md +49 -0
  54. package/examples/kinship-subordination/brief.json +161 -0
  55. package/examples/kinship-subordination/build-rsform.ts +100 -0
  56. package/examples/kinship-subordination/rsform-session.json +795 -0
  57. package/examples/library-loans/NOTES.md +46 -0
  58. package/examples/library-loans/anti/collapsed.json +481 -0
  59. package/examples/library-loans/anti/species-as-genus.json +334 -0
  60. package/examples/library-loans/anti/uncovered.json +406 -0
  61. package/examples/library-loans/anti/weakened.json +464 -0
  62. package/examples/library-loans/brief-v1.json +340 -0
  63. package/examples/library-loans/brief.json +502 -0
  64. package/examples/library-loans/build-rsform.ts +239 -0
  65. package/examples/library-loans/requirements-v1.md +11 -0
  66. package/examples/library-loans/requirements-v2.md +5 -0
  67. package/examples/library-loans/rsform-session-v1.json +481 -0
  68. package/examples/library-loans/rsform-session.json +652 -0
  69. package/examples/library-loans/source-markup.md +18 -0
  70. package/examples/movd/brief.json +220 -0
  71. package/examples/movd/build-rsform.ts +5 -2
  72. package/examples/movd/rsform-session.json +14 -46
  73. package/examples/subordination/NOTES.md +59 -0
  74. package/examples/subordination/anti/collapsed.json +556 -0
  75. package/examples/subordination/anti/single-relation.json +125 -0
  76. package/examples/subordination/anti/transitive.json +573 -0
  77. package/examples/subordination/anti/weakened.json +539 -0
  78. package/examples/subordination/brief.json +386 -0
  79. package/examples/subordination/build-rsform.ts +63 -0
  80. package/examples/subordination/constants.ts +115 -0
  81. package/examples/subordination/rsform-session.json +556 -0
  82. package/examples/subordination/source-markup.md +19 -0
  83. package/examples/subordination/source.md +40 -0
  84. package/package.json +18 -10
  85. package/skills/INSTALL.md +28 -29
  86. package/skills/README.md +25 -10
  87. package/skills/rs-core/SKILL.md +56 -0
  88. package/skills/rs-explain/SKILL.md +28 -0
  89. package/skills/rs-explicate/SKILL.md +71 -0
  90. package/skills/rs-interpret/SKILL.md +67 -0
  91. package/skills/rs-portal/SKILL.md +51 -0
  92. package/skills/rs-review/SKILL.md +79 -0
  93. package/skills/rs-scope/SKILL.md +67 -0
  94. package/skills/rs-synthesis/SKILL.md +52 -0
  95. package/skills/rstool/SKILL.md +70 -0
  96. package/skills/rstool-helper/GUIDE.md +18 -299
  97. package/skills/rstool-helper/SKILL.md +8 -58
  98. package/skills/{rstool-helper → rstool-runtime}/EXAMPLES.md +16 -12
  99. package/skills/{rstool-helper → rstool-runtime}/REFERENCE.md +7 -5
  100. package/skills/rstool-runtime/SKILL.md +96 -0
  101. package/skills/scripts/brief-check.test.ts +165 -0
  102. package/skills/scripts/brief-check.ts +826 -0
  103. package/skills/scripts/check-brief.ts +94 -0
  104. package/skills/scripts/rstool-skills.mjs +119 -0
  105. package/skills/scripts/skill-stubs.test.ts +48 -0
@@ -1,67 +1,17 @@
1
1
  ---
2
2
  name: rstool-helper
3
3
  description: >-
4
- ЯРЭ и концептуальные схемы через rstool: концептуализация, ревью/оценка КС,
5
- правки и диагностики формул, объяснение конструкций ЯРЭ, проверка на КМ (evaluate),
6
- выбор X#/C#/Z, импорт/экспорт Portal (/rsforms, /details).
7
- Читай GUIDE и docs из node_modules.
4
+ Устаревший вход: используй скилл rstool. ЯРЭ и концептуальные схемы через
5
+ rstool, ревью КС, диагностики, Portal.
8
6
  ---
9
7
 
10
- # rstool-helper
8
+ # rstool-helper (устарел)
11
9
 
12
- Тонкий **входной** skill. Полный гайд и документация остаются в пакете — читай через Read tool по путям ниже (от корня проекта).
10
+ Скилл заменён маршрутизатором **`rstool`** и скиллами этапов. Прочитай `skills/rstool/SKILL.md` пакета и следуй ему:
13
11
 
14
- ## Если входной skill ещё не установлен
12
+ - в workspace Portal — `rsconcept/rstool/skills/rstool/SKILL.md`;
13
+ - в npm-проекте — `node_modules/@rsconcept/rstool/skills/rstool/SKILL.md`.
15
14
 
16
- Пользователь выполнил `npm install @rsconcept/rstool`, но не зарегистрировал agent skill в проекте. **Выполни процедуру установки** из:
15
+ Чтобы заменить эту заглушку в проекте, выполни `node_modules/@rsconcept/rstool/skills/INSTALL.md`, затем удали папку `rstool-helper/` из каталога скиллов проекта.
17
16
 
18
- `node_modules/@rsconcept/rstool/skills/INSTALL.md`
19
-
20
- Затем продолжай с каноническими файлами ниже.
21
-
22
- ## Канонические файлы
23
-
24
- Префикс путей: `node_modules/@rsconcept/rstool/`.
25
-
26
- | Что | Путь |
27
- | :-------------------------------------------------- | :---------------------------------- |
28
- | **Начни здесь** — матрица задач, воркфлоу, чеклисты | `skills/rstool-helper/GUIDE.md` |
29
- | API, stdio, MCP, контракт | `skills/rstool-helper/REFERENCE.md` |
30
- | Примеры, антипаттерны | `skills/rstool-helper/EXAMPLES.md` |
31
- | Язык и предметная область | `docs/*.md` |
32
- | Установка skill | `skills/INSTALL.md` |
33
-
34
- ## Задача → что читать
35
-
36
- Не читай все `docs/` подряд. Открой **GUIDE.md** (раздел «Задача → чтение»), затем только нужные файлы:
37
-
38
- | Задача | Минимум |
39
- | :-------------------------------- | :----------------------------------------------------------------------------- |
40
- | Собрать / развить КС из текста | GUIDE: концептуализация; `docs/CONCEPTUAL-SCHEMA.md`; `docs/BASE-SELECTION.md` |
41
- | Оценить / отревьюить готовую КС | GUIDE: ревью; чеклист ревью; `docs/CONCEPTUAL-SCHEMA.md` |
42
- | Починить формулу / диагностики | GUIDE: цикл диагностик; `docs/DIAGNOSTICS.md` |
43
- | Написать формулу / синтаксис | `docs/SYNTAX.md` |
44
- | Объяснить формулу / конструкцию | `docs/CONSTRUCTIONS.md` |
45
- | Импорт / правка по ссылке Portal | GUIDE: Portal; `docs/PORTAL-API.md` |
46
- | Проверить смысл на данных | GUIDE: КМ; `docs/MODEL-TESTING.md` |
47
- | Типизация / вызов API | `docs/TYPIFICATION.md` / `REFERENCE.md` |
48
-
49
- Перед работой всегда открой **GUIDE.md**; остальное — по строке таблицы.
50
-
51
- ## Не правь пакет rstool без запроса
52
-
53
- Разовые скрипты и JSON для Portal — вне дерева пакета (каталог задачи, `.tmp/`, путь пользователя). См. **«Границы правок»** в GUIDE.md.
54
-
55
- ## Язык ответа пользователю
56
-
57
- В тексте для пользователя используй термины предметной области («формальное определение», «конституента», «диагностики»), а не английские имена полей и методов API (`definitionFormal`, `applySchemaPatch`). Идентификаторы API — только в коде, patch-ах и JSON. Словарь API → текст: раздел «Язык ответа» в GUIDE.md. Термины КС (**неопределяемые понятия**, **базисное множество**, ядро) — только из `docs/DOMAIN.md`, раздел **«Термины: не путать»**. Не сокращай «базисное множество» до «базис» / «базисы».
58
-
59
- ## Portal (приложение)
60
-
61
- REST API и curl — `node_modules/@rsconcept/rstool/docs/PORTAL-API.md`.
62
-
63
- ## Кратко
64
-
65
- - Пакет: `@rsconcept/rstool`; обёртка: `npx rstool-wrapper`
66
- - MCP: `@rsconcept/rstool-mcp` (имена tools — `snake_case`, см. REFERENCE)
67
- - `@rsconcept/domain` устанавливается как зависимость (анализатор и коды ошибок)
17
+ Заглушка будет удалена в следующем минорном релизе.
@@ -1,19 +1,21 @@
1
1
  # ЯРЭ и rstool — примеры
2
2
 
3
- Короткие фрагменты для агентов. Воркфлоу — [GUIDE.md](GUIDE.md). Контракт — [REFERENCE.md](REFERENCE.md).
3
+ Короткие фрагменты для агентов. Запуск и правила — [SKILL.md](SKILL.md); этапы работы — [../rstool/SKILL.md](../rstool/SKILL.md). Контракт — [REFERENCE.md](REFERENCE.md).
4
4
 
5
5
  ## Индекс runnable `examples/`
6
6
 
7
7
  Полные сценарии пакета:
8
8
 
9
- | Тема | Паттерн | Смотри |
10
- | ----------------------------------------------------- | ------------------------------------ | ------------------------------------------------- |
11
- | [`sample/`](../../examples/sample/) | Минимальная КС + КМ | `X1`, `C1`, `S1`, `D1`, `A1` |
12
- | [`kinship/`](../../examples/kinship/) | Предметная схема, модель, CLI | отношения на `X1`, правки интерпретации |
13
- | [`chocolate-nim/`](../../examples/chocolate-nim/) | Математика на `Z` без `X#` | [BASE-SELECTION.md](../../docs/BASE-SELECTION.md) |
14
- | [`movd/`](../../examples/movd/) | Сложные `S#`, мультипроекции, `Fi` | фильтры и проекции |
15
- | [`expression-bank/`](../../examples/expression-bank/) | Шаблоны на радикалах `R#` | [SYNTAX.md](../../docs/SYNTAX.md) «Радикалы» |
16
- | [`template-apply/`](../../examples/template-apply/) | Подстановка `R#` → предметные домены | применение шаблонов |
9
+ | Тема | Паттерн | Смотри |
10
+ | ----------------------------------------------------------------- | ------------------------------------ | ------------------------------------------------- |
11
+ | [`sample/`](../../examples/sample/) | Минимальная КС + КМ | `X1`, `C1`, `S1`, `D1`, `A1` |
12
+ | [`kinship/`](../../examples/kinship/) | Предметная схема, модель, CLI | отношения на `X1`, правки интерпретации |
13
+ | [`chocolate-nim/`](../../examples/chocolate-nim/) | Математика на `Z` без `X#` | [BASE-SELECTION.md](../../docs/BASE-SELECTION.md) |
14
+ | [`movd/`](../../examples/movd/) | Сложные `S#`, мультипроекции, `Fi` | фильтры и проекции |
15
+ | [`expression-bank/`](../../examples/expression-bank/) | Шаблоны на радикалах `R#` | [SYNTAX.md](../../docs/SYNTAX.md) «Радикалы» |
16
+ | [`template-apply/`](../../examples/template-apply/) | Подстановка `R#` → предметные домены | применение шаблонов |
17
+ | [`subordination/`](../../examples/subordination/) | Метод по этапам, бриф, антипримеры | [METHOD.md](../../docs/METHOD.md) |
18
+ | [`kinship-subordination/`](../../examples/kinship-subordination/) | Синтез микротеорий | [rs-synthesis](../rs-synthesis/SKILL.md) |
17
19
 
18
20
  Запуск и структура папок — [examples/README.md](../../examples/README.md).
19
21
 
@@ -152,6 +154,7 @@ tool.applySchemaPatch({
152
154
  | `arithmeticNotSupported` / `orderingNotSupported` | `ξ+1` или `α<β` при `ξ∈X1` | `Z` или `C#` ([BASE-SELECTION.md](../../docs/BASE-SELECTION.md)) |
153
155
  | `globalFuncParenCall` | `F1(ξ)` | `F1[ξ]` |
154
156
  | `globalFuncWithoutArgs` | голое `F1` в формуле | `F1[…]` |
157
+ | `globalDeleted` | `X1∪DEL` — ссылка на удаленную конституенту | подставь действующее обозначение |
155
158
  | `radicalUsage` | `R1` в теле формулы или как конституента | `R#` только в `[…]` у `F#`/`P#` |
156
159
  | `invalidPropertyUsage` | `∀σ∈ℬ(S1)\{∅} ¬P1[σ]` — квантор по булеану | вычислимая форма через достижимость: `∀α∈X1 α∉F4[α]` |
157
160
  | `schemaMissingConvention` | `X1` без конвенции | добавь предметную конвенцию |
@@ -159,6 +162,7 @@ tool.applySchemaPatch({
159
162
  | `schemaDependencyCycle` | круг в определениях (`F3 → P1 → F3`) | разорви цикл: убери взаимные ссылки |
160
163
  | `localOutOfScopeParentheses` | `∀a∈S P(a) & Q(a)` | `∀a∈S (P(a) & Q(a))` |
161
164
  | `invalidFilterSyntax` | кривой `Fi` | `Fi1[{ξ}](S1)` / `Fi1,2[D1,D2](S1)` |
165
+ | стиль: `card(S) > 0` / `card(S) = 0` | проверка (не)пустоты через мощность | `S ≠ ∅` / `S = ∅` / `A ∩ B ≠ ∅` |
162
166
 
163
167
  ```ts
164
168
  const analysis = tool.analyzeExpression({
@@ -270,14 +274,14 @@ const restored = tool.importData(payload, 'session');
270
274
  const schemaJson = tool.exportPortal({ kind: 'schema' });
271
275
  const modelObj = tool.exportPortal({ kind: 'model', format: 'object' });
272
276
 
273
- // Portal GET /api/rsforms/:id/details → строка или объект
277
+ // Portal JSON: GET /api/agents/rsforms/:id/details (Bearer key), same shape as public /details
274
278
  const session = tool.importData(portalDetailsJsonString); // kind auto
275
279
  tool.listDiagnostics();
276
280
  // правки…
277
281
  const forPortal = tool.exportPortal({ kind: 'schema' });
278
282
  ```
279
283
 
280
- Не передавай `/details` с `kind: 'session'`. REST и curl — [PORTAL-API.md](../../docs/PORTAL-API.md).
284
+ Не передавай `/details` с `kind: 'session'`. REST и curl — [PORTAL-READ.md](../../docs/PORTAL-READ.md).
281
285
 
282
286
  ## Встраивание схемы (синтез)
283
287
 
@@ -306,7 +310,7 @@ tool.synthesize({
306
310
 
307
311
  ## Образец текста ревью (не код)
308
312
 
309
- После [воркфлоу ревью](GUIDE.md#ревью--оценка-готовой-кс) ответ может выглядеть так:
313
+ После [ревью](../rs-review/SKILL.md) ответ может выглядеть так:
310
314
 
311
315
  > **Вердикт:** схема покрывает роли и отношение подчинения; главный риск — вычисляемая «степень» задана графиком пар вместо терм-функции.
312
316
  >
@@ -1,6 +1,6 @@
1
1
  # ЯРЭ и rstool — справочник
2
2
 
3
- Контракт library / stdio / MCP для агентов. Воркфлоу — [GUIDE.md](GUIDE.md). Примеры — [EXAMPLES.md](EXAMPLES.md). Язык — `docs/*.md`.
3
+ Контракт library / stdio / MCP для агентов. Запуск и правила — [SKILL.md](SKILL.md); этапы работы — [../rstool/SKILL.md](../rstool/SKILL.md). Примеры — [EXAMPLES.md](EXAMPLES.md). Язык — `docs/*.md`.
4
4
 
5
5
  ## Контракт rstool
6
6
 
@@ -116,7 +116,7 @@ tool.listDiagnostics({ kind: 'schema', constituentId: 3, severity: 'error' });
116
116
 
117
117
  Фильтры: `kind?: 'expression' | 'schema' | 'model'`, `constituentId?`, `severity?: 'error' | 'warning'`. В stdio / MCP те же поля передаются **плоско** в `params` (`{ "kind": "schema", "severity": "warning" }`); stdio дополнительно принимает устаревший вложенный `filters`.
118
118
 
119
- `severity` отражает правило инструмента, а не вес для ревью: `schemaMissingConvention` / `schemaMissingTerm` приходят как `error`. Как ранжировать в отчёте — [GUIDE.md](GUIDE.md), «Ревью / оценка готовой КС».
119
+ `severity` отражает правило инструмента, а не вес для ревью: `schemaMissingConvention` / `schemaMissingTerm` приходят как `error`. Как ранжировать в отчёте — [rs-review](../rs-review/SKILL.md), «Ранжирование находок».
120
120
 
121
121
  Элемент диагностики (агентский вид): `kind`, `code`, `name`, `severity`, `alias?`, `expression`, `from`, `to`, `params?`, `stack?` (цепочка вызовов при ошибке внутри `F#`/`P#`). Ключ для поиска исправления — `name` ([DIAGNOSTICS.md](../../docs/DIAGNOSTICS.md)).
122
122
 
@@ -223,7 +223,7 @@ tool.synthesize({
223
223
 
224
224
  ### `importData(payload, kind?)`
225
225
 
226
- `kind`: `'auto'` (default), `'session'`, `'portal-details'` (`GET /api/rsforms/:id/details`), `'portal-schema'` (Portal Load from JSON). После импорта новая сессия становится текущей. Возвращает `SessionHandle`.
226
+ `kind`: `'auto'` (default), `'session'`, `'portal-details'` (JSON of `GET /api/agents/rsforms/:id/details` or public `GET /api/rsforms/:id/details`), `'portal-schema'` (Portal Load from JSON). После импорта новая сессия становится текущей. Возвращает `SessionHandle`.
227
227
 
228
228
  Portal JSON из `/details` **не** является `exportSession` — не передавай его с `kind: 'session'`.
229
229
 
@@ -269,9 +269,11 @@ JSON-строка сессии для последующего `importData(...,
269
269
  | Проектирование, `F#` vs пары, ревью | [CONCEPTUAL-SCHEMA.md](../../docs/CONCEPTUAL-SCHEMA.md) |
270
270
  | Поля и валидация конституенты | [CONSTITUENTA.md](../../docs/CONSTITUENTA.md) |
271
271
  | Формы значений КМ, тесты | [MODEL-TESTING.md](../../docs/MODEL-TESTING.md) |
272
- | Ссылка Portal, REST, curl | [PORTAL-API.md](../../docs/PORTAL-API.md) |
272
+ | Ссылка Portal, REST, curl | [PORTAL-READ.md](../../docs/PORTAL-READ.md) |
273
273
  | Термины, статусы, «не путать» | [DOMAIN.md](../../docs/DOMAIN.md) |
274
- | Воркфлоу агента | [GUIDE.md](GUIDE.md) |
274
+ | Бриф, сценарии, `check-brief` | [BRIEF.md](../../docs/BRIEF.md) |
275
+ | Метод: этапы и гейты | [METHOD.md](../../docs/METHOD.md) |
276
+ | Этапы работы, маршрут | [../rstool/SKILL.md](../rstool/SKILL.md) |
275
277
  | Сниппеты и антипаттерны | [EXAMPLES.md](EXAMPLES.md) |
276
278
 
277
279
  Исходники кодов ошибок ЯРЭ: `@rsconcept/domain` (`RSErrorCode`, `error.ts`). Не дублируй грамматику в skill — правь domain и при необходимости этот help map.
@@ -0,0 +1,96 @@
1
+ ---
2
+ name: rstool-runtime
3
+ description: >-
4
+ Как вызывать rstool: библиотека RSToolAgent, stdio-обёртка, MCP. Быстрый
5
+ контракт, запуск скриптов вне пакета, сохранение сессий, кодировки Windows,
6
+ словарь «API → текст для пользователя».
7
+ ---
8
+
9
+ # rstool · запуск и контракт
10
+
11
+ Пути — от `<rstool>`. Полный контракт — [REFERENCE.md](REFERENCE.md); сниппеты и антипаттерны — [EXAMPLES.md](EXAMPLES.md).
12
+
13
+ ## Быстрый контракт
14
+
15
+ - Библиотека: `@rsconcept/rstool`, класс `RSToolAgent`. Анализатор — `@rsconcept/domain`.
16
+ - Правка схемы — только `applySchemaPatch({ items, mode?, commitMessage? })`. `id` и `cstType` выводятся из префикса имени (`X/C/S/D/F/P/A/T/N`); пачка упорядочивается сама. `mode: 'atomic'` (по умолчанию) откатывает всё при первой ошибке; `'best_effort'` применяет корректное — после него `failed` должен стать пустым.
17
+ - Черновик формулы — `analyzeExpression({ expression, cstType })` без сохранения.
18
+ - Диагностики — `listDiagnostics({ kind?, severity? })`; `analysisSuccess: true` в summary не означает их отсутствия.
19
+ - Состояние — `getSessionState()` (summary) или `getSessionState('full')`.
20
+ - Модель — `await setModelValues(...)`, `evaluate`, `recalculateModel`; `status` — число (`EvalStatus`). Для проверки смысла по брифу удобнее сценарии и `check-brief` (`docs/BRIEF.md`).
21
+ - Синтез (встраивание) — `synthesize({ sourceSessionId, substitutions })`; имена источника перенумеровываются (`aliasMapping` в ответе).
22
+ - Импорт / экспорт — `importData(payload, kind?)` (`auto` различает сессию и JSON Portal), `exportSession()`, `exportPortal({ kind: 'schema' })`.
23
+ - Stdio (`npx rstool-wrapper`) и MCP (`@rsconcept/rstool-mcp`, имена в `snake_case`): **плоские** `params` — поля метода и `sessionId` на одном уровне.
24
+
25
+ ## Запуск скрипта вне пакета
26
+
27
+ Разовые скрипты, сессии, бриф и экспорт — в папке задачи, **не** в `<rstool>`.
28
+
29
+ **В workspace Portal** (после `pnpm install` и сборки `@rsconcept/domain`):
30
+
31
+ ```bash
32
+ pnpm --filter @rsconcept/rstool exec tsx <abs>/task/build.mts
33
+ ```
34
+
35
+ - Импорт по абсолютному `file://` URL: `import { RSToolAgent } from 'file:///<workspace>/rsconcept/rstool/src/index.ts'`. Обычный `'@rsconcept/rstool'` из файла вне пакета не резолвится; на Windows путь без `file://` падает (`ERR_UNSUPPORTED_ESM_URL_SCHEME`).
36
+ - Расширение **`.mts`**: `.ts` вне пакета считается CommonJS, а `@rsconcept/*` — только ESM.
37
+ - Helpers domain — тем же способом: `file:///…/rsconcept/domain/src/index.ts` (`TUPLE_ID`, `EvalStatus`), `…/domain/src/rslang/labels.ts` (`labelType`).
38
+
39
+ **В npm-проекте:** `npx tsx task/build.mts` с обычным `import { RSToolAgent } from '@rsconcept/rstool'`.
40
+
41
+ Альтернатива без резолвинга — stdio из собранного `dist`: `new RSToolWrapperClient({ command: 'node', args: ['<abs>/rsconcept/rstool/dist/wrapper/stdio-wrapper.js'] })`.
42
+
43
+ ```ts
44
+ import { readFileSync, writeFileSync } from 'node:fs';
45
+ import { RSToolAgent } from 'file:///<workspace>/rsconcept/rstool/src/index.ts';
46
+
47
+ const tool = new RSToolAgent();
48
+ tool.importData(readFileSync('<abs>/task/session.json', 'utf-8'));
49
+ console.log(tool.listDiagnostics());
50
+ writeFileSync('<abs>/task/session.json', tool.exportSession(), 'utf-8');
51
+ ```
52
+
53
+ **Проверка брифа** — `skills/scripts/check-brief.ts` запускается из пакета, не копируется: `pnpm --filter @rsconcept/rstool exec tsx skills/scripts/check-brief.ts --session <abs> --brief <abs>` (npm: `npx tsx node_modules/@rsconcept/rstool/skills/scripts/check-brief.ts …`).
54
+
55
+ ## Сохранение сессий
56
+
57
+ Сессии живут в памяти процесса. Между запусками скрипта сохраняй `exportSession()` в файл и загружай `importData`. `new RSToolAgent({ persistenceDir })` (stdio / MCP: `RSTOOL_PERSISTENCE_DIR`) сохраняет сессии автоматически.
58
+
59
+ ## Windows и кодировки
60
+
61
+ - Консоль часто в cp1251: символы ЯРЭ в выводе ломаются. Пиши результаты в файл UTF-8; в PowerShell — `-Encoding utf8`.
62
+ - JSON — UTF-8 без экранирования Unicode (`ensure_ascii=False` в Python). Логи в `print` — ASCII.
63
+ - В PowerShell вызывай `curl.exe`, а не alias `curl`.
64
+
65
+ ## Язык ответа
66
+
67
+ С пользователем — термины предметной области, не имена API. Идентификаторы уместны только в коде, патчах и JSON.
68
+
69
+ | В API | В тексте ответа |
70
+ | :-------------------------------- | :---------------------------------- |
71
+ | `alias` | имя конституенты |
72
+ | `cstType` | тип конституенты |
73
+ | `definitionFormal` | формальное определение (формула) |
74
+ | `term` | термин |
75
+ | `definitionText` | текстовое определение |
76
+ | `convention` | конвенция |
77
+ | `applySchemaPatch` | правка схемы |
78
+ | `synthesize` | встраивание / синтез схем |
79
+ | `analyzeExpression` | проверка / анализ выражения |
80
+ | `listDiagnostics`, `diagnostics` | диагностики |
81
+ | `setModelValues`, `getModelState` | интерпретация, значения модели |
82
+ | `evaluate`, `recalculateModel` | вычисление, пересчёт модели |
83
+ | `commitStep`, `commitMessage` | фиксация шага (ревизия) |
84
+ | `exportSession` / `exportPortal` | экспорт сессии / экспорт для Portal |
85
+ | `importData` | импорт данных |
86
+ | session, `sessionId` | сессия |
87
+ | brief, `check-brief` | бриф, проверка по брифу |
88
+
89
+ Имена конституент (`X1`, `D3`) и формулы — часть схемы, приводи как есть, лучше с термином. Термины КС — `docs/DOMAIN.md` «Термины: не путать».
90
+
91
+ ## Не делай
92
+
93
+ - Не клади разовые скрипты и снимки в `<rstool>` и `examples/`.
94
+ - Не передавай JSON `/details` Portal с `kind: 'session'`.
95
+ - Не повторяй вызов без изменения ввода.
96
+ - Не задавай значения производным понятиям — только `X#`, `C#`, `S#`.
@@ -0,0 +1,165 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { RSToolAgent } from '../../src';
4
+
5
+ import { type Brief, checkBrief } from './brief-check';
6
+
7
+ function buildSession(overrides: Record<string, { definitionFormal?: string; cstType?: string }> = {}): string {
8
+ const tool = new RSToolAgent();
9
+ tool.createSession({ title: 'Выдачи' });
10
+ const items = [
11
+ { alias: 'X1', term: 'читатели', convention: 'Читатели библиотеки.' },
12
+ { alias: 'X2', term: 'экземпляры', convention: 'Экземпляры книг в фонде.' },
13
+ {
14
+ alias: 'S1',
15
+ term: 'выдачи',
16
+ definitionFormal: 'ℬ(X1×X2×Z)',
17
+ convention: 'Тройка (читатель, экземпляр, срок в днях).'
18
+ },
19
+ { alias: 'D1', term: 'выданные экземпляры', definitionFormal: 'Pr2(S1)' },
20
+ { alias: 'D2', term: 'доступные экземпляры', definitionFormal: 'X2\\D1' },
21
+ { alias: 'F1', term: 'экземпляры читателя', definitionFormal: '[ξ∈X1] Pr2(Fi1[{ξ}](S1))' },
22
+ { alias: 'P1', term: 'должник', definitionFormal: '[ξ∈X1] F1[ξ]≠∅' },
23
+ { alias: 'A1', term: 'экземпляр выдан одному', definitionFormal: 'card(Pr2(S1))=card(S1)' }
24
+ ].map(item => ({ ...item, ...overrides[item.alias] }));
25
+ tool.applySchemaPatch({ items: items as Parameters<RSToolAgent['applySchemaPatch']>[0]['items'] });
26
+ return tool.exportSession();
27
+ }
28
+
29
+ const BRIEF: Brief = {
30
+ version: 1,
31
+ status: 'confirmed',
32
+ approach: 'project',
33
+ object: 'Выдача книг',
34
+ task: 'Проверка выдач',
35
+ expressiveness: [
36
+ { id: 'E1', concept: 'выданный экземпляр', via: 'Pr2 выдач', constituent: 'D1' },
37
+ { id: 'E2', concept: 'доступный экземпляр', via: 'дополнение E1', constituent: 'D2' },
38
+ { id: 'E3', concept: 'экземпляры читателя', via: 'фильтр выдач', constituent: 'F1' }
39
+ ],
40
+ distinctions: [{ id: 'V1', between: ['E1', 'E2'], witness: 'SC1' }],
41
+ invariants: [{ id: 'I1', text: 'Экземпляр не выдан дважды', constituent: 'A1', positive: 'SC1', negative: 'SC2' }],
42
+ decisions: [{ id: 'DC1', topic: 'выдача', choice: 'читатель × экземпляр × срок', rationale: 'срок нужен' }],
43
+ scenarios: [
44
+ {
45
+ id: 'SC1',
46
+ title: 'Обычные выдачи',
47
+ values: {
48
+ X1: ['ann', 'bob'],
49
+ X2: ['e1', 'e2', 'e3'],
50
+ S1: [
51
+ ['ann', 'e1', 3],
52
+ ['bob', 'e2', 5]
53
+ ]
54
+ },
55
+ expect: [
56
+ { of: 'D1', value: ['e1', 'e2'] },
57
+ { of: 'D2', contains: ['e3'], excludes: ['e1'] },
58
+ { of: 'F1', args: ['ann'], value: ['e1'] },
59
+ { of: 'P1', args: ['bob'], holds: true },
60
+ { of: 'A1', holds: true },
61
+ { expr: 'card(D1)', value: 2 }
62
+ ]
63
+ },
64
+ {
65
+ id: 'SC2',
66
+ title: 'Двойная выдача',
67
+ base: 'SC1',
68
+ values: {
69
+ S1: [
70
+ ['ann', 'e1', 3],
71
+ ['bob', 'e1', 4]
72
+ ]
73
+ },
74
+ expect: [{ of: 'A1', holds: false }]
75
+ }
76
+ ]
77
+ };
78
+
79
+ describe('checkBrief', () => {
80
+ it('passes a schema that answers the brief', async () => {
81
+ const { readiness, scenarios } = await checkBrief({ session: buildSession(), brief: BRIEF });
82
+ expect(scenarios.flatMap(item => item.checks.filter(check => !check.passed))).toEqual([]);
83
+ expect(readiness.blockers).toEqual([]);
84
+ expect(readiness.ready).toBe(true);
85
+ expect(readiness.stage).toBe('review');
86
+ expect(readiness.coverage).toEqual({ expressiveness: '3/3', invariants: '1/1', distinctions: '1/1' });
87
+ });
88
+
89
+ it('reports a failed expectation with labels', async () => {
90
+ const session = buildSession({ D2: { definitionFormal: 'X2' } });
91
+ const { readiness, scenarios } = await checkBrief({ session, brief: BRIEF });
92
+ const failed = scenarios[0].checks.find(check => !check.passed);
93
+ expect(failed?.target).toBe('D2');
94
+ expect(failed?.actual).toBe('["e1","e2","e3"]');
95
+ expect(readiness.stage).toBe('interpret');
96
+ });
97
+
98
+ it('reports uncovered requirements and missing reasoning', async () => {
99
+ const brief: Brief = {
100
+ ...BRIEF,
101
+ status: 'draft',
102
+ expressiveness: [...BRIEF.expressiveness, { id: 'E4', concept: 'просроченная выдача', constituent: null }]
103
+ };
104
+ const { readiness } = await checkBrief({ session: buildSession(), brief });
105
+ expect(readiness.stage).toBe('scope');
106
+ expect(readiness.coverage.expressiveness).toBe('3/4');
107
+ expect(readiness.blockers.some(item => item.startsWith('E4'))).toBe(true);
108
+ });
109
+
110
+ it('detects a collapsed distinction', async () => {
111
+ const session = buildSession({ D2: { definitionFormal: 'Pr2(S1)' } });
112
+ const { readiness } = await checkBrief({
113
+ session,
114
+ brief: { ...BRIEF, approach: 'research', scenarios: [BRIEF.scenarios![1]] }
115
+ });
116
+ expect(readiness.blockers.some(item => item.startsWith('V1'))).toBe(true);
117
+ });
118
+
119
+ it('detects weakening against the base version', async () => {
120
+ const base = buildSession();
121
+ const session = buildSession({
122
+ A1: { definitionFormal: 'S1=S1' },
123
+ D1: { cstType: 'structure', definitionFormal: 'ℬ(X2)' }
124
+ });
125
+ const { readiness } = await checkBrief({ session, base, brief: { ...BRIEF, scenarios: [] } });
126
+ expect(readiness.blockers.some(item => item.startsWith('A1: формула стала тривиальной'))).toBe(true);
127
+ expect(readiness.blockers.some(item => item.startsWith('D1: производное понятие стало неопределяемым'))).toBe(true);
128
+ });
129
+
130
+ it('reports orphans for project schemas', async () => {
131
+ const tool = new RSToolAgent();
132
+ tool.importData(buildSession(), 'session');
133
+ tool.applySchemaPatch({ items: [{ alias: 'D3', term: 'лишнее', definitionFormal: 'X1×X2' }] });
134
+ const { readiness } = await checkBrief({ session: tool.exportSession(), brief: BRIEF });
135
+ expect(readiness.blockers.some(item => item.includes('D3'))).toBe(true);
136
+ });
137
+
138
+ it('flags an axiom that is false on an admissible scenario', async () => {
139
+ const tool = new RSToolAgent();
140
+ tool.importData(buildSession(), 'session');
141
+ tool.applySchemaPatch({ items: [{ alias: 'A2', term: 'один читатель', definitionFormal: 'card(Pr1(S1))≤1' }] });
142
+ const { readiness, scenarios } = await checkBrief({ session: tool.exportSession(), brief: BRIEF });
143
+ expect(scenarios[0].checks.some(check => check.target === 'A2 (допустимый сценарий)')).toBe(true);
144
+ expect(scenarios[1].checks.some(check => check.target.startsWith('A2'))).toBe(false);
145
+ expect(readiness.ready).toBe(false);
146
+ });
147
+
148
+ it('compares functions by their graphs in distinctions', async () => {
149
+ const tool = new RSToolAgent();
150
+ tool.importData(buildSession(), 'session');
151
+ tool.applySchemaPatch({ items: [{ alias: 'F2', term: 'то же', definitionFormal: '[ξ∈X1] Pr2(Fi1[{ξ}](S1))' }] });
152
+ const brief: Brief = { ...BRIEF, approach: 'research', distinctions: [{ id: 'V2', between: ['F1', 'F2'] }] };
153
+ const { readiness } = await checkBrief({ session: tool.exportSession(), brief });
154
+ expect(readiness.blockers.some(item => item.startsWith('V2: F1 и F2 совпадают'))).toBe(true);
155
+ });
156
+
157
+ it('warns when conventions cite brief decisions', async () => {
158
+ const tool = new RSToolAgent();
159
+ tool.importData(buildSession(), 'session');
160
+ tool.applySchemaPatch({ items: [{ alias: 'X2', convention: 'Экземпляры книг (решение DC1).' }] });
161
+ const { readiness } = await checkBrief({ session: tool.exportSession(), brief: BRIEF });
162
+ expect(readiness.warnings.some(item => item.includes('(DC#): X2'))).toBe(true);
163
+ expect(readiness.warnings.some(item => item.startsWith('Описание схемы пусто'))).toBe(true);
164
+ });
165
+ });