@rsconcept/rstool 1.7.1 → 1.9.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 (38) hide show
  1. package/README.md +5 -5
  2. package/dist/index.js +1 -1
  3. package/dist/mappers/model-adapter.d.ts +5 -0
  4. package/dist/mappers/model-adapter.js +28 -3
  5. package/dist/mappers/model-adapter.js.map +1 -1
  6. package/dist/mappers/schema-adapter.js +1 -1
  7. package/dist/models/index.js +1 -1
  8. package/dist/models/rstool-agent.js +1 -1
  9. package/dist/{models-DG2uTaV_.js → models-D06g8LId.js} +6 -5
  10. package/dist/{models-DG2uTaV_.js.map → models-D06g8LId.js.map} +1 -1
  11. package/dist/{rsform-builder-DKwZfJvN.js → rsform-builder-BlXEe5Ow.js} +2 -2
  12. package/dist/{rsform-builder-DKwZfJvN.js.map → rsform-builder-BlXEe5Ow.js.map} +1 -1
  13. package/dist/session/session-store.js +1 -1
  14. package/dist/wrapper/client.d.ts +12 -5
  15. package/dist/wrapper/client.js +79 -12
  16. package/dist/wrapper/client.js.map +1 -1
  17. package/dist/wrapper/stdio-wrapper.d.ts +1 -1
  18. package/dist/wrapper/stdio-wrapper.js +18 -10
  19. package/dist/wrapper/stdio-wrapper.js.map +1 -1
  20. package/docs/CONCEPTUAL-SCHEMA.md +1 -1
  21. package/docs/CONSTRUCTIONS.md +372 -0
  22. package/docs/DIAGNOSTICS.md +6 -6
  23. package/docs/MODEL-TESTING.md +48 -0
  24. package/docs/README.md +1 -0
  25. package/docs/SYNTAX.md +1 -1
  26. package/docs/TYPIFICATION.md +11 -2
  27. package/package.json +20 -19
  28. package/skills/README.md +1 -1
  29. package/skills/rstool-helper/EXAMPLES.md +24 -0
  30. package/skills/rstool-helper/GUIDE.md +46 -19
  31. package/skills/rstool-helper/REFERENCE.md +22 -3
  32. package/skills/rstool-helper/SKILL.md +6 -3
  33. package/src/mappers/model-adapter.ts +34 -1
  34. package/src/models/rstool-agent.test.ts +95 -0
  35. package/src/wrapper/client.test.ts +43 -4
  36. package/src/wrapper/client.ts +95 -16
  37. package/src/wrapper/stdio-handler.test.ts +43 -0
  38. package/src/wrapper/stdio-handler.ts +19 -5
@@ -0,0 +1,372 @@
1
+ # Объяснение конструкций ЯРЭ
2
+
3
+ Читай, когда нужно **объяснить человеку** формулу или конструкцию языка. Написание и починка формул — [SYNTAX.md](SYNTAX.md); диагностики — [DIAGNOSTICS.md](DIAGNOSTICS.md); ступени как объект анализа — [TYPIFICATION.md](TYPIFICATION.md).
4
+
5
+ Не сыпь таблицы операторов из `SYNTAX.md` в чат. Этот файл — словарь фраз и сценарий разбора. Механика генераторов и приоритеты операторов при написании формулы — [SYNTAX.md](SYNTAX.md).
6
+
7
+ ## Карточка
8
+
9
+ У каждой конструкции:
10
+
11
+ | Поле | Зачем |
12
+ | :-------------- | :------------------------------------------------------------------------- |
13
+ | Запись | как выглядит в формуле |
14
+ | Что считается | одно предложение, значение или истинность |
15
+ | Ступень | результат |
16
+ | Не сосед | граница со смежной конструкцией |
17
+ | Как сказать | сначала обычная речь, сразу канонический термин |
18
+ | Пример | один посчитанный |
19
+ | Антипаттерн | типичная путаница |
20
+ | Справка | топик Portal; в чат — только по правилам [ниже](#ссылка-на-справку-portal) |
21
+
22
+ В разборе формулы термин называй в том шаге, где конструкция появляется, не на каждый вложенный узел.
23
+
24
+ ## Как объяснять формулу
25
+
26
+ Сценарий для конкретной конституенты. Карточки — словарь фраз, не оглавление ответа.
27
+
28
+ 1. Роль конституенты и термин.
29
+ 2. Формула как есть.
30
+ 3. Это ТМВ или ЛВ (преамбула ниже).
31
+ 4. Снаружи внутрь: что получается в целом, затем цепочка только теми карточками, которые есть в формуле.
32
+ 5. Ступень результата и на какие понятия опирается.
33
+ 6. Вычисление на данных (`evaluate`, маленькая КМ) — только если спросили «что получится на этих данных». Иначе не придумывай интерпретацию.
34
+
35
+ Не вставляй ссылку на справку Portal на каждый оператор в этом разборе.
36
+
37
+ ## ТМВ и ЛВ
38
+
39
+ Формула либо **считает значение**, либо **утверждает истинность**. С этого начинается любой разбор.
40
+
41
+ | Класс | Что возвращает | Где живёт в схеме |
42
+ | :---- | :------------- | :---------------- |
43
+ | Теоретико-множественное выражение (ТМВ) | элемент ступени: объект, кортеж, множество, целое | типизация `S#`, определение `D#` / `F#`, тело терм-функции |
44
+ | Логическое выражение (ЛВ) | истина или ложь | `A#`, `T#`, тело `P#`, условие в `D{}` / `I{}` / `R{}` / кванторе |
45
+
46
+ Не говори «формула возвращает TRUE/FALSE» про ТМВ и не называй множество «проверкой». `TRUE` и `FALSE` в экспликации КС не используют.
47
+
48
+ Каноническая рамка: «это теоретико-множественное выражение: считается множество / элемент» или «это логическое выражение: утверждается, что …».
49
+
50
+ Справка: [ЯРЭ](https://portal.acconcept.ru/manuals?topic=rslang). Типизация ступеней: [типизация](https://portal.acconcept.ru/manuals?topic=rslang-typification).
51
+
52
+ ## Малая проекция (`pr`)
53
+
54
+ **Запись.** `prk(кортеж)`. Мультииндекс: `pr1,3((a, b, c, d))`.
55
+
56
+ **Что считается.** Выбранная компонента **одного** кортежа (при мультииндексе — кортеж из выбранных компонент).
57
+
58
+ **Ступень.** Ступень k-й компоненты; при мультииндексе — кортеж этих ступеней.
59
+
60
+ **Не сосед.** [Большая проекция](#большая-проекция-pr) идёт по **множеству** кортежей и возвращает множество компонент. `pr` не глотает `ℬ(…)`.
61
+
62
+ **Как сказать.** «вторая компонента кортежа α» (малая проекция `pr2`).
63
+
64
+ **Пример.** `pr2((5, 4, 3, 2, 1)) = 4`.
65
+
66
+ **Антипаттерн.** `pr1(S1)` при `S1 : ℬ(X1×X1)`. Нужен `Pr1(S1)`.
67
+
68
+ **Справка.** [Структурные выражения](https://portal.acconcept.ru/manuals?topic=rslang-expression-structure).
69
+
70
+ ## Большая проекция (`Pr`)
71
+
72
+ **Запись.** `Prk(S)`. Мультииндекс: `Pr2,4(S1)`.
73
+
74
+ **Что считается.** Множество выбранных компонент **всех** кортежей из `S`.
75
+
76
+ **Ступень.** Если `S : ℬ(H1×…×Hn)`, то `Prk(S) : ℬ(Hk)`; мультииндекс даёт множество кортежей выбранных компонент.
77
+
78
+ **Не сосед.** [Малая проекция](#малая-проекция-pr) — один кортеж. [Фильтр](#фильтр-fi) оставляет целые кортежи, а не вынимает компоненты.
79
+
80
+ **Как сказать.** «множество вторых компонент всех кортежей из S1» (большая проекция `Pr2`).
81
+
82
+ **Пример.** `Pr3({(1, 2, 3), (4, 5, 6)}) = {3, 6}`.
83
+
84
+ **Антипаттерн.** `Pr1((a, b))` — аргумент не множество. Нужен `pr1((a, b))`.
85
+
86
+ **Справка.** [Структурные выражения](https://portal.acconcept.ru/manuals?topic=rslang-expression-structure).
87
+
88
+ ## Фильтр (`Fi`)
89
+
90
+ **Запись.** `Fi1[D](S)`. Индекс указывает, какую компоненту кортежей из `S` сверять с `D`.
91
+
92
+ **Что считается.** Подмножество `S`: те кортежи, у которых выбранная компонента принадлежит `D`.
93
+
94
+ **Ступень.** Та же, что у `S` (множество кортежей). `D` должен быть множеством ступени выбранной компоненты: для элемента `ξ` пиши `{ξ}` или `bool(ξ)`, не голое `ξ`.
95
+
96
+ **Не сосед.** [Отбор `D{}`](#отбор-d) — условие на элементах любого множества, не обязательно отношения. [Большая проекция](#большая-проекция-pr) вынимает компоненты, фильтр оставляет кортежи целиком. Несколько индексов — карточки [фильтра с мультииндексом](#фильтр-с-мультииндексом) и [мультифильтра](#мультифильтр).
97
+
98
+ **Как сказать.** «из отношения S1 оставляем только кортежи, чья первая компонента лежит в D» (фильтр `Fi1`).
99
+
100
+ **Пример.** `Fi2[{2, 4}]({(1, 2), (3, 4), (5, 6)}) = {(1, 2), (3, 4)}`.
101
+
102
+ **Антипаттерн.** `Fi1[ξ](S1)` при `ξ∈X1`. Параметр фильтра — множество, нужен синглетон: `Fi1[{ξ}](S1)`. Иначе `invalidFilterBooleanEchelon`.
103
+
104
+ **Справка.** [Структурные выражения](https://portal.acconcept.ru/manuals?topic=rslang-expression-structure).
105
+
106
+ ## Фильтр с мультииндексом
107
+
108
+ **Запись.** `Fi1,2[D1, D2](S)` — индексов столько же, сколько параметров.
109
+
110
+ **Что считается.** Подмножество `S`, где первая компонента лежит в `D1` **и** вторая в `D2` (условия независимы).
111
+
112
+ **Ступень.** Та же, что у `S`. Каждый `Di` — множество ступени соответствующей компоненты.
113
+
114
+ **Не сосед.** [Мультифильтр](#мультифильтр) принимает **один** параметр: в него должен входить кортеж выбранных компонент. `Fi1,2[Pr1(D), Pr2(D)](S)` — это эта карточка (декартово по проекциям), а не мультифильтр `Fi1,2[D](S)`.
115
+
116
+ **Как сказать.** «оставляем кортежи, у которых первая компонента из D1, а вторая из D2» (фильтр с мультииндексом).
117
+
118
+ **Пример.** `S1 = {(1, 10), (1, 20), (2, 10)}`. `Fi1,2[{1, 2}, {10}](S1) = {(1, 10), (2, 10)}`.
119
+
120
+ **Антипаттерн.** Один параметр при двух индексах, если имелись в виду независимые множества: это уже [мультифильтр](#мультифильтр), другой смысл.
121
+
122
+ **Справка.** [Структурные выражения](https://portal.acconcept.ru/manuals?topic=rslang-expression-structure).
123
+
124
+ ## Мультифильтр
125
+
126
+ **Запись.** `Fi1,2[D](S)` — несколько индексов, **один** параметр `D`.
127
+
128
+ **Что считается.** Подмножество `S`, где кортеж выбранных компонент **целиком** принадлежит `D`. `D` — множество таких кортежей, не два отдельных домена.
129
+
130
+ **Ступень.** Та же, что у `S`. Ступень `D` — множество кортежей выбранных компонент, например `ℬ(H1×H2)` для `Fi1,2`.
131
+
132
+ **Не сосед.** `Fi1,2[D1, D2](S)` — [фильтр с мультииндексом](#фильтр-с-мультииндексом). Для `D = {(1, 10), (2, 20)}` мультифильтр `Fi1,2[D](S)` не равен `Fi1,2[Pr1(D), Pr2(D)](S)`: второе пускает любую комбинацию проекций.
133
+
134
+ **Как сказать.** «оставляем те кортежи, чья пара выбранных компонент лежит в D» (мультифильтр).
135
+
136
+ **Пример.** `S1 = {(1, 10), (1, 20), (2, 10)}`, `D1 = {(1, 10), (2, 20)}`. `Fi1,2[D1](S1) = {(1, 10)}`. Тогда `Fi1,2[Pr1(D1), Pr2(D1)](S1) = Fi1,2[{1, 2}, {10, 20}](S1) = S1`.
137
+
138
+ **Антипаттерн.** Объяснять мультифильтр как «первая компонента в D и вторая в D». У `D` элементы — кортежи, не смешивай с двумя множествами.
139
+
140
+ **Справка.** [Структурные выражения](https://portal.acconcept.ru/manuals?topic=rslang-expression-structure).
141
+
142
+ ## Синглетон (`bool`)
143
+
144
+ **Запись.** `bool(a)`. В идиоме фильтра чаще пишут `{ξ}` — одноэлементное перечисление, тот же смысл.
145
+
146
+ **Что считается.** Множество из одного элемента `a`.
147
+
148
+ **Ступень.** Если `a : H`, то `bool(a) : ℬ(H)`.
149
+
150
+ **Не сосед.** [Десинглетон](#десинглетон-debool) — обратная операция, только если множество одноэлементное. Голое `ξ` в параметре [фильтра](#фильтр-fi) — не синглетон.
151
+
152
+ **Как сказать.** «множество, в котором только ξ» (синглетон / буль `bool(ξ)`, в формуле часто `{ξ}`).
153
+
154
+ **Пример.** `bool(1) = {1}`.
155
+
156
+ **Антипаттерн.** `bool(S)` когда `S` уже множество и нужно само `S`, а не `{{…}}` ещё на один `ℬ`.
157
+
158
+ **Справка.** [Структурные выражения](https://portal.acconcept.ru/manuals?topic=rslang-expression-structure).
159
+
160
+ ## Десинглетон (`debool`)
161
+
162
+ **Запись.** `debool(S)`.
163
+
164
+ **Что считается.** Единственный элемент одноэлементного множества `S`.
165
+
166
+ **Ступень.** Если `S : ℬ(H)` и в `S` ровно один элемент, результат ступени `H`. Иначе ошибка типизации или вычисления (`invalidDebool`, `calcInvalidDebool`).
167
+
168
+ **Не сосед.** [Синглетон](#синглетон-bool) упаковывает элемент во множество. `debool` не заменяет [малую проекцию](#малая-проекция-pr).
169
+
170
+ **Как сказать.** «единственный элемент множества S» (десинглетон / дебуль `debool`).
171
+
172
+ **Пример.** `debool({1}) = 1`.
173
+
174
+ **Антипаттерн.** `debool` без гарантии синглетона: «тот единственный», хотя элементов может быть несколько.
175
+
176
+ **Справка.** [Структурные выражения](https://portal.acconcept.ru/manuals?topic=rslang-expression-structure).
177
+
178
+ ## Отбор (`D{}`)
179
+
180
+ **Запись.** `D{ξ∈A | P(ξ)}`. Буква `D` — часть синтаксиса, не конституента. Слева от `|` — переменная и домен (`∈`, не `:∈`); справа — логическое условие.
181
+
182
+ Краткая форма без `D` — только одна переменная: `{ξ∈A | P(ξ)}`. Кортеж в объявлении требует префикса: `D{(ξ1, ξ2)∈S1 | P(ξ1, ξ2)}`.
183
+
184
+ **Что считается.** Подмножество домена: те элементы (или кортежи), для которых условие истинно (схема ограниченного выделения, родо-видовое определение).
185
+
186
+ **Ступень.** `ℬ(H)`, где `H` — ступень элементов домена.
187
+
188
+ **Не сосед.** [Фильтр](#фильтр-fi) режет отношение по компоненте кортежа. [Императивный перебор](#императивный-перебор-i) строит то же множество по шагам, когда нужны промежуточные присвоения. [Рекурсия](#рекурсия-r) возвращает одно значение, не множество.
189
+
190
+ **Как сказать.** «те ξ из A, для которых выполняется P» (декларативный отбор, схема ограниченного выделения).
191
+
192
+ **Пример.** `D{ξ∈{1, 2, 3, 4, 5, 6} | ∃σ∈{10, 11, 12} σ = 2 * ξ} = {5, 6}`.
193
+
194
+ **Антипаттерн.** Объяснять `Fi1[{ξ}](S1)` как декларативный отбор. Для среза отношения по компоненте каноничен фильтр. В `D{}` писать `:∈` — это синтаксис перебора в `I{}`.
195
+
196
+ **Справка.** [Декларативная конструкция](https://portal.acconcept.ru/manuals?topic=rslang-expression-declarative).
197
+
198
+ ## Императивный перебор (`I{}`)
199
+
200
+ **Запись.** `I{элемент | блок; блок; …}`. Префикс `I` обязателен. Слева от `|` — ТМВ элемента результата. Справа — блоки через `;`: перебор `ξ:∈STE`, присвоение `ξ:=STE`, проверка `LE`.
201
+
202
+ **Что считается.** Множество значений левой части по всем прохождениям блоков, где каждая проверка истинна. Эквивалентен декларативному отбору, но шаги могут зависеть друг от друга.
203
+
204
+ **Ступень.** `ℬ(H)`, где `H` — ступень выражения слева от `|`.
205
+
206
+ **Не сосед.** [Отбор `D{}`](#отбор-d) — когда достаточно «элементы A по условию», без промежуточных `:=`. Если `I{(ξ, σ) | ξ:∈A; σ:=E(ξ)}` задаёт однозначную зависимость, в схеме это обычно [терм-функция](#параметризованные-выражения-f-p), а не множество пар. [Рекурсия](#рекурсия-r) — одно значение, не множество.
207
+
208
+ **Как сказать.** «собираем множество, перебирая элементы и по ходу вычисляя промежуточные значения» (императивная конструкция).
209
+
210
+ **Пример.** `I{(ξ1, ξ2) | ξ1:∈{1, 2, 3}; ξ2:=ξ1+1; ∃σ∈{4, 5, 6} σ=2*ξ2} = {(1, 2), (2, 3)}`.
211
+
212
+ **Антипаттерн.** `∈` вместо `:∈` в переборе. Называть `I{}` «циклом, который что-то печатает»: результат — множество. Объяснять график `I{(ξ,σ)|…}` как единственный канон, если это функция: см. [CONCEPTUAL-SCHEMA.md](CONCEPTUAL-SCHEMA.md).
213
+
214
+ **Справка.** [Императивная конструкция](https://portal.acconcept.ru/manuals?topic=rslang-expression-imperative).
215
+
216
+ ## Рекурсия (`R{}`)
217
+
218
+ **Запись.** `R{ξ := база | условие | следующий}`. Короткая форма без условия: `R{ξ := база | следующий}` — выход, когда значение стабилизировалось. Префикс `R` обязателен; в базе — `:=`. Переменная может быть кортежем.
219
+
220
+ **Что считается.** **Одно** значение: последнее значение переменной рекурсии. Не множество пройденных шагов.
221
+
222
+ **Ступень.** Ступень переменной рекурсии; пересчёт той же ступени.
223
+
224
+ **Не сосед.** [Императивный перебор](#императивный-перебор-i) собирает множество. Буква `R` перед `{` — синтаксис рекурсии, не [радикал `R#`](#параметризованные-выражения-f-p) и не конституента.
225
+
226
+ **Как сказать.** «начинаем с базы и подставляем формулу следующего шага, пока условие истинно или пока значение не перестанет меняться; результат — последнее значение» (рекурсивная / циклическая конструкция).
227
+
228
+ **Пример.** `R{ξ := 1 | ξ < 32 | 2 * ξ} = 32`. Кортеж: `R{(ξ, σ) := (1, 0) | σ < 5 | (2 * ξ, σ + 1)}` удваивает `ξ` пять раз (`ξ` доходит до 32); значение конструкции — последняя пара.
229
+
230
+ **Антипаттерн.** Говорить, что `R{}` «возвращает множество всех итераций». Путать `R{…}` с радикалом `R1` в `[α∈R1]`.
231
+
232
+ **Справка.** [Циклическая конструкция](https://portal.acconcept.ru/manuals?topic=rslang-expression-recursive).
233
+
234
+ ## Кванторы
235
+
236
+ **Запись.** `∀ξ∈A (P(ξ))` — всеобщность; `∃ξ∈A (P(ξ))` — существование. Кортеж: `∀(ξ1, ξ2)∈S1 (P(ξ1, ξ2))`. Сокращение вложенных кванторов с одним доменом: `∀ξ1, ξ2∈A (P(ξ1, ξ2))`. Скобки вокруг тела можно опустить, только если тело — атомарное ЛВ.
237
+
238
+ **Что считается.** Истинность утверждения о всех или о некоторых элементах множества. Это логическое выражение, не множество.
239
+
240
+ **Ступень.** `Logic`.
241
+
242
+ **Не сосед.** [Отбор `D{}`](#отбор-d) строит множество «те, для кого P». Квантор утверждает «для всех / существует», не отбирает. Кортеж `∀(a, b)∈S` — не то же, что два имени через запятую `∀a, b∈A`.
243
+
244
+ **Как сказать.** «для каждого ξ из A верно P» (квантор всеобщности) или «есть хотя бы один ξ из A, для которого верно P» (квантор существования).
245
+
246
+ **Пример.** `∀x∈D1 ∃y∈D2 ((x, y)∈S1 & (x, x)∈S1)`.
247
+
248
+ **Антипаттерн.** `∀a∈S P(a) & Q(a)`: без скобок `Q(a)` вне области квантора (`localOutOfScopeParentheses`). Нужно `∀a∈S (P(a) & Q(a))`.
249
+
250
+ **Справка.** [Кванторные выражения](https://portal.acconcept.ru/manuals?topic=rslang-expression-quantor).
251
+
252
+ ## Параметризованные выражения (`F#` / `P#`)
253
+
254
+ **Запись.** Объявление: `F1 ::= [α∈A] E(α)` — терм-функция, тело ТМВ; `P1 ::= [α∈A] P(α)` — предикат-функция, тело ЛВ. Вызов: `F1[ξ]`, `P1[ξ1, ξ2]`. Аргументы позиционные, только квадратные скобки.
255
+
256
+ Радикалы `R1`, `R2`, … — шаблонные ступени **только** в доменах параметров `[α∈R1×R2]`. Это не конституенты: в схеме нет записи с именем `R1`. В теле после `]` радикалов быть не должно.
257
+
258
+ **Что считается.** Вызов `F#` считает значение при данных аргументах. Вызов `P#` утверждает истинность при данных аргументах.
259
+
260
+ **Ступень.** У `F#` — ступень тела; у `P#` — `Logic`. Ступень радикала выводится по аргументам в месте вызова; все вхождения одного `R#` в одном определении дают одну ступень.
261
+
262
+ **Не сосед.** Множество пар `I{(ξ, σ) | ξ:∈A; σ:=E(ξ)}` — график; однозначная зависимость — терм-функция с вызовом `F[ξ]`. Рекурсия `R{…}` и радикал `R#` — разные буквы `R`.
263
+
264
+ **Как сказать.** «F1 по аргументу ξ считает …» (терм-функция, вызов `F1[ξ]`). «P1 при аргументах … утверждает, что …» (предикат-функция). Если в доменах `R#`: «это шаблон: ступень подставляется по месту вызова» (радикал, не понятие схемы).
265
+
266
+ **Пример.** `[ξ∈X1] Pr2(Fi1[{ξ}](S1))` — исходящие соседи; вызов `F1[α]`. Шаблон: `[α1∈R1×R2, α2∈R1] α2 = pr1(α1)`.
267
+
268
+ **Антипаттерн.** `F1(ξ)` вместо `F1[ξ]`. Голое `F1` без `[…]`. «Пропущенная конституента `R1`» или добавление `R1` в схему. Радикал в теле формулы (`radicalUsage`).
269
+
270
+ **Справка.** [Параметризованные выражения](https://portal.acconcept.ru/manuals?topic=rslang-expression-parameter). Выбор `F#` против пар — [CONCEPTUAL-SCHEMA.md](CONCEPTUAL-SCHEMA.md).
271
+
272
+ ## Типичная цепочка
273
+
274
+ Это **не** отдельный оператор языка. Так в схемах читают связь «аргумент ξ → связанные объекты в отношении S».
275
+
276
+ ```text
277
+ Pr2(Fi1[{ξ}](S1))
278
+ ```
279
+
280
+ Снаружи: множество вторых компонент тех пар из `S1`, у которых первая компонента равна `ξ`. Если `S1` — ориентированные рёбра, это концы рёбер из `ξ`.
281
+
282
+ Разбор карточками, изнутри:
283
+
284
+ 1. `{ξ}` — синглетон, фильтру нужно множество допустимых первых компонент.
285
+ 2. `Fi1[{ξ}](S1)` — фильтр, рёбра (пары) с началом `ξ`.
286
+ 3. `Pr2(...)` — большая проекция, множество концов.
287
+
288
+ В определениях эту зависимость обычно оформляют [терм-функцией](#параметризованные-выражения-f-p) `[ξ∈X1] Pr2(Fi1[{ξ}](S1))`, а не множеством пар. Правило проектирования — [CONCEPTUAL-SCHEMA.md](CONCEPTUAL-SCHEMA.md), «Терм-функция вместо множества пар». При объяснении цепочку всё равно разбирай карточками `Fi` и `Pr`.
289
+
290
+ ## Образец разбора
291
+
292
+ Конституента: терм-функция `F1`, термин «исходящие соседи».
293
+ `S1 : ℬ(X1×X1)`, конвенция: ориентированные рёбра `(начало, конец)`.
294
+
295
+ Формула:
296
+
297
+ ```text
298
+ [ξ∈X1] Pr2(Fi1[{ξ}](S1))
299
+ ```
300
+
301
+ Это теоретико-множественное выражение: по узлу `ξ` считается множество, а не истинность.
302
+
303
+ Снаружи. Для элемента `ξ` базисного множества `X1` получается множество вторых компонент тех пар из `S1`, у которых первая компонента — `ξ`. По конвенции это множество концов рёбер, выходящих из `ξ`.
304
+
305
+ Цепочка:
306
+
307
+ - `{ξ}` — множество, в котором только `ξ` (синглетон): фильтру нужен набор допустимых первых компонент, не сам элемент.
308
+ - `Fi1[{ξ}](S1)` — из отношения `S1` оставляем кортежи с первой компонентой `ξ` (фильтр).
309
+ - `Pr2(...)` — множество вторых компонент этих кортежей (большая проекция).
310
+
311
+ Ступень. Параметр `ξ∈X1`, результат `ℬ(X1)`. Опоры: `X1`, `S1`.
312
+
313
+ Ссылок на справку Portal в таком разборе нет. Вычисление на данных — только по отдельному запросу.
314
+
315
+ ## Классические операции
316
+
317
+ Короткие строки. Не разворачивай их в отдельные главы и не читай `SYNTAX.md` целиком, чтобы объяснить объединение.
318
+
319
+ Справка по группам: [теоретико-множественные](https://portal.acconcept.ru/manuals?topic=rslang-expression-set), [структурные](https://portal.acconcept.ru/manuals?topic=rslang-expression-structure), [арифметика](https://portal.acconcept.ru/manuals?topic=rslang-expression-arithmetic).
320
+
321
+ ### Объединение, пересечение, разность
322
+
323
+ | Запись | Как сказать | Пример |
324
+ | :----- | :---------- | :----- |
325
+ | `A ∪ B` | элементы, которые есть в A или в B (объединение) | `{1, 2} ∪ {2, 3} = {1, 2, 3}` |
326
+ | `A ∩ B` | элементы, которые есть и в A, и в B (пересечение) | `{1, 2, 3} ∩ {2, 3, 4} = {2, 3}` |
327
+ | `A \ B` | элементы A, которых нет в B (разность) | `{1, 2, 3} \ {2} = {1, 3}` |
328
+ | `A ∆ B` | элементы ровно в одном из двух множеств (симметрическая разность) | `{1, 2} ∆ {2, 3} = {1, 3}` |
329
+
330
+ Операнды одной ступени-множества. Не сосед фильтра: `∪` не «добавляет колонку», а сливает два множества.
331
+
332
+ ### Булеан (`ℬ`)
333
+
334
+ **Как сказать.** «множество всех подмножеств A» (булеан `ℬ(A)`).
335
+
336
+ **Ступень.** Элементы результата сами являются подмножествами A. В типизации `S#` запись `ℬ(X1×X1)` — «множество пар из X1».
337
+
338
+ **Не сосед.** [Синглетон](#синглетон-bool) `bool(a)` — одно подмножество `{a}`, не все подмножества.
339
+
340
+ ### Декартово произведение (`×`)
341
+
342
+ **Как сказать.** «множество всех пар (кортежей) с первой компонентой из A и второй из B» (декартово произведение).
343
+
344
+ **Пример.** Элементы `X1×X2` — пары `(x1, x2)`.
345
+
346
+ **Не сосед.** Один кортеж `(a, b)` — значение, не множество всех пар. [Отбор](#отбор-d) / [фильтр](#фильтр-fi) выбирают из уже построенного произведения или отношения.
347
+
348
+ ### Суммарное множество (`red`)
349
+
350
+ **Как сказать.** «объединение всех множеств, которые являются элементами S» (множество-сумма `red`).
351
+
352
+ **Ступень.** Нужно `S : ℬ(ℬ(H))`. Результат `ℬ(H)`.
353
+
354
+ **Пример.** `red({{1, 2, 3}, {3, 4}}) = {1, 2, 3, 4}`.
355
+
356
+ **Антипаттерн.** `red` по множеству, элементы которого не множества (`invalidReduce`).
357
+
358
+ ### Мощность (`card`)
359
+
360
+ **Как сказать.** «сколько элементов в конечном множестве S» (мощность `card(S)`). Результат — целое (`Z`).
361
+
362
+ **Пример.** `card(X1) > 5` — логическое сравнение мощности.
363
+
364
+ **Не сосед.** `card` не заменяет [квантор](#кванторы) «для всех». Арифметика `+` `-` `*` и порядок `<` только на `Z` или `C#`, не на элементах `X#` ([BASE-SELECTION.md](BASE-SELECTION.md)).
365
+
366
+ ## Ссылка на справку Portal
367
+
368
+ Стабильный адрес: `https://portal.acconcept.ru/manuals?topic=<slug>`.
369
+
370
+ В чат ссылку давай, если пользователь разбирает **конструкцию в абстракции** («что такое фильтр») или явно просит подробнее. При разборе конкретной формулы ссылку на каждый оператор не повторяй.
371
+
372
+ Не читай TSX справки Portal как источник фраз: говори по карточкам этого файла.
@@ -210,12 +210,12 @@ runtime-ошибки в теле `F#`/`P#`) диагностика несёт `s
210
210
 
211
211
  ## Значение и схема
212
212
 
213
- | Код | Имя | `params` | Исправление |
214
- | -------- | ---------------------- | ------------------ | --------------------------------------------------------------------------------------------------------- |
215
- | `0x8840` | `globalNoValue` | `[name]` | Идентификатор `name` невычислим в модели. |
216
- | `0x8841` | `invalidPropertyUsage` | — | `Property` - множество использовано как вычислимое значение. |
217
- | `0x8861` | `cstEmptyDerived` | — | У выводимой конституенты пустая формула. |
218
- | `0x8862` | `definitionNotAllowed` | `[cstType, alias]` | У `basic`/`constant` формула должна быть пустой; `cstType` — роль конституенты, `alias` — её обозначение. |
213
+ | Код | Имя | `params` | Исправление |
214
+ | -------- | ---------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
215
+ | `0x8840` | `globalNoValue` | `[name]` | Идентификатор `name` невычислим в модели. |
216
+ | `0x8841` | `invalidPropertyUsage` | — | `Property` - множество использовано как вычислимое значение (типично: квантор по `ℬ(S1)` / `ℬ(X1)`). Перепиши через вычислимые термы (`F#` достижимости, `card`, `Pr`) или оставь как декларативную формулировку и укажи это в ревью. |
217
+ | `0x8861` | `cstEmptyDerived` | — | У выводимой конституенты пустая формула. |
218
+ | `0x8862` | `definitionNotAllowed` | `[cstType, alias]` | У `basic`/`constant` формула должна быть пустой; `cstType` — роль конституенты, `alias` — её обозначение. |
219
219
 
220
220
  ## Вычисление КМ
221
221
 
@@ -35,6 +35,16 @@ await tool.setModelValues({
35
35
 
36
36
  Здесь `X1` получает подписи элементов, а `S1: ℬ(X1×X1)` получает множество пар по индексам элементов `X1`.
37
37
 
38
+ - Порядок элементов и дубликаты во входе не важны: `setModelValues` приводит значения `S#` к канонической форме (сортировка `compare`, без повторов). В `getModelState` и в результатах вычисления множества всегда отсортированы — сравнивай с ожиданием как с отсортированным массивом.
39
+ - Кортежи — `[TUPLE_ID, …]`; вложенные множества — обычные массивы (`ℬℬ(X1)`: `[[0, 1], [2]]`).
40
+ - `status` в `evaluate` / `recalculateModel` — числовой `EvalStatus` (`7` `HAS_DATA`, `6` `EMPTY`, `5` `AXIOM_FALSE`, `4` `EVAL_FAIL`); таблица — в `REFERENCE.md`.
41
+
42
+ ## Чтение результата
43
+
44
+ - Конституента: `evaluate({ constituentId })` — вычисляет её и все поставщики.
45
+ - Scratch: `evaluate({ expression, cstType })`. `cstType` задаёт ожидаемую ступень: `'term'` — множество или число, `'axiom'` — логическое выражение (`P1[S1]`, `D2⊆S1`). В scratch-выражении можно ссылаться на любые конституенты схемы, включая производные `D#`.
46
+ - Литералов элементов `X#` в ЯРЭ нет: выражай тестовые элементы через схему (`debool(D3)`, `Pr1(S1)\Pr2(S1)`), а не через подписи.
47
+
38
48
  ## Скрипты-тесты
39
49
 
40
50
  Если проверка влияет на поведение схемы или есть риск регрессии, вынеси ее в маленький скрипт или colocated `*.test.ts`:
@@ -46,6 +56,44 @@ await tool.setModelValues({
46
56
 
47
57
  Тест должен проверять смысл формулы, а не только отсутствие диагностик. Для аксиом отдельно проверяй положительный и отрицательный набор данных: корректная модель должна давать истинную аксиому, ошибочная — `AXIOM_FALSE` или диагностируемый сбой вычисления.
48
58
 
59
+ ```ts
60
+ import { EvalStatus, TUPLE_ID } from '@rsconcept/domain';
61
+
62
+ // X1 — вершины, S1: ℬ(X1×X1) — рёбра, A1 ::= ∀α∈X1 α∉F4[α] — ацикличность
63
+ const X1 = 1,
64
+ S1 = 2,
65
+ A1 = 17;
66
+ await tool.setModelValues({
67
+ set: [
68
+ { target: X1, value: { 0: 'a', 1: 'b', 2: 'c' } },
69
+ {
70
+ target: S1,
71
+ value: [
72
+ [TUPLE_ID, 0, 1],
73
+ [TUPLE_ID, 1, 2]
74
+ ]
75
+ }
76
+ ]
77
+ });
78
+ let a1 = tool.evaluate({ constituentId: A1 });
79
+ // a1.status === EvalStatus.HAS_DATA, a1.value === 1
80
+
81
+ await tool.setModelValues({
82
+ set: [
83
+ {
84
+ target: S1,
85
+ value: [
86
+ [TUPLE_ID, 0, 1],
87
+ [TUPLE_ID, 1, 2],
88
+ [TUPLE_ID, 2, 0]
89
+ ]
90
+ }
91
+ ]
92
+ });
93
+ a1 = tool.evaluate({ constituentId: A1 });
94
+ // a1.status === EvalStatus.AXIOM_FALSE, a1.value === 0
95
+ ```
96
+
49
97
  ## Ограничения
50
98
 
51
99
  - Маленькая КМ проверяет семантику на выбранных данных, но не доказывает определение для всех моделей.
package/docs/README.md CHANGED
@@ -11,6 +11,7 @@
11
11
  - **CONSTITUENTA.md** — структура и правила конституент.
12
12
  - **BASE-SELECTION.md** — выбор основания: `X#`, `C#` или `Z`.
13
13
  - **SYNTAX.md** — синтаксис ЯРЭ: операторы, генераторы `D{}`/`I{}`/`R{}`, кванторы, `F#`/`P#`.
14
+ - **CONSTRUCTIONS.md** — объяснение формул и конструкций человеку (карточки, разбор снаружи внутрь).
14
15
  - **TYPIFICATION.md** — типизация (`AnalysisResult.type`, `valueClass`).
15
16
  - **MODEL-TESTING.md** — проверка семантики определений на маленьких концептуальных моделях.
16
17
  - **DIAGNOSTICS.md** — диагностики анализа и способы исправления ошибок.
package/docs/SYNTAX.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Синтаксис ЯРЭ
2
2
 
3
- Единая справка для агента: читай при построении или исправлении `definitionFormal`. Типизация — `TYPIFICATION.md`; ошибки — `DIAGNOSTICS.md`.
3
+ Единая справка для агента: читай при построении или исправлении `definitionFormal`. Типизация — `TYPIFICATION.md`; ошибки — `DIAGNOSTICS.md`. Объяснение человеку — [CONSTRUCTIONS.md](CONSTRUCTIONS.md).
4
4
 
5
5
  ## Имена и литералы
6
6
 
@@ -25,8 +25,17 @@
25
25
  ## `AnalysisResult.type`
26
26
 
27
27
  1. Сначала проверь `analysis.success === true` и `analysis.type !== null`.
28
- 2. Не разбирай объект вручную; используй helpers из `@rsconcept/domain`.
29
- 3. `valueClass` уточняет вычислимость: `Value`, `Property`, `Invalid`.
28
+ 2. Не разбирай объект вручную; печатай через `labelType` из `@rsconcept/domain/rslang/labels`:
29
+
30
+ ```ts
31
+ import { labelType } from '@rsconcept/domain/rslang/labels';
32
+
33
+ labelType(analysis.type); // 'ℬ(X1×X1)', '[X1] → ℬ(X1)', '[ℬ(X1×X1)] → Logic', 'Logic'
34
+ ```
35
+
36
+ Для скрипта вне пакета — `file:///<workspace>/rsconcept/domain/src/rslang/labels.ts` (см. GUIDE, «Как запускать rstool»). `normalizeType` из того же модуля даёт каноническую строку для сравнения типизаций.
37
+
38
+ 3. `valueClass` уточняет вычислимость: `'value'` (вычислимо), `'property'` (только проверка принадлежности), `null` (ошибка). `success: true` не исключает диагностику `error`: квантор по `ℬ(…)` разбирается, но даёт `invalidPropertyUsage` и `valueClass: null`.
30
39
 
31
40
  ## `S#` и `D#`
32
41
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rsconcept/rstool",
3
- "version": "1.7.1",
3
+ "version": "1.9.0",
4
4
  "description": "Agent-facing library for incremental RSForm construction, RSLang analysis, diagnostics, modeling, and evaluation. Wraps @rsconcept/domain with a deterministic session contract.",
5
5
  "license": "MIT",
6
6
  "author": "IRBorisov",
@@ -50,6 +50,23 @@
50
50
  "README.md",
51
51
  "LICENSE"
52
52
  ],
53
+ "dependencies": {
54
+ "eslint": "^10.9.1",
55
+ "eslint-plugin-simple-import-sort": "^14.0.0",
56
+ "@rsconcept/domain": "3.1.1"
57
+ },
58
+ "devDependencies": {
59
+ "@types/node": "^26.4.1",
60
+ "@vitest/coverage-v8": "^4.1.11",
61
+ "tsdown": "^0.22.14",
62
+ "tsx": "^4.23.13",
63
+ "typescript": "^6.0.3",
64
+ "unrun": "^0.3.1",
65
+ "vitest": "^4.1.11"
66
+ },
67
+ "publishConfig": {
68
+ "access": "public"
69
+ },
53
70
  "scripts": {
54
71
  "build": "tsdown",
55
72
  "typecheck": "tsc -p tsconfig.json --noEmit",
@@ -68,22 +85,6 @@
68
85
  "example:build-expression-bank-schema": "tsx examples/expression-bank/build-rsform.ts",
69
86
  "example:build-template-apply-schema": "tsx examples/template-apply/build-rsform.ts",
70
87
  "example:audit-diagnostics": "tsx examples/audit-diagnostics.ts",
71
- "kinship:cli": "tsx examples/kinship/cli.ts",
72
- "prepublishOnly": "pnpm run build"
73
- },
74
- "dependencies": {
75
- "@rsconcept/domain": "workspace:*"
76
- },
77
- "devDependencies": {
78
- "@types/node": "^26.1.1",
79
- "@vitest/coverage-v8": "^4.1.10",
80
- "tsdown": "^0.22.4",
81
- "tsx": "^4.23.0",
82
- "typescript": "^6.0.3",
83
- "unrun": "^0.3.1",
84
- "vitest": "^4.1.10"
85
- },
86
- "publishConfig": {
87
- "access": "public"
88
+ "kinship:cli": "tsx examples/kinship/cli.ts"
88
89
  }
89
- }
90
+ }
package/skills/README.md CHANGED
@@ -9,7 +9,7 @@ Each skill lives in its own subdirectory: `skills/<skill-name>/SKILL.md` (plus r
9
9
  - `rstool-helper/GUIDE.md`: entry point — task→read matrix, workflows (incl. review), checklists (Russian)
10
10
  - `rstool-helper/REFERENCE.md`: API, stdio, MCP names, response shapes, help map (Russian)
11
11
  - `rstool-helper/EXAMPLES.md`: snippets, anti-patterns, diagnostics, `examples/` index (Russian)
12
- - `../docs/*.md`: language reference (DOMAIN, SYNTAX, DIAGNOSTICS, …)
12
+ - `../docs/*.md`: language reference (DOMAIN, SYNTAX, CONSTRUCTIONS, DIAGNOSTICS, …)
13
13
 
14
14
  ## npm workflow
15
15
 
@@ -153,6 +153,7 @@ tool.applySchemaPatch({
153
153
  | `globalFuncParenCall` | `F1(ξ)` | `F1[ξ]` |
154
154
  | `globalFuncWithoutArgs` | голое `F1` в формуле | `F1[…]` |
155
155
  | `radicalUsage` | `R1` в теле формулы или как конституента | `R#` только в `[…]` у `F#`/`P#` |
156
+ | `invalidPropertyUsage` | `∀σ∈ℬ(S1)\{∅} ¬P1[σ]` — квантор по булеану | вычислимая форма через достижимость: `∀α∈X1 α∉F4[α]` |
156
157
  | `schemaMissingConvention` | `X1` без конвенции | добавь предметную конвенцию |
157
158
  | `schemaHomonym` | одинаковый термин у разных конституент | различай термины |
158
159
  | `schemaDependencyCycle` | круг в определениях (`F3 → P1 → F3`) | разорви цикл: убери взаимные ссылки |
@@ -237,6 +238,29 @@ const scratch = tool.evaluate({ expression: '1+2', cstType: CstType.TERM });
237
238
  const recalc = tool.recalculateModel();
238
239
  ```
239
240
 
241
+ Множества `S#` — кортежи `[TUPLE_ID, i, j]` по индексам `X#`; порядок во входе не важен (нормализуется). Scratch может ссылаться на производные конституенты; логические выражения — с `cstType: CstType.AXIOM`:
242
+
243
+ ```ts
244
+ import { EvalStatus, TUPLE_ID } from '@rsconcept/domain';
245
+
246
+ await tool.setModelValues({
247
+ set: [
248
+ { target: 1, value: { 0: 'a', 1: 'b', 2: 'c' } },
249
+ {
250
+ target: 2,
251
+ value: [
252
+ [TUPLE_ID, 1, 2],
253
+ [TUPLE_ID, 0, 1]
254
+ ]
255
+ } // S1: ℬ(X1×X1)
256
+ ]
257
+ });
258
+ const closure = tool.evaluate({ constituentId: 9 }); // D9 — транзитивное замыкание
259
+ closure.status === EvalStatus.HAS_DATA; // status — число: 7
260
+ const check = tool.evaluate({ expression: 'S1⊆D9', cstType: CstType.AXIOM });
261
+ check.value === 1;
262
+ ```
263
+
240
264
  ## Экспорт / импорт и Portal round-trip
241
265
 
242
266
  ```ts