@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.
- package/README.md +3 -3
- package/dist/mappers/model-adapter.d.ts +1 -2
- package/dist/mappers/schema-adapter.d.ts +1 -2
- package/dist/mappers/types.d.ts +4 -5
- package/dist/models/rstool-agent.js +1 -2
- package/dist/session/session-store.d.ts +3 -3
- package/dist/session/session-store.js +1 -2
- package/dist/wrapper/client.d.ts +3 -4
- package/docs/BRIEF.md +93 -0
- package/docs/CONCEPTUAL-SCHEMA.md +16 -1
- package/docs/CONSTRUCTIONS.md +14 -2
- package/docs/DIAGNOSTICS.md +3 -2
- package/docs/DOMAIN.md +12 -0
- package/docs/METHOD.md +208 -0
- package/docs/PORTAL-API.md +38 -285
- package/docs/PORTAL-MODELS.md +24 -0
- package/docs/PORTAL-OSS.md +56 -0
- package/docs/PORTAL-PUBLISH.md +39 -0
- package/docs/PORTAL-READ.md +301 -0
- package/docs/README.md +7 -4
- package/docs/REQUIREMENTS.md +61 -0
- package/docs/SYNTAX.md +4 -3
- package/docs/TYPIFICATION.md +1 -1
- package/docs/brief.schema.json +173 -0
- package/examples/README.md +16 -2
- package/examples/access-control/NOTES.md +23 -0
- package/examples/access-control/anti/collapsed.json +439 -0
- package/examples/access-control/anti/weakened.json +439 -0
- package/examples/access-control/brief-v1.json +231 -0
- package/examples/access-control/brief.json +310 -0
- package/examples/access-control/build-rsform.ts +151 -0
- package/examples/access-control/requirements-v1.md +9 -0
- package/examples/access-control/requirements-v2.md +4 -0
- package/examples/access-control/rsform-session-v1.json +439 -0
- package/examples/access-control/rsform-session.json +523 -0
- package/examples/audit-diagnostics.ts +9 -1
- package/examples/briefs.test.ts +126 -0
- package/examples/clinic-booking/NOTES.md +24 -0
- package/examples/clinic-booking/anti/collapsed.json +615 -0
- package/examples/clinic-booking/anti/species-as-genus.json +568 -0
- package/examples/clinic-booking/brief-v1.json +332 -0
- package/examples/clinic-booking/brief.json +405 -0
- package/examples/clinic-booking/build-rsform.ts +174 -0
- package/examples/clinic-booking/requirements-v1.md +9 -0
- package/examples/clinic-booking/requirements-v2.md +4 -0
- package/examples/clinic-booking/rsform-session-v1.json +615 -0
- package/examples/clinic-booking/rsform-session.json +700 -0
- package/examples/diagnostics-utils.ts +26 -0
- package/examples/kinship/brief.json +337 -0
- package/examples/kinship/build-rsform.ts +7 -4
- package/examples/kinship/rsform-session.json +20 -63
- package/examples/kinship/rsmodel-session.json +14 -14
- package/examples/kinship-subordination/NOTES.md +49 -0
- package/examples/kinship-subordination/brief.json +161 -0
- package/examples/kinship-subordination/build-rsform.ts +100 -0
- package/examples/kinship-subordination/rsform-session.json +795 -0
- package/examples/library-loans/NOTES.md +46 -0
- package/examples/library-loans/anti/collapsed.json +481 -0
- package/examples/library-loans/anti/species-as-genus.json +334 -0
- package/examples/library-loans/anti/uncovered.json +406 -0
- package/examples/library-loans/anti/weakened.json +464 -0
- package/examples/library-loans/brief-v1.json +340 -0
- package/examples/library-loans/brief.json +502 -0
- package/examples/library-loans/build-rsform.ts +239 -0
- package/examples/library-loans/requirements-v1.md +11 -0
- package/examples/library-loans/requirements-v2.md +5 -0
- package/examples/library-loans/rsform-session-v1.json +481 -0
- package/examples/library-loans/rsform-session.json +652 -0
- package/examples/library-loans/source-markup.md +18 -0
- package/examples/movd/brief.json +220 -0
- package/examples/movd/build-rsform.ts +5 -2
- package/examples/movd/rsform-session.json +14 -46
- package/examples/subordination/NOTES.md +59 -0
- package/examples/subordination/anti/collapsed.json +556 -0
- package/examples/subordination/anti/single-relation.json +125 -0
- package/examples/subordination/anti/transitive.json +573 -0
- package/examples/subordination/anti/weakened.json +539 -0
- package/examples/subordination/brief.json +386 -0
- package/examples/subordination/build-rsform.ts +63 -0
- package/examples/subordination/constants.ts +115 -0
- package/examples/subordination/rsform-session.json +556 -0
- package/examples/subordination/source-markup.md +19 -0
- package/examples/subordination/source.md +40 -0
- package/package.json +18 -10
- package/skills/INSTALL.md +28 -29
- package/skills/README.md +25 -10
- package/skills/rs-core/SKILL.md +56 -0
- package/skills/rs-explain/SKILL.md +28 -0
- package/skills/rs-explicate/SKILL.md +71 -0
- package/skills/rs-interpret/SKILL.md +67 -0
- package/skills/rs-portal/SKILL.md +51 -0
- package/skills/rs-review/SKILL.md +79 -0
- package/skills/rs-scope/SKILL.md +67 -0
- package/skills/rs-synthesis/SKILL.md +52 -0
- package/skills/rstool/SKILL.md +70 -0
- package/skills/rstool-helper/GUIDE.md +18 -299
- package/skills/rstool-helper/SKILL.md +8 -58
- package/skills/{rstool-helper → rstool-runtime}/EXAMPLES.md +16 -12
- package/skills/{rstool-helper → rstool-runtime}/REFERENCE.md +7 -5
- package/skills/rstool-runtime/SKILL.md +96 -0
- package/skills/scripts/brief-check.test.ts +165 -0
- package/skills/scripts/brief-check.ts +826 -0
- package/skills/scripts/check-brief.ts +94 -0
- package/skills/scripts/rstool-skills.mjs +119 -0
- package/skills/scripts/skill-stubs.test.ts +48 -0
|
@@ -1,67 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: rstool-helper
|
|
3
3
|
description: >-
|
|
4
|
-
ЯРЭ и концептуальные схемы через
|
|
5
|
-
|
|
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
|
-
|
|
10
|
+
Скилл заменён маршрутизатором **`rstool`** и скиллами этапов. Прочитай `skills/rstool/SKILL.md` пакета и следуй ему:
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
- в workspace Portal — `rsconcept/rstool/skills/rstool/SKILL.md`;
|
|
13
|
+
- в npm-проекте — `node_modules/@rsconcept/rstool/skills/rstool/SKILL.md`.
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
Чтобы заменить эту заглушку в проекте, выполни `node_modules/@rsconcept/rstool/skills/INSTALL.md`, затем удали папку `rstool-helper/` из каталога скиллов проекта.
|
|
17
16
|
|
|
18
|
-
|
|
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
|
-
Короткие фрагменты для агентов.
|
|
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/)
|
|
12
|
-
| [`kinship/`](../../examples/kinship/)
|
|
13
|
-
| [`chocolate-nim/`](../../examples/chocolate-nim/)
|
|
14
|
-
| [`movd/`](../../examples/movd/)
|
|
15
|
-
| [`expression-bank/`](../../examples/expression-bank/)
|
|
16
|
-
| [`template-apply/`](../../examples/template-apply/)
|
|
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-
|
|
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
|
-
После [
|
|
313
|
+
После [ревью](../rs-review/SKILL.md) ответ может выглядеть так:
|
|
310
314
|
|
|
311
315
|
> **Вердикт:** схема покрывает роли и отношение подчинения; главный риск — вычисляемая «степень» задана графиком пар вместо терм-функции.
|
|
312
316
|
>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ЯРЭ и rstool — справочник
|
|
2
2
|
|
|
3
|
-
Контракт library / stdio / MCP для агентов.
|
|
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`. Как ранжировать в отчёте — [
|
|
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-
|
|
272
|
+
| Ссылка Portal, REST, curl | [PORTAL-READ.md](../../docs/PORTAL-READ.md) |
|
|
273
273
|
| Термины, статусы, «не путать» | [DOMAIN.md](../../docs/DOMAIN.md) |
|
|
274
|
-
|
|
|
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
|
+
});
|