@rsconcept/rstool 0.3.0 → 0.5.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 (42) hide show
  1. package/README.md +4 -2
  2. package/dist/index-uhkmwruf.d.ts +46 -0
  3. package/dist/index.d.ts +5 -4
  4. package/dist/index.js +2 -2
  5. package/dist/mappers/model-adapter.d.ts +1 -1
  6. package/dist/mappers/schema-adapter.d.ts +1 -1
  7. package/dist/models/index.d.ts +5 -4
  8. package/dist/models/index.js +2 -2
  9. package/dist/models/rstool-agent.d.ts +1 -1
  10. package/dist/models/rstool-agent.js +1 -92
  11. package/dist/models/session.d.ts +1 -1
  12. package/dist/models/tool-contract.d.ts +1 -1
  13. package/dist/models/tool-contract.js +1 -1
  14. package/dist/models/tool-contract.js.map +1 -1
  15. package/dist/rstool-agent-BZi5jO1y.js +158 -0
  16. package/dist/rstool-agent-BZi5jO1y.js.map +1 -0
  17. package/dist/{rstool-agent-DkeH5Qml.d.ts → rstool-agent-pRaPnZay.d.ts} +6 -4
  18. package/dist/session/session-store.d.ts +2 -1
  19. package/dist/session/session-store.js +3 -0
  20. package/dist/session/session-store.js.map +1 -1
  21. package/dist/{session-BHGCCLfQ.d.ts → session-BPgsE80c.d.ts} +12 -1
  22. package/dist/{tool-contract-CsGqg_0P.d.ts → tool-contract-n1ghUOrK.d.ts} +5 -3
  23. package/dist/wrapper/stdio-wrapper.js +13 -1
  24. package/dist/wrapper/stdio-wrapper.js.map +1 -1
  25. package/docs/CONCEPTUAL-SCHEMA.md +66 -28
  26. package/docs/CONSTITUENTA.md +11 -9
  27. package/docs/PORTAL-API.md +1 -0
  28. package/docs/TYPIFICATION.md +3 -9
  29. package/package.json +1 -1
  30. package/skills/rstool-helper/EXAMPLES.md +59 -0
  31. package/skills/rstool-helper/GUIDE.md +5 -30
  32. package/skills/rstool-helper/REFERENCE.md +42 -11
  33. package/src/index.ts +6 -0
  34. package/src/models/index.ts +8 -0
  35. package/src/models/portal-json.ts +45 -0
  36. package/src/models/rstool-agent.test.ts +98 -0
  37. package/src/models/rstool-agent.ts +72 -4
  38. package/src/models/session.ts +11 -0
  39. package/src/models/tool-contract.ts +3 -1
  40. package/src/session/session-store.ts +3 -0
  41. package/src/wrapper/stdio-wrapper.ts +14 -0
  42. package/dist/models/rstool-agent.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"stdio-wrapper.js","names":[],"sources":["../../src/wrapper/stdio-wrapper.ts"],"sourcesContent":["#!/usr/bin/env node\nimport readline from 'node:readline';\n\nimport { RSToolAgent } from '../models/rstool-agent';\n\ninterface StdioRequest {\n id: string | number;\n method: string;\n params?: unknown;\n}\n\ninterface StdioResponse {\n id: string | number | null;\n ok: boolean;\n result?: unknown;\n error?: {\n code: string;\n message: string;\n details?: unknown;\n };\n}\n\nconst tool = new RSToolAgent();\n\nconst METHODS = [\n 'createSession',\n 'addOrUpdateConstituenta',\n 'analyzeExpression',\n 'getFormState',\n 'listDiagnostics',\n 'commitStep',\n 'exportSession',\n 'importSession',\n 'setConstituentaValue',\n 'setConstituentaValues',\n 'clearConstituentaValues',\n 'getModelState',\n 'evaluateExpression',\n 'evaluateConstituenta',\n 'recalculateModel'\n] as const;\n\nfunction writeResponse(response: StdioResponse): void {\n if (!process.stdout.writable || process.stdout.destroyed || process.stdout.writableEnded) {\n return;\n }\n try {\n process.stdout.write(`${JSON.stringify(response)}\\n`);\n } catch {\n // The client might have already closed stdout (EPIPE). Safe to ignore.\n }\n}\n\nfunction asObject(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return {};\n }\n return value as Record<string, unknown>;\n}\n\nfunction requiredString(input: Record<string, unknown>, key: string): string {\n const value = input[key];\n if (typeof value !== 'string' || value.length === 0) {\n throw new Error(`Missing or invalid \"${key}\"`);\n }\n return value;\n}\n\nasync function handleRequest(request: StdioRequest): Promise<StdioResponse> {\n try {\n const params = asObject(request.params);\n switch (request.method) {\n case 'ping':\n return { id: request.id, ok: true, result: { pong: true } };\n case 'methods':\n return { id: request.id, ok: true, result: METHODS };\n case 'createSession':\n return {\n id: request.id,\n ok: true,\n result: tool.createSession(params.initial as never)\n };\n case 'addOrUpdateConstituenta':\n return {\n id: request.id,\n ok: true,\n result: tool.addOrUpdateConstituenta(requiredString(params, 'sessionId'), params.input as never)\n };\n case 'analyzeExpression':\n return {\n id: request.id,\n ok: true,\n result: tool.analyzeExpression(requiredString(params, 'sessionId'), params.input as never)\n };\n case 'getFormState':\n return {\n id: request.id,\n ok: true,\n result: tool.getFormState(requiredString(params, 'sessionId'))\n };\n case 'listDiagnostics':\n return {\n id: request.id,\n ok: true,\n result: tool.listDiagnostics(requiredString(params, 'sessionId'), params.filters as never)\n };\n case 'commitStep':\n return {\n id: request.id,\n ok: true,\n result: tool.commitStep(requiredString(params, 'sessionId'), params.message as string | undefined)\n };\n case 'exportSession':\n return {\n id: request.id,\n ok: true,\n result: tool.exportSession(requiredString(params, 'sessionId'))\n };\n case 'importSession':\n return {\n id: request.id,\n ok: true,\n result: tool.importSession(requiredString(params, 'payload'))\n };\n case 'setConstituentaValue':\n return {\n id: request.id,\n ok: true,\n result: await tool.setConstituentaValue(requiredString(params, 'sessionId'), params.input as never)\n };\n case 'setConstituentaValues':\n return {\n id: request.id,\n ok: true,\n result: await tool.setConstituentaValues(requiredString(params, 'sessionId'), params.input as never)\n };\n case 'clearConstituentaValues':\n return {\n id: request.id,\n ok: true,\n result: await tool.clearConstituentaValues(requiredString(params, 'sessionId'), params.input as never)\n };\n case 'getModelState':\n return {\n id: request.id,\n ok: true,\n result: tool.getModelState(requiredString(params, 'sessionId'))\n };\n case 'evaluateExpression':\n return {\n id: request.id,\n ok: true,\n result: tool.evaluateExpression(requiredString(params, 'sessionId'), params.input as never)\n };\n case 'evaluateConstituenta':\n return {\n id: request.id,\n ok: true,\n result: tool.evaluateConstituenta(requiredString(params, 'sessionId'), params.input as never)\n };\n case 'recalculateModel':\n return {\n id: request.id,\n ok: true,\n result: tool.recalculateModel(requiredString(params, 'sessionId'))\n };\n default:\n return {\n id: request.id ?? null,\n ok: false,\n error: {\n code: 'METHOD_NOT_FOUND',\n message: `Unknown method: ${request.method}`\n }\n };\n }\n } catch (error) {\n return {\n id: request.id ?? null,\n ok: false,\n error: {\n code: 'INTERNAL_ERROR',\n message: error instanceof Error ? error.message : 'Unknown error',\n details: error\n }\n };\n }\n}\n\nconst input = readline.createInterface({\n input: process.stdin,\n crlfDelay: Infinity\n});\n\nwriteResponse({\n id: null,\n ok: true,\n result: {\n ready: true,\n wrapper: 'rstool-stdio',\n contractVersion: tool.contractVersion\n }\n});\n\ninput.on('line', line => {\n if (!line.trim()) {\n return;\n }\n try {\n const request = JSON.parse(line) as StdioRequest;\n if (!('id' in request) || !('method' in request)) {\n throw new Error('Request must include \"id\" and \"method\"');\n }\n void handleRequest(request).then(writeResponse);\n } catch (error) {\n writeResponse({\n id: null,\n ok: false,\n error: {\n code: 'BAD_REQUEST',\n message: error instanceof Error ? error.message : 'Invalid JSON'\n }\n });\n }\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"stdio-wrapper.js","names":[],"sources":["../../src/wrapper/stdio-wrapper.ts"],"sourcesContent":["#!/usr/bin/env node\nimport readline from 'node:readline';\n\nimport { RSToolAgent } from '../models/rstool-agent';\n\ninterface StdioRequest {\n id: string | number;\n method: string;\n params?: unknown;\n}\n\ninterface StdioResponse {\n id: string | number | null;\n ok: boolean;\n result?: unknown;\n error?: {\n code: string;\n message: string;\n details?: unknown;\n };\n}\n\nconst tool = new RSToolAgent();\n\nconst METHODS = [\n 'createSession',\n 'addOrUpdateConstituenta',\n 'analyzeExpression',\n 'getFormState',\n 'listDiagnostics',\n 'commitStep',\n 'exportSession',\n 'exportPortalSchema',\n 'exportPortalModel',\n 'importSession',\n 'setConstituentaValue',\n 'setConstituentaValues',\n 'clearConstituentaValues',\n 'getModelState',\n 'evaluateExpression',\n 'evaluateConstituenta',\n 'recalculateModel'\n] as const;\n\nfunction writeResponse(response: StdioResponse): void {\n if (!process.stdout.writable || process.stdout.destroyed || process.stdout.writableEnded) {\n return;\n }\n try {\n process.stdout.write(`${JSON.stringify(response)}\\n`);\n } catch {\n // The client might have already closed stdout (EPIPE). Safe to ignore.\n }\n}\n\nfunction asObject(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return {};\n }\n return value as Record<string, unknown>;\n}\n\nfunction requiredString(input: Record<string, unknown>, key: string): string {\n const value = input[key];\n if (typeof value !== 'string' || value.length === 0) {\n throw new Error(`Missing or invalid \"${key}\"`);\n }\n return value;\n}\n\nasync function handleRequest(request: StdioRequest): Promise<StdioResponse> {\n try {\n const params = asObject(request.params);\n switch (request.method) {\n case 'ping':\n return { id: request.id, ok: true, result: { pong: true } };\n case 'methods':\n return { id: request.id, ok: true, result: METHODS };\n case 'createSession':\n return {\n id: request.id,\n ok: true,\n result: tool.createSession(params.initial as never)\n };\n case 'addOrUpdateConstituenta':\n return {\n id: request.id,\n ok: true,\n result: tool.addOrUpdateConstituenta(requiredString(params, 'sessionId'), params.input as never)\n };\n case 'analyzeExpression':\n return {\n id: request.id,\n ok: true,\n result: tool.analyzeExpression(requiredString(params, 'sessionId'), params.input as never)\n };\n case 'getFormState':\n return {\n id: request.id,\n ok: true,\n result: tool.getFormState(requiredString(params, 'sessionId'))\n };\n case 'listDiagnostics':\n return {\n id: request.id,\n ok: true,\n result: tool.listDiagnostics(requiredString(params, 'sessionId'), params.filters as never)\n };\n case 'commitStep':\n return {\n id: request.id,\n ok: true,\n result: tool.commitStep(requiredString(params, 'sessionId'), params.message as string | undefined)\n };\n case 'exportSession':\n return {\n id: request.id,\n ok: true,\n result: tool.exportSession(requiredString(params, 'sessionId'))\n };\n case 'exportPortalSchema':\n return {\n id: request.id,\n ok: true,\n result: tool.exportPortalSchema(requiredString(params, 'sessionId'))\n };\n case 'exportPortalModel':\n return {\n id: request.id,\n ok: true,\n result: tool.exportPortalModel(requiredString(params, 'sessionId'))\n };\n case 'importSession':\n return {\n id: request.id,\n ok: true,\n result: tool.importSession(requiredString(params, 'payload'))\n };\n case 'setConstituentaValue':\n return {\n id: request.id,\n ok: true,\n result: await tool.setConstituentaValue(requiredString(params, 'sessionId'), params.input as never)\n };\n case 'setConstituentaValues':\n return {\n id: request.id,\n ok: true,\n result: await tool.setConstituentaValues(requiredString(params, 'sessionId'), params.input as never)\n };\n case 'clearConstituentaValues':\n return {\n id: request.id,\n ok: true,\n result: await tool.clearConstituentaValues(requiredString(params, 'sessionId'), params.input as never)\n };\n case 'getModelState':\n return {\n id: request.id,\n ok: true,\n result: tool.getModelState(requiredString(params, 'sessionId'))\n };\n case 'evaluateExpression':\n return {\n id: request.id,\n ok: true,\n result: tool.evaluateExpression(requiredString(params, 'sessionId'), params.input as never)\n };\n case 'evaluateConstituenta':\n return {\n id: request.id,\n ok: true,\n result: tool.evaluateConstituenta(requiredString(params, 'sessionId'), params.input as never)\n };\n case 'recalculateModel':\n return {\n id: request.id,\n ok: true,\n result: tool.recalculateModel(requiredString(params, 'sessionId'))\n };\n default:\n return {\n id: request.id ?? null,\n ok: false,\n error: {\n code: 'METHOD_NOT_FOUND',\n message: `Unknown method: ${request.method}`\n }\n };\n }\n } catch (error) {\n return {\n id: request.id ?? null,\n ok: false,\n error: {\n code: 'INTERNAL_ERROR',\n message: error instanceof Error ? error.message : 'Unknown error',\n details: error\n }\n };\n }\n}\n\nconst input = readline.createInterface({\n input: process.stdin,\n crlfDelay: Infinity\n});\n\nwriteResponse({\n id: null,\n ok: true,\n result: {\n ready: true,\n wrapper: 'rstool-stdio',\n contractVersion: tool.contractVersion\n }\n});\n\ninput.on('line', line => {\n if (!line.trim()) {\n return;\n }\n try {\n const request = JSON.parse(line) as StdioRequest;\n if (!('id' in request) || !('method' in request)) {\n throw new Error('Request must include \"id\" and \"method\"');\n }\n void handleRequest(request).then(writeResponse);\n } catch (error) {\n writeResponse({\n id: null,\n ok: false,\n error: {\n code: 'BAD_REQUEST',\n message: error instanceof Error ? error.message : 'Invalid JSON'\n }\n });\n }\n});\n"],"mappings":"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"}
@@ -9,15 +9,7 @@
9
9
  - Добавляй понятие, если оно дает новый критерий, роль, отношение, инвариант или правило.
10
10
  - Если пользователь постоянно переформулирует одно различие, введи отдельную конституенту.
11
11
 
12
- ## Текстовые поля
13
-
14
- `term`, `definitionText`, `convention` держи в языке схемы и в ее словаре.
15
-
16
- - `term` — короткое имя понятия.
17
- - `definitionText` — текстовая интерпретация формального определения.
18
- - `convention` — соглашение для неопределяемого понятия.
19
-
20
- Перед записью `definitionText` проверь существительные: важный предметный термин должен быть введен как `N#`, `X#`, `C#`, `S#` или `D#`.
12
+ Подробнее про структуру и поля конституент см. в [CONSTITUENTA.md](./CONSTITUENTA.md).
21
13
 
22
14
  ## Номиноиды и атрибутирование
23
15
 
@@ -25,7 +17,7 @@
25
17
 
26
18
  Атрибутирование связывает номиноид с другими конституентами через атрибуты. Это отдельная атрибутивная экспликация, не замена `S#`, `D#`, `A#` в родоструктурной экспликации.
27
19
 
28
- Правило для `rstool`: не смешивай атрибутивную и родоструктурную экспликацию. Используй `N#` как словарную опору, но не превращай атрибуты в RS-формулы и не добавляй атрибутивные связи, если пользователь явно не просит совместить эти способы.
20
+ Правило для `rstool`: не смешивай атрибутивную и родоструктурную экспликацию если явно не указано пользователем.
29
21
 
30
22
  ## Родовые структуры
31
23
 
@@ -34,19 +26,64 @@
34
26
  Паттерн для отношения:
35
27
 
36
28
  1. `X1` — базисное множество.
37
- 2. `S1: ℬ(X1×X1)` — отношение; порядок пары описан в `convention`.
29
+ 2. `S1: ℬ(X1×X1)` — отношение; предметное пояснение в `convention`.
38
30
  3. `D# := Pr1(S1)`, `D# := Pr2(S1)` — именованные компоненты.
39
- 4. Сложные термы строятся поверх этих `D#`.
31
+ 4. Сложные термы строятся поверх этих `D#` и `S#`.
32
+
33
+ Если повторяется цепочка вроде `Pr2(Fi1[D](S7))`, введи промежуточный терм или функцию `F#`.
34
+
35
+ ## Подход relation-first
36
+
37
+ Используй при объединении нескольких исходных КС в одну предметную модель и при появлении длинных цепочек `∃d1…∃dn` в разных термах.
38
+
39
+ ### Семантическая лестница
40
+
41
+ Строй схему слоями; каждый следующий слой ссылается только на предыдущие:
42
+
43
+ | Слой | Роль | Что вводить |
44
+ | :--- | :--------------------- | :------------------------------------------------------------------------------------------- |
45
+ | 1 | Базис | `X#`, `C#` — пустой `definitionFormal`, смысл в `convention` / `definitionText` из источника |
46
+ | 2 | Структуры | `S#` — типизация `ℬ(…×…)` и конвенция на кортеж |
47
+ | 3 | Инварианты | `A#` — короткие ограничения (см. ниже про `card`) |
48
+ | 4 | Параметрический доступ | `F#` — «локальный API»: `[α∈…] Pr*(Fi*[…](S#))` |
49
+ | 5 | Центральное отношение | один `D#` (или `S#` с конвенцией), задающий полную траекторию синтеза |
50
+ | 6 | Витрина понятий | `D#` через `Pr*`, `Fi*`, `card`, `red`; узкие `F#` для аналитики |
51
+
52
+ ### Центральное отношение
53
+
54
+ Когда в тексте описан единый сценарий, зафиксируй его **одним** объектом:
55
+
56
+ ```text
57
+ D13 ::= I{(α, ξ1, τ, ξ2, β1, β2, ρ, ξ3) |
58
+ α∈S6; ξ1∈X2; τ∈F7[α,ξ1]; …; ξ3∈S3
59
+ }
60
+ ```
61
+
62
+ (Имена и арность — по предметной области; важна форма: кортеж + ограничения через уже введённые `F#` и `S#`.)
63
+
64
+ Далее можешь дать название необходимым частям кортежа с помощью `D#` через `Pr#`
65
+
66
+ ### Инварианты: `card` вместо длинных `∀`
67
+
68
+ Для функциональности отношения удобно:
69
+
70
+ ```text
71
+ card(S1) = card(Pr1,2(S1))
72
+ ```
73
+
74
+ Эквивалентно идее `∀d1,d2∈S1 ...`
75
+
76
+ Оставляй `∀`/`∃`, когда не получается заменить на теоретико-множественные и структурные конструкции.
40
77
 
41
- Если повторяется цепочка вроде `Pr2(Fi1[D](S7))`, введи промежуточный терм или уточни конвенцию/аксиому для `S7`.
78
+ ### Проекции вместо повторных кванторов
42
79
 
43
- ## Аксиомы
80
+ Если условие уже задано на `S#` или центральном `D#`, производный терм — это почти всегда:
44
81
 
45
- `A#` логическое требование к модели. Используй аксиомы, чтобы:
82
+ - `Prk(…)` / `Pri,j(…)`;
83
+ - `Fi*k[{…}](…)`;
84
+ - `D{ξ∈… | F[ξ] = …}` или `card(F[ξ]) = 1`.
46
85
 
47
- - фиксировать смысл `S#`;
48
- - задавать уникальность, тотальность, непересечение, порядок, область и диапазон;
49
- - оправдывать `debool(...)`: внутреннее множество должно быть гарантированно одноэлементным.
86
+ Перед тем как писать `D{x∈… | ∃d1∈… ∃d2∈…}`, проверь: нельзя ли выразить через `Pr` от уже введённого отношения.
50
87
 
51
88
  ## Проверка на маленькой модели
52
89
 
@@ -61,18 +98,19 @@
61
98
  - Атрибутивная экспликация не смешана с родоструктурной без явного запроса пользователя.
62
99
  - Не добавляй проверки принадлежности к собственной типизации: если `x` уже объявлен в `X1`, `x ∈ X1` избыточно.
63
100
  - Покрыты главные предметные сущности, роли, отношения и утверждения.
64
- - Слои идут так: `X#`/`C#` `S#` простые `D#` сложные `D#`/`F#`/`P#` → `A#`/`T#`.
65
- - У каждой аксиомы понятная цель.
101
+ - Повторяющиеся отборы вынесены в `F#`, а не размазаны по термам.
102
+ - У каждой аксиомы понятна цель.
66
103
  - Частые падения аксиом в модели указывают на ошибку данных или семантики схемы.
67
104
  - Сомнительные выражения проверены на маленькой КМ, если есть показательные тестовые данные.
68
105
 
69
106
  ## Рабочий порядок
70
107
 
71
- 1. Собери словарь предметной области.
72
- 2. Добавь `X#` и `C#` с конвенциями.
73
- 3. Добавь ключевые `S#` с типизацией и конвенцией.
74
- 4. Назови важные компоненты через `D#`: `Pr*`, `pr*`, `red`.
75
- 5. Добавляй выводимые `D#`, `F#`, `P#` маленькими шагами.
76
- 6. Добавь `A#` и `T#` по необходимости.
77
- 7. Перед upsert проверяй `analyzeExpression`.
78
- 8. Для сомнительной семантики собери маленькую КМ и вычисли ожидаемые значения.
108
+ 1. Собери словарь предметной области (базисы, ключевые отношения, сценарий синтеза).
109
+ 2. Добавь `X#` и `C#` с конвенциями из источника.
110
+ 3. Добавь базовые `S#` (трансформация, перевод, допускание, выбор, цели, субъекты).
111
+ 4. Добавь `A#` на структуры (`card`, покрытие `Pr1,2(S#)=…`, принадлежность выбора).
112
+ 5. Введи `F#` для типовых запросов.
113
+ 6. Производные понятия — `Pr*` / `Fi*` / `F#` от центрального `D#` и базовых `S#`.
114
+ 7. Узкие классификаторы (`для любой обстановки`, `для одного индивида`) — через `F#` и `card`/`=` с `X#`, не новые монолиты.
115
+ 8. Перед каждым upsert `analyzeExpression`.
116
+ 9. Для сомнительной семантики — маленькая КМ (`MODEL-TESTING.md`).
@@ -2,21 +2,23 @@
2
2
 
3
3
  Читай перед `addOrUpdateConstituenta`.
4
4
 
5
- ## Поля черновика
5
+ ## Поля
6
6
 
7
7
  - `id` — стабильный id внутри сессии.
8
8
  - `alias` — имя вида `X1`, `D5`, `F2`; префикс должен совпадать с `cstType`.
9
9
  - `cstType` — роль конституенты.
10
10
  - `definitionFormal` — формальное определение; для `basic` и `constant` строго `''`.
11
- - `term` — естественно-языковое имя.
12
- - `definitionText` — текстовая интерпретация формулы.
13
- - `convention` — соглашение для неопределяемого понятия.
11
+ - `term` — термин в естественном языке, используется в текстовых определениях. Если обозначаются элементы множества, то пишется с маленькой буквы во множественном числе. Иначе с большой буквы в единственном.
12
+ - `definitionText` — текстовое определение, соответствующее формальному определению. Для простых выражений не указывается если совпадает с термином. Каждый используемый термин должен быть введен в схеме.
13
+ - `convention` — соглашение для неопределяемого понятия. Может использовать термины, не определенные в схеме.
14
14
 
15
15
  Пропущенные текстовые поля сохраняются как `''`. Пиши `term`, `definitionText`, `convention` на одном языке: в языке схемы или, для новой схемы, в языке запроса.
16
16
 
17
+ Не добавляй точку в конце текстовых полей.
18
+
17
19
  ## `cstType`
18
20
 
19
- - `nominal` / `N#` — номиноид. В родоструктурной экспликации не используется.
21
+ - `nominal` / `N#` — номиноид. В родоструктурной экспликации и формальных определениях не используется.
20
22
  - `basic` / `X#` — базисное множество; формула пустая.
21
23
  - `constant` / `C#` — константное множество; формула пустая.
22
24
  - `structure` / `S#` — родовая структура; формула задает типизацию.
@@ -26,13 +28,13 @@
26
28
  - `axiom` / `A#` — аксиома; нужна типизация `Logic`.
27
29
  - `statement` / `T#` — высказывание; нужна типизация `Logic`.
28
30
 
29
- `basic`, `constant`, `structure` можно интерпретировать через `setConstituentaValue`. `term`, `axiom`, `statement` вычисляются и напрямую не задаются.
31
+ В модели `basic`, `constant`, `structure` можно интерпретировать через `setConstituentaValue`. `term`, `axiom`, `statement` вычисляются и напрямую не задаются.
30
32
 
31
- ## `S#` и `D#`
33
+ ## Различие родовой структуры и терма
32
34
 
33
- `S#` — неопределяемая родовая структура. `definitionFormal: 'ℬ(X1×X1)'` описывает ступень элемента: множество пар над `X1`.
35
+ `S#` — неопределяемое понятие - родовая структура. Пример: `definitionFormal: 'ℬ(X1×X1)'` описывает ступень элемента: множество пар над `X1`.
34
36
 
35
- `D#` — терм. `definitionFormal: 'X1×X1'` строит полный декартов продукт.
37
+ `D#` — производное понятие - терм. Пример: `definitionFormal: 'X1×X1'` строит полный декартов продукт.
36
38
 
37
39
  Для бинарного отношения обычно нужно:
38
40
 
@@ -28,4 +28,5 @@
28
28
 
29
29
  - Не парси HTML SPA.
30
30
  - Не переноси UI query/hash вроде `?tab=editor` в REST.
31
+ - Не запрашивай UI напрямую, используй преобразованные API запросы.
31
32
  - Не запрашивай `/details`, если нужны только метаданные.
@@ -29,16 +29,10 @@
29
29
 
30
30
  ## `AnalysisResult.type`
31
31
 
32
- `type` приходит как JSON анализатора: `Record<string, unknown> | null`.
33
-
34
- Правила:
35
-
36
32
  1. Сначала проверь `analysis.success === true` и `analysis.type !== null`.
37
33
  2. Не разбирай объект вручную; используй helpers из `@rsconcept/domain`.
38
34
  3. `valueClass` уточняет вычислимость: `Value`, `Property`, `Invalid`.
39
35
 
40
- Полезные API: `TypeID`, `TypePath`, `makeTypePath`, `parseTypeText(...)`.
41
-
42
36
  ## `S#` и `D#`
43
37
 
44
38
  - У `structure` (`S#`) `definitionFormal` читается как типизация. `ℬ(X1×X1)` описывает множество пар.
@@ -52,14 +46,14 @@
52
46
 
53
47
  Требуют подходящую ступень:
54
48
 
55
- - `red(S)` — нужно `S : (ℬ(H))`.
49
+ - `red(S)` — нужно `S : ℬℬ(H)`.
56
50
  - `debool(S)` — нужно одноэлементное множество.
57
51
  - `pr1(tuple)`, `Pr1(S)` — нужна достаточная арность.
58
- - `Fi1[D](S)` — `D` должен соответствовать выбранной проекции.
52
+ - `Fi1[a](S)` — `a` должен соответствовать выбранной проекции.
59
53
 
60
54
  ## Частые ошибки
61
55
 
62
56
  - `debool(S)` без гарантии синглетона.
63
57
  - `pr3((a, b))`: индекс вне арности.
64
- - `Fi1,2[D](S)`: параметр `D` не совпал с двумя проекциями.
58
+ - `Fi1,2[a](S)`: параметр `a` не совпал с двумя проекциями.
65
59
  - `A#` и `T#` не имеют `Logic`: будет `expectedLogic`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rsconcept/rstool",
3
- "version": "0.3.0",
3
+ "version": "0.5.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 and stdio wrapper.",
5
5
  "license": "MIT",
6
6
  "author": "IRBorisov",
@@ -92,6 +92,15 @@ const restored = tool.importSession(payload);
92
92
 
93
93
  Export includes session state and model values.
94
94
 
95
+ To create files the user can upload to an existing Portal object:
96
+
97
+ ```ts
98
+ const schemaJson = tool.exportPortalSchema(sessionId);
99
+ const modelJson = tool.exportPortalModel(sessionId);
100
+ ```
101
+
102
+ Use `schemaJson` on a schema page and `modelJson` on a model page via **Load from JSON**.
103
+
95
104
  ## Evaluation
96
105
 
97
106
  ```ts
@@ -153,6 +162,52 @@ if (!result.success || result.status !== EvalStatus.HAS_DATA || JSON.stringify(r
153
162
 
154
163
  Use this pattern for tests that protect important definitions. Full kinship model: `../../examples/build-kinship-rsmodel.ts`. More notes: `../../docs/MODEL-TESTING.md`.
155
164
 
165
+ ## Relation-first synthesis (layered KS)
166
+
167
+ Pattern for merging sub-schemas (transformation + transition + choice → stimulation). Reference: Portal `D01B03` / rsform `843`.
168
+
169
+ 1. **Structures** — one `S#` per mechanism, typification only:
170
+
171
+ ```text
172
+ S1: ℬ(X1×X2×X1) // transformation
173
+ S2: ℬ(X2×X3×X2) // transition
174
+ S4: ℬ(X2×X1×X3) // allowance (flat triple, not ℬ(X2×X1×ℬ(X3)))
175
+ S5: ℬ(X1×ℬ(X3)×X3) // choice
176
+ ```
177
+
178
+ 2. **Axioms** — short invariants:
179
+
180
+ ```text
181
+ A1: Pr1,2(S1) = X1×X2
182
+ A2: card(S1) = card(Pr1,2(S1))
183
+ A4: card(S5) = card(Pr1,2(S5))
184
+ A5: ∀d∈S5 pr3(d)∈pr2(d)
185
+ ```
186
+
187
+ 3. **Functions** — parameterized access (reuse everywhere):
188
+
189
+ ```text
190
+ F5[α,β] := Pr3(Fi1,2[{(β,α)}](S4)) // possible actions
191
+ F7[α,ξ] := F6[α, F5[α,ξ]] // chosen action in situation
192
+ ```
193
+
194
+ 4. **Central term** — one tuple relation, then projections:
195
+
196
+ ```text
197
+ D13 ::= I{(α,ξ1,τ,ξ2,β1,β2,ρ,ξ3) | α∈S6; ξ1∈X2; τ∈F7[α,ξ1]; …; ξ3∈S3}
198
+ D14 := Pr3(D13) // stimuli
199
+ D18 := Pr2(D13) // initial situations
200
+ ```
201
+
202
+ 5. **Classifiers** — filter via `F#`, not a new `∃` chain:
203
+
204
+ ```text
205
+ F8[α] := Pr2(Fi3[{α}](D13))
206
+ D22 := D{ξ∈D14 | F8[ξ] = X2} // stimulus valid in any situation
207
+ ```
208
+
209
+ Upsert in dependency order; run `analyzeExpression` on `I{…}` before committing the central `D#`.
210
+
156
211
  ## Common mistakes
157
212
 
158
213
  - `definitionFormal: 'Z'` on `basic` / `constant` → `definitionNotAllowed`.
@@ -160,6 +215,10 @@ Use this pattern for tests that protect important definitions. Full kinship mode
160
215
  - Wrong `cstType` in `analyzeExpression` → role-specific errors.
161
216
  - `term` with `X1×X1` for a relation → full Cartesian product, not relation typification.
162
217
  - `structure` with `Pr1(S1)` → wrong role; projections belong on `term` / `function`.
218
+ - Same long `∃d1…∃dn` chain in many `D#` → define one central `D#` and use `Pr*` / `F#`.
219
+ - `S4: ℬ(X2×X1×ℬ(X3))` when you only need «individual allows actions» → prefer `ℬ(X2×X1×X3)` + `F5`.
220
+ - `∀x∈A, ∀y∈B` → invalid; nest: `∀x∈A (∀y∈B (…))`.
221
+ - Functional relation axiom as huge `∀⇒` → prefer `card(S)=card(Pr1,2(S))` when equivalent.
163
222
  - `setConstituentaValue` on `term`, `axiom`, or `statement` → cannot set computed constituents directly.
164
223
  - Evaluation before base bindings → missing value, empty result, or evaluation failure.
165
224
 
@@ -29,6 +29,8 @@ Paths are relative to this file.
29
29
 
30
30
  ## Workflow
31
31
 
32
+ Use this when editing or checking schemas and models.
33
+
32
34
  1. `createSession`.
33
35
  2. Add `basic` (`X#`) and `constant` (`C#`) with `definitionFormal: ''`.
34
36
  3. Add dependencies before dependents.
@@ -39,26 +41,7 @@ Paths are relative to this file.
39
41
  8. Set base/model values with `setConstituentaValue(s)`.
40
42
  9. Evaluate with `evaluateExpression`, `evaluateConstituenta`, or `recalculateModel`.
41
43
  10. Persist with `exportSession` / `importSession`.
42
-
43
- ## Portal REST
44
-
45
- rstool never calls Portal REST itself. Fetch live data outside rstool, then import constituents with `addOrUpdateConstituenta`.
46
-
47
- - UI host: `https://portal.acconcept.ru`.
48
- - API host: `https://api.portal.acconcept.ru`.
49
- - Useful reads: `/api/rsforms/{id}`, `/api/rsforms/{id}/details`, `/api/library/{id}/versions/{v}`, `/api/oss/{id}`, `/api/models/{id}`, `/schema`.
50
- - Do not scrape SPA HTML or reuse UI query params like `?tab=`.
51
-
52
- ## Syntax Cheatsheet
53
-
54
- - Globals: `X1`, `C1`, `S1`, `D1`, `F1`, `P1`, `A1`, `T1`, `N1`, `R1`.
55
- - Locals: `x`, `ξ`, `μ2`.
56
- - Literals: `42`, `Z`, `∅`.
57
- - Set expressions: `∪`, `∩`, `\`, `∆`, `×`, `ℬ(...)`, tuples, `Pr*`, `Fi*`.
58
- - Logic: `¬`, `&`, `∨`, `⇒`, `⇔`, `∀`, `∃`, `=`, `≠`, `<`, `∈`, `⊆`.
59
- - Parameterized expressions: `[arg1∈H1, arg2∈H2] body`.
60
-
61
- Read tool output; do not infer types by inspection.
44
+ 11. For user-uploadable Portal files, use `exportPortalSchema` for schema JSON or `exportPortalModel` for model JSON.
62
45
 
63
46
  ## Diagnostics Loop
64
47
 
@@ -75,19 +58,11 @@ Read tool output; do not infer types by inspection.
75
58
  3. Derived constituents in topological order.
76
59
  4. Axioms and statements after their references.
77
60
 
78
- ## Natural-Language Fields
79
-
80
- Keep `term`, `definitionText`, and `convention` in one language.
81
-
82
- - Extending a schema: use the schema's existing language.
83
- - New schema: use the user's request language.
84
-
85
61
  ## Checklist
86
62
 
87
63
  - [ ] `sessionId` tracked.
88
- - [ ] `basic` / `constant` formals are empty.
89
- - [ ] Dependencies exist before upsert.
90
64
  - [ ] `cstType` matches the role.
65
+ - [ ] Check schema and fix errors before showing result.
91
66
  - [ ] Diagnostics handled before commit/export.
92
- - [ ] Ambiguous semantics checked on a small model when data examples are available.
67
+ - [ ] Ambiguous semantics checked on a small model.
93
68
  - [ ] Base values set before evaluation.
@@ -3,7 +3,7 @@
3
3
  ## rstool contract
4
4
 
5
5
  - Package: `@rsconcept/rstool`
6
- - Contract version: `1.2.0` (`CONTRACT_VERSION`)
6
+ - Contract version: `1.4.0` (`CONTRACT_VERSION`)
7
7
  - Core class: `RSToolAgent`
8
8
  - Public imports: `@rsconcept/rstool` and `@rsconcept/rstool/wrapper`
9
9
 
@@ -18,6 +18,8 @@
18
18
  | `listDiagnostics(sessionId, filters?)` | Accumulated diagnostics; optional `constituentId` filter |
19
19
  | `commitStep(sessionId, message?)` | Record revision checkpoint |
20
20
  | `exportSession(sessionId)` | JSON string `{ contractVersion, state, diagnostics }` |
21
+ | `exportPortalSchema(sessionId)` | Portal schema import JSON string using versioned schema shape |
22
+ | `exportPortalModel(sessionId)` | Portal model import JSON string using versioned model values shape |
21
23
  | `importSession(payload)` | New session from export |
22
24
  | `setConstituentaValue(sessionId, { target, type?, value })` | Set one base binding or structured value → `SessionModelState` |
23
25
  | `setConstituentaValues(sessionId, { items })` | Batch set values → `SessionModelState` |
@@ -43,6 +45,20 @@
43
45
 
44
46
  Omitted text fields default to `''` in stored state.
45
47
 
48
+ ### `SessionState` metadata
49
+
50
+ Set on `createSession(initial?)` or via `importSession`:
51
+
52
+ ```ts
53
+ {
54
+ alias: string; // library item alias
55
+ title: string; // display title
56
+ comment: string; // developer notes
57
+ }
58
+ ```
59
+
60
+ All default to `''` when omitted.
61
+
46
62
  ### Model and evaluation types
47
63
 
48
64
  ```ts
@@ -69,7 +85,7 @@ Base/constant bindings use `type: "basic"` and `value: { "0": "label", … }`. S
69
85
 
70
86
  Process: `npx rstool-wrapper`
71
87
 
72
- 1. **Ready** (no request): `{"id":null,"ok":true,"result":{"ready":true,"wrapper":"rstool-stdio","contractVersion":"1.2.0"}}`
88
+ 1. **Ready** (no request): `{"id":null,"ok":true,"result":{"ready":true,"wrapper":"rstool-stdio","contractVersion":"1.4.0"}}`
73
89
  2. **Request**: `{"id":"<unique>","method":"<name>","params":{...}}`
74
90
  3. **Response**: `{"id":"<same>","ok":true,"result":...}` or `{"id":"...","ok":false,"error":{"code":"...","message":"..."}}`
75
91
 
@@ -85,6 +101,8 @@ Example chain:
85
101
  {"id":"4","method":"listDiagnostics","params":{"sessionId":"…"}}
86
102
  {"id":"5","method":"commitStep","params":{"sessionId":"…","message":"checkpoint"}}
87
103
  {"id":"6","method":"exportSession","params":{"sessionId":"…"}}
104
+ {"id":"6a","method":"exportPortalSchema","params":{"sessionId":"…"}}
105
+ {"id":"6b","method":"exportPortalModel","params":{"sessionId":"…"}}
88
106
  {"id":"7","method":"setConstituentaValue","params":{"sessionId":"…","input":{"target":1,"value":{"0":"a","1":"b"}}}}
89
107
  {"id":"8","method":"evaluateExpression","params":{"sessionId":"…","input":{"expression":"1+2","cstType":"term"}}}
90
108
  {"id":"9","method":"evaluateConstituenta","params":{"sessionId":"…","input":{"constituentId":3}}}
@@ -109,7 +127,7 @@ interface AnalysisResult {
109
127
  - **Term graph**: directed dependencies between constituenta via alias references in definitions.
110
128
  - **`S#` vs `D#`**: same `×` token — in `ℬ(X1×X1)` on `S#` it forms a **grade** (pair type); in `X1×X1` on `D#` it is the **Cartesian product** (all pairs). Relations: `S#` + `convention`, then derived `D#` (`Pr1(S1)`, …).
111
129
 
112
- Intro (help): language is FOL-based; set vs logic expression split; parameterized templates for term/predicate functions; structural expressions reshape stages.
130
+ Intro (help): language is FOL-based; set vs logic expression split; parameterized templates for term/predicate functions.
113
131
 
114
132
  ## Grammar tokens (selected)
115
133
 
@@ -134,15 +152,15 @@ Standalone agents should consult the bundled distilled docs (`docs/*.md` inside
134
152
 
135
153
  | Topic | Bundled doc |
136
154
  | ------------------------------------ | ------------------------------------------ |
137
- | Identifiers, literals | `docs/SYNTAX.md` § *Identifier rules* |
155
+ | Identifiers, literals | `docs/SYNTAX.md` § _Identifier rules_ |
138
156
  | Grades, `Logic`, parameterized types | `docs/TYPIFICATION.md` |
139
- | Logical expressions | `docs/SYNTAX.md` § *Logical expressions* |
140
- | Set operators | `docs/SYNTAX.md` § *Set-theoretic* |
141
- | Integer arithmetic | `docs/SYNTAX.md` § *Arithmetic* |
142
- | Structural / typification reshaping | `docs/TYPIFICATION.md` § *Forming/derived* |
143
- | Quantifiers | `docs/SYNTAX.md` § *Quantifiers* |
144
- | Parameterized functions, templates | `docs/SYNTAX.md` § *Parameterised* |
145
- | Correctness / validation mindset | `docs/SYNTAX.md` § *Correctness model* |
157
+ | Logical expressions | `docs/SYNTAX.md` § _Logical expressions_ |
158
+ | Set operators | `docs/SYNTAX.md` § _Set-theoretic_ |
159
+ | Integer arithmetic | `docs/SYNTAX.md` § _Arithmetic_ |
160
+ | Structural / typification reshaping | `docs/TYPIFICATION.md` § _Forming/derived_ |
161
+ | Quantifiers | `docs/SYNTAX.md` § _Quantifiers_ |
162
+ | Parameterized functions, templates | `docs/SYNTAX.md` § _Parameterised_ |
163
+ | Correctness / validation mindset | `docs/SYNTAX.md` § _Correctness model_ |
146
164
  | Definition semantic tests | `docs/MODEL-TESTING.md` |
147
165
  | Domain vocabulary | `docs/DOMAIN.md` |
148
166
  | Constituent fields and ordering | `docs/CONSTITUENTA.md` |
@@ -167,6 +185,19 @@ Categories:
167
185
 
168
186
  `exportSession(sessionId)` returns a JSON string with `{ contractVersion, state, diagnostics }`.
169
187
 
188
+ - `state.alias`, `state.title`, `state.comment` — library-item metadata for Portal export (`comment` → JSON `description`).
170
189
  - `state.items[]` contains each constituent with `id`, `alias`, `cstType`, `definitionFormal`, optional text fields, and nested analysis output.
171
190
  - `state.model.items[]` is present when interpretation values have been set.
172
191
  - `diagnostics[]` contains accumulated diagnostics with offsets and codes.
192
+
193
+ ## Portal import JSON
194
+
195
+ For **Load from JSON** on an existing Portal schema or model:
196
+
197
+ - `exportPortalSchema(sessionId)` — schema file
198
+ - `exportPortalModel(sessionId)` — model file
199
+
200
+ Both return `contract_version` `1.0.0` plus required `title`, `alias`, `description`, and `items`. Schema files may include `attribution`. Values come from `state.title`, `state.alias`, and `state.comment` (empty fields fall back to `Conceptual schema` / `SCHEMA` or `Conceptual model` / `MODEL` and `""`).
201
+
202
+ - Schema `items[]`: versioned constituent fields (`cst_type`, `definition_formal`, `term_raw`, …).
203
+ - Model `items[]`: `{ id, type, value }` per binding.
package/src/index.ts CHANGED
@@ -25,6 +25,12 @@ export {
25
25
  type EvaluationResult,
26
26
  type ListDiagnosticsFilters,
27
27
  type ModelValueState,
28
+ PORTAL_JSON_CONTRACT_VERSION,
29
+ type PortalImportMetadata,
30
+ type PortalModelImportData,
31
+ type PortalSchemaConstituenta,
32
+ type PortalSchemaImportData,
33
+ type PortalTermForm,
28
34
  type RecalculateModelResult,
29
35
  type RSToolAgentContract,
30
36
  type RSToolErrorDescription,
@@ -28,6 +28,14 @@ export {
28
28
  type SetConstituentaValueInput,
29
29
  type SetConstituentaValuesInput
30
30
  } from './model-value';
31
+ export {
32
+ PORTAL_JSON_CONTRACT_VERSION,
33
+ type PortalImportMetadata,
34
+ type PortalModelImportData,
35
+ type PortalSchemaConstituenta,
36
+ type PortalSchemaImportData,
37
+ type PortalTermForm
38
+ } from './portal-json';
31
39
  export { RSToolAgent } from './rstool-agent';
32
40
  export { type SessionHandle, type SessionRevision, type SessionState } from './session';
33
41
  export { CONTRACT_VERSION, type RSToolAgentContract } from './tool-contract';
@@ -0,0 +1,45 @@
1
+ import { type BasicBinding, type RSToolValue } from './common';
2
+
3
+ /** Portal JSON import/export format version (schema and model files). */
4
+ export const PORTAL_JSON_CONTRACT_VERSION = '1.0.0';
5
+
6
+ export interface PortalImportMetadata {
7
+ contract_version: string;
8
+ title: string;
9
+ alias: string;
10
+ description: string;
11
+ }
12
+
13
+ export interface PortalTermForm {
14
+ text: string;
15
+ tags: string;
16
+ }
17
+
18
+ export interface PortalSchemaConstituenta {
19
+ id: number;
20
+ alias: string;
21
+ convention: string;
22
+ crucial: boolean;
23
+ cst_type: string;
24
+ definition_formal: string;
25
+ typification_manual: string;
26
+ value_is_property: boolean;
27
+ definition_raw: string;
28
+ definition_resolved: string;
29
+ term_raw: string;
30
+ term_resolved: string;
31
+ term_forms: PortalTermForm[];
32
+ }
33
+
34
+ export interface PortalSchemaImportData extends PortalImportMetadata {
35
+ items: PortalSchemaConstituenta[];
36
+ attribution: Array<{ container: number; attribute: number }>;
37
+ }
38
+
39
+ export interface PortalModelImportData extends PortalImportMetadata {
40
+ items: Array<{
41
+ id: number;
42
+ type: string;
43
+ value: RSToolValue | BasicBinding;
44
+ }>;
45
+ }