@rsconcept/rstool 1.7.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/README.md +7 -7
  2. package/dist/index.js +1 -1
  3. package/dist/mappers/model-adapter.d.ts +6 -2
  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.d.ts +1 -2
  7. package/dist/mappers/schema-adapter.js +1 -1
  8. package/dist/mappers/types.d.ts +4 -5
  9. package/dist/models/index.js +1 -1
  10. package/dist/models/rstool-agent.js +1 -2
  11. package/dist/{models-DG2uTaV_.js → models-D06g8LId.js} +6 -5
  12. package/dist/{models-DG2uTaV_.js.map → models-D06g8LId.js.map} +1 -1
  13. package/dist/{rsform-builder-DKwZfJvN.js → rsform-builder-BlXEe5Ow.js} +2 -2
  14. package/dist/{rsform-builder-DKwZfJvN.js.map → rsform-builder-BlXEe5Ow.js.map} +1 -1
  15. package/dist/session/session-store.d.ts +3 -3
  16. package/dist/session/session-store.js +1 -2
  17. package/dist/wrapper/client.d.ts +15 -9
  18. package/dist/wrapper/client.js +79 -12
  19. package/dist/wrapper/client.js.map +1 -1
  20. package/dist/wrapper/stdio-wrapper.d.ts +1 -1
  21. package/dist/wrapper/stdio-wrapper.js +18 -10
  22. package/dist/wrapper/stdio-wrapper.js.map +1 -1
  23. package/docs/BRIEF.md +93 -0
  24. package/docs/CONCEPTUAL-SCHEMA.md +17 -2
  25. package/docs/CONSTRUCTIONS.md +384 -0
  26. package/docs/DIAGNOSTICS.md +9 -8
  27. package/docs/DOMAIN.md +12 -0
  28. package/docs/METHOD.md +208 -0
  29. package/docs/MODEL-TESTING.md +48 -0
  30. package/docs/PORTAL-API.md +38 -285
  31. package/docs/PORTAL-MODELS.md +24 -0
  32. package/docs/PORTAL-OSS.md +56 -0
  33. package/docs/PORTAL-PUBLISH.md +39 -0
  34. package/docs/PORTAL-READ.md +301 -0
  35. package/docs/README.md +8 -4
  36. package/docs/REQUIREMENTS.md +61 -0
  37. package/docs/SYNTAX.md +5 -4
  38. package/docs/TYPIFICATION.md +12 -3
  39. package/docs/brief.schema.json +173 -0
  40. package/examples/README.md +16 -2
  41. package/examples/access-control/NOTES.md +23 -0
  42. package/examples/access-control/anti/collapsed.json +439 -0
  43. package/examples/access-control/anti/weakened.json +439 -0
  44. package/examples/access-control/brief-v1.json +231 -0
  45. package/examples/access-control/brief.json +310 -0
  46. package/examples/access-control/build-rsform.ts +151 -0
  47. package/examples/access-control/requirements-v1.md +9 -0
  48. package/examples/access-control/requirements-v2.md +4 -0
  49. package/examples/access-control/rsform-session-v1.json +439 -0
  50. package/examples/access-control/rsform-session.json +523 -0
  51. package/examples/audit-diagnostics.ts +9 -1
  52. package/examples/briefs.test.ts +126 -0
  53. package/examples/clinic-booking/NOTES.md +24 -0
  54. package/examples/clinic-booking/anti/collapsed.json +615 -0
  55. package/examples/clinic-booking/anti/species-as-genus.json +568 -0
  56. package/examples/clinic-booking/brief-v1.json +332 -0
  57. package/examples/clinic-booking/brief.json +405 -0
  58. package/examples/clinic-booking/build-rsform.ts +174 -0
  59. package/examples/clinic-booking/requirements-v1.md +9 -0
  60. package/examples/clinic-booking/requirements-v2.md +4 -0
  61. package/examples/clinic-booking/rsform-session-v1.json +615 -0
  62. package/examples/clinic-booking/rsform-session.json +700 -0
  63. package/examples/diagnostics-utils.ts +26 -0
  64. package/examples/kinship/brief.json +337 -0
  65. package/examples/kinship/build-rsform.ts +7 -4
  66. package/examples/kinship/rsform-session.json +20 -63
  67. package/examples/kinship/rsmodel-session.json +14 -14
  68. package/examples/kinship-subordination/NOTES.md +49 -0
  69. package/examples/kinship-subordination/brief.json +161 -0
  70. package/examples/kinship-subordination/build-rsform.ts +100 -0
  71. package/examples/kinship-subordination/rsform-session.json +795 -0
  72. package/examples/library-loans/NOTES.md +46 -0
  73. package/examples/library-loans/anti/collapsed.json +481 -0
  74. package/examples/library-loans/anti/species-as-genus.json +334 -0
  75. package/examples/library-loans/anti/uncovered.json +406 -0
  76. package/examples/library-loans/anti/weakened.json +464 -0
  77. package/examples/library-loans/brief-v1.json +340 -0
  78. package/examples/library-loans/brief.json +502 -0
  79. package/examples/library-loans/build-rsform.ts +239 -0
  80. package/examples/library-loans/requirements-v1.md +11 -0
  81. package/examples/library-loans/requirements-v2.md +5 -0
  82. package/examples/library-loans/rsform-session-v1.json +481 -0
  83. package/examples/library-loans/rsform-session.json +652 -0
  84. package/examples/library-loans/source-markup.md +18 -0
  85. package/examples/movd/brief.json +220 -0
  86. package/examples/movd/build-rsform.ts +5 -2
  87. package/examples/movd/rsform-session.json +14 -46
  88. package/examples/subordination/NOTES.md +59 -0
  89. package/examples/subordination/anti/collapsed.json +556 -0
  90. package/examples/subordination/anti/single-relation.json +125 -0
  91. package/examples/subordination/anti/transitive.json +573 -0
  92. package/examples/subordination/anti/weakened.json +539 -0
  93. package/examples/subordination/brief.json +386 -0
  94. package/examples/subordination/build-rsform.ts +63 -0
  95. package/examples/subordination/constants.ts +115 -0
  96. package/examples/subordination/rsform-session.json +556 -0
  97. package/examples/subordination/source-markup.md +19 -0
  98. package/examples/subordination/source.md +40 -0
  99. package/package.json +29 -20
  100. package/skills/INSTALL.md +28 -29
  101. package/skills/README.md +25 -10
  102. package/skills/rs-core/SKILL.md +56 -0
  103. package/skills/rs-explain/SKILL.md +28 -0
  104. package/skills/rs-explicate/SKILL.md +71 -0
  105. package/skills/rs-interpret/SKILL.md +67 -0
  106. package/skills/rs-portal/SKILL.md +51 -0
  107. package/skills/rs-review/SKILL.md +79 -0
  108. package/skills/rs-scope/SKILL.md +67 -0
  109. package/skills/rs-synthesis/SKILL.md +52 -0
  110. package/skills/rstool/SKILL.md +70 -0
  111. package/skills/rstool-helper/GUIDE.md +18 -272
  112. package/skills/rstool-helper/SKILL.md +8 -55
  113. package/skills/{rstool-helper → rstool-runtime}/EXAMPLES.md +40 -12
  114. package/skills/{rstool-helper → rstool-runtime}/REFERENCE.md +28 -7
  115. package/skills/rstool-runtime/SKILL.md +96 -0
  116. package/skills/scripts/brief-check.test.ts +165 -0
  117. package/skills/scripts/brief-check.ts +826 -0
  118. package/skills/scripts/check-brief.ts +94 -0
  119. package/skills/scripts/rstool-skills.mjs +119 -0
  120. package/skills/scripts/skill-stubs.test.ts +48 -0
  121. package/src/mappers/model-adapter.ts +34 -1
  122. package/src/models/rstool-agent.test.ts +95 -0
  123. package/src/wrapper/client.test.ts +43 -4
  124. package/src/wrapper/client.ts +95 -16
  125. package/src/wrapper/stdio-handler.test.ts +43 -0
  126. package/src/wrapper/stdio-handler.ts +19 -5
@@ -0,0 +1,523 @@
1
+ {
2
+ "contractVersion": "3.3.0",
3
+ "state": {
4
+ "sessionId": "b3bb9a66-a290-4690-b16b-8b1c6b757839",
5
+ "alias": "RBAC",
6
+ "title": "Ролевой доступ",
7
+ "comment": "Ролевое управление доступом. Эксплицировать роли, иерархию и эффективные права для проектирования подсистемы доступа и проверок при назначении ролей.\nL1. Исключено: журнал изменений и сроки хранения (п. 6); невыразимо: кто и когда выдал право, права на прошлую дату.\nL2. Исключено: аутентификация (п. 7); невыразимо: способ входа, учётная запись SSO.\nL3. Исключено: ресурсы как объекты: право — неделимый элемент; невыразимо: права на конкретный документ.\nDC1. иерархия ролей: отношение S3 — п. 2; роль может входить в несколько старших — дерево избыточно ограничивает.\nDC2. права пользователя: вывод через роли (F5, F6) — права пользователя не задаются отдельно — иначе разойдутся с ролями.\nDC3. разделение обязанностей: по эффективным ролям (A2) — п. 4: «в том числе через иерархию».\nDC4. симметричность несовместимости: без аксиомы — A2 запрещает пару в любом порядке; достаточно записать пару один раз.\nDC5. ацикличность иерархии: аксиома A1 через замыкание F1 — п. 2.\nDC6. прямые роли с временными назначениями: F2 включает временные роли с действующим периодом — v2 п. 1; без временных назначений совпадает с v1.\nDC7. временное назначение: S5 (пользователь, роль, первый день, последний день) и текущий день S6 — S1 и сценарии v1 не меняются; E6 — родовая структура по DC7.",
8
+ "createdAt": "2026-10-25T18:34:35.438Z",
9
+ "updatedAt": "2026-10-25T18:34:35.450Z",
10
+ "revisions": [
11
+ {
12
+ "revisionId": "9f9ac1f9-a45e-4f3c-9b89-26578542e186",
13
+ "at": "2026-10-25T18:34:35.445Z",
14
+ "message": "Ролевой доступ: шаг 1"
15
+ },
16
+ {
17
+ "revisionId": "bd67960d-38bf-4eb7-bf83-4e3ee8c29f80",
18
+ "at": "2026-10-25T18:34:35.450Z",
19
+ "message": "Ролевой доступ: шаг 2"
20
+ }
21
+ ],
22
+ "items": [
23
+ {
24
+ "id": 1,
25
+ "alias": "X1",
26
+ "cstType": "basic",
27
+ "definitionFormal": "",
28
+ "term": "пользователи",
29
+ "definitionText": "",
30
+ "convention": "Учётные записи пользователей системы.",
31
+ "analysis": {
32
+ "success": true,
33
+ "type": {
34
+ "typeID": 5,
35
+ "base": {
36
+ "typeID": 3,
37
+ "baseID": "X1"
38
+ }
39
+ },
40
+ "valueClass": "value",
41
+ "diagnostics": []
42
+ }
43
+ },
44
+ {
45
+ "id": 2,
46
+ "alias": "X2",
47
+ "cstType": "basic",
48
+ "definitionFormal": "",
49
+ "term": "роли",
50
+ "definitionText": "",
51
+ "convention": "Роли доступа (администратор, редактор, …).",
52
+ "analysis": {
53
+ "success": true,
54
+ "type": {
55
+ "typeID": 5,
56
+ "base": {
57
+ "typeID": 3,
58
+ "baseID": "X2"
59
+ }
60
+ },
61
+ "valueClass": "value",
62
+ "diagnostics": []
63
+ }
64
+ },
65
+ {
66
+ "id": 3,
67
+ "alias": "X3",
68
+ "cstType": "basic",
69
+ "definitionFormal": "",
70
+ "term": "права",
71
+ "definitionText": "",
72
+ "convention": "Элементарные права: действие над видом ресурса (чтение документов, …).",
73
+ "analysis": {
74
+ "success": true,
75
+ "type": {
76
+ "typeID": 5,
77
+ "base": {
78
+ "typeID": 3,
79
+ "baseID": "X3"
80
+ }
81
+ },
82
+ "valueClass": "value",
83
+ "diagnostics": []
84
+ }
85
+ },
86
+ {
87
+ "id": 4,
88
+ "alias": "S1",
89
+ "cstType": "structure",
90
+ "definitionFormal": "ℬ(X1×X2)",
91
+ "term": "назначения ролей",
92
+ "definitionText": "",
93
+ "convention": "Пара (пользователь, роль): роль назначена пользователю напрямую.",
94
+ "analysis": {
95
+ "success": true,
96
+ "type": {
97
+ "typeID": 5,
98
+ "base": {
99
+ "typeID": 4,
100
+ "factors": [
101
+ {
102
+ "typeID": 3,
103
+ "baseID": "X1"
104
+ },
105
+ {
106
+ "typeID": 3,
107
+ "baseID": "X2"
108
+ }
109
+ ]
110
+ }
111
+ },
112
+ "valueClass": "value",
113
+ "diagnostics": []
114
+ }
115
+ },
116
+ {
117
+ "id": 5,
118
+ "alias": "S2",
119
+ "cstType": "structure",
120
+ "definitionFormal": "ℬ(X2×X3)",
121
+ "term": "права роли",
122
+ "definitionText": "",
123
+ "convention": "Пара (роль, право): право дано роли напрямую.",
124
+ "analysis": {
125
+ "success": true,
126
+ "type": {
127
+ "typeID": 5,
128
+ "base": {
129
+ "typeID": 4,
130
+ "factors": [
131
+ {
132
+ "typeID": 3,
133
+ "baseID": "X2"
134
+ },
135
+ {
136
+ "typeID": 3,
137
+ "baseID": "X3"
138
+ }
139
+ ]
140
+ }
141
+ },
142
+ "valueClass": "value",
143
+ "diagnostics": []
144
+ }
145
+ },
146
+ {
147
+ "id": 6,
148
+ "alias": "S3",
149
+ "cstType": "structure",
150
+ "definitionFormal": "ℬ(X2×X2)",
151
+ "term": "иерархия ролей",
152
+ "definitionText": "",
153
+ "convention": "Пара (старшая, младшая): старшая роль включает права младшей.",
154
+ "analysis": {
155
+ "success": true,
156
+ "type": {
157
+ "typeID": 5,
158
+ "base": {
159
+ "typeID": 4,
160
+ "factors": [
161
+ {
162
+ "typeID": 3,
163
+ "baseID": "X2"
164
+ },
165
+ {
166
+ "typeID": 3,
167
+ "baseID": "X2"
168
+ }
169
+ ]
170
+ }
171
+ },
172
+ "valueClass": "value",
173
+ "diagnostics": []
174
+ }
175
+ },
176
+ {
177
+ "id": 7,
178
+ "alias": "S4",
179
+ "cstType": "structure",
180
+ "definitionFormal": "ℬ(X2×X2)",
181
+ "term": "несовместимые роли",
182
+ "definitionText": "",
183
+ "convention": "Пара ролей, которые нельзя иметь одному пользователю (разделение обязанностей).",
184
+ "analysis": {
185
+ "success": true,
186
+ "type": {
187
+ "typeID": 5,
188
+ "base": {
189
+ "typeID": 4,
190
+ "factors": [
191
+ {
192
+ "typeID": 3,
193
+ "baseID": "X2"
194
+ },
195
+ {
196
+ "typeID": 3,
197
+ "baseID": "X2"
198
+ }
199
+ ]
200
+ }
201
+ },
202
+ "valueClass": "value",
203
+ "diagnostics": []
204
+ }
205
+ },
206
+ {
207
+ "id": 8,
208
+ "alias": "F1",
209
+ "cstType": "function",
210
+ "definitionFormal": "[ρ∈X2] R{σ:=Pr2(Fi1[{ρ}](S3)) | σ∪Pr2(Fi1[σ](S3))}",
211
+ "term": "младшие роли",
212
+ "definitionText": "Роли, которые данная роль включает напрямую или через цепочку.",
213
+ "convention": "",
214
+ "analysis": {
215
+ "success": true,
216
+ "type": {
217
+ "typeID": 7,
218
+ "result": {
219
+ "typeID": 5,
220
+ "base": {
221
+ "typeID": 3,
222
+ "baseID": "X2"
223
+ }
224
+ },
225
+ "args": [
226
+ {
227
+ "alias": "ρ",
228
+ "type": {
229
+ "typeID": 3,
230
+ "baseID": "X2"
231
+ }
232
+ }
233
+ ]
234
+ },
235
+ "valueClass": "value",
236
+ "diagnostics": []
237
+ }
238
+ },
239
+ {
240
+ "id": 9,
241
+ "alias": "F2",
242
+ "cstType": "function",
243
+ "definitionFormal": "[ξ∈X1] Pr2(Fi1[{ξ}](S1)) ∪ I{pr2(τ) | τ:∈Fi1[{ξ}](S5); pr3(τ)≤S6; S6≤pr4(τ)}",
244
+ "term": "прямые роли",
245
+ "definitionText": "Роли, назначенные пользователю напрямую: постоянно или временно с действующим сегодня периодом.",
246
+ "convention": "",
247
+ "analysis": {
248
+ "success": true,
249
+ "type": {
250
+ "typeID": 7,
251
+ "result": {
252
+ "typeID": 5,
253
+ "base": {
254
+ "typeID": 3,
255
+ "baseID": "X2"
256
+ }
257
+ },
258
+ "args": [
259
+ {
260
+ "alias": "ξ",
261
+ "type": {
262
+ "typeID": 3,
263
+ "baseID": "X1"
264
+ }
265
+ }
266
+ ]
267
+ },
268
+ "valueClass": "value",
269
+ "diagnostics": []
270
+ }
271
+ },
272
+ {
273
+ "id": 10,
274
+ "alias": "F3",
275
+ "cstType": "function",
276
+ "definitionFormal": "[ξ∈X1] red(I{F1[ρ] | ρ:∈F2[ξ]})\\F2[ξ]",
277
+ "term": "унаследованные роли",
278
+ "definitionText": "Роли, которые пользователь получает только через иерархию.",
279
+ "convention": "",
280
+ "analysis": {
281
+ "success": true,
282
+ "type": {
283
+ "typeID": 7,
284
+ "result": {
285
+ "typeID": 5,
286
+ "base": {
287
+ "typeID": 3,
288
+ "baseID": "X2"
289
+ }
290
+ },
291
+ "args": [
292
+ {
293
+ "alias": "ξ",
294
+ "type": {
295
+ "typeID": 3,
296
+ "baseID": "X1"
297
+ }
298
+ }
299
+ ]
300
+ },
301
+ "valueClass": "value",
302
+ "diagnostics": []
303
+ }
304
+ },
305
+ {
306
+ "id": 11,
307
+ "alias": "F4",
308
+ "cstType": "function",
309
+ "definitionFormal": "[ξ∈X1] F2[ξ]∪F3[ξ]",
310
+ "term": "эффективные роли",
311
+ "definitionText": "Прямые и унаследованные роли пользователя.",
312
+ "convention": "",
313
+ "analysis": {
314
+ "success": true,
315
+ "type": {
316
+ "typeID": 7,
317
+ "result": {
318
+ "typeID": 5,
319
+ "base": {
320
+ "typeID": 3,
321
+ "baseID": "X2"
322
+ }
323
+ },
324
+ "args": [
325
+ {
326
+ "alias": "ξ",
327
+ "type": {
328
+ "typeID": 3,
329
+ "baseID": "X1"
330
+ }
331
+ }
332
+ ]
333
+ },
334
+ "valueClass": "value",
335
+ "diagnostics": []
336
+ }
337
+ },
338
+ {
339
+ "id": 12,
340
+ "alias": "F5",
341
+ "cstType": "function",
342
+ "definitionFormal": "[ξ∈X1] Pr2(Fi1[F2[ξ]](S2))",
343
+ "term": "назначенные права",
344
+ "definitionText": "Права прямых ролей пользователя.",
345
+ "convention": "",
346
+ "analysis": {
347
+ "success": true,
348
+ "type": {
349
+ "typeID": 7,
350
+ "result": {
351
+ "typeID": 5,
352
+ "base": {
353
+ "typeID": 3,
354
+ "baseID": "X3"
355
+ }
356
+ },
357
+ "args": [
358
+ {
359
+ "alias": "ξ",
360
+ "type": {
361
+ "typeID": 3,
362
+ "baseID": "X1"
363
+ }
364
+ }
365
+ ]
366
+ },
367
+ "valueClass": "value",
368
+ "diagnostics": []
369
+ }
370
+ },
371
+ {
372
+ "id": 13,
373
+ "alias": "F6",
374
+ "cstType": "function",
375
+ "definitionFormal": "[ξ∈X1] Pr2(Fi1[F4[ξ]](S2))",
376
+ "term": "эффективные права",
377
+ "definitionText": "Права всех ролей пользователя, включая унаследованные.",
378
+ "convention": "",
379
+ "analysis": {
380
+ "success": true,
381
+ "type": {
382
+ "typeID": 7,
383
+ "result": {
384
+ "typeID": 5,
385
+ "base": {
386
+ "typeID": 3,
387
+ "baseID": "X3"
388
+ }
389
+ },
390
+ "args": [
391
+ {
392
+ "alias": "ξ",
393
+ "type": {
394
+ "typeID": 3,
395
+ "baseID": "X1"
396
+ }
397
+ }
398
+ ]
399
+ },
400
+ "valueClass": "value",
401
+ "diagnostics": []
402
+ }
403
+ },
404
+ {
405
+ "id": 14,
406
+ "alias": "A1",
407
+ "cstType": "axiom",
408
+ "definitionFormal": "∀ρ∈X2 ρ∉F1[ρ]",
409
+ "term": "иерархия без циклов",
410
+ "definitionText": "Роль не включает саму себя ни напрямую, ни через цепочку.",
411
+ "convention": "",
412
+ "analysis": {
413
+ "success": true,
414
+ "type": {
415
+ "typeID": 6
416
+ },
417
+ "valueClass": "value",
418
+ "diagnostics": []
419
+ }
420
+ },
421
+ {
422
+ "id": 15,
423
+ "alias": "A2",
424
+ "cstType": "axiom",
425
+ "definitionFormal": "∀ξ∈X1 ∀(α,β)∈S4 ¬(α∈F4[ξ] & β∈F4[ξ])",
426
+ "term": "разделение обязанностей",
427
+ "definitionText": "Ни у одного пользователя нет обеих ролей несовместимой пары, в том числе через иерархию.",
428
+ "convention": "",
429
+ "analysis": {
430
+ "success": true,
431
+ "type": {
432
+ "typeID": 6
433
+ },
434
+ "valueClass": "value",
435
+ "diagnostics": []
436
+ }
437
+ },
438
+ {
439
+ "id": 16,
440
+ "alias": "S5",
441
+ "cstType": "structure",
442
+ "definitionFormal": "ℬ(X1×X2×Z×Z)",
443
+ "term": "временные назначения",
444
+ "definitionText": "",
445
+ "convention": "Четвёрка (пользователь, роль, первый день, последний день): роль действует в эти дни включительно.",
446
+ "analysis": {
447
+ "success": true,
448
+ "type": {
449
+ "typeID": 5,
450
+ "base": {
451
+ "typeID": 4,
452
+ "factors": [
453
+ {
454
+ "typeID": 3,
455
+ "baseID": "X1"
456
+ },
457
+ {
458
+ "typeID": 3,
459
+ "baseID": "X2"
460
+ },
461
+ {
462
+ "typeID": 2,
463
+ "isOrdered": true,
464
+ "isArithmetic": true,
465
+ "isIntegerCompatible": true
466
+ },
467
+ {
468
+ "typeID": 2,
469
+ "isOrdered": true,
470
+ "isArithmetic": true,
471
+ "isIntegerCompatible": true
472
+ }
473
+ ]
474
+ }
475
+ },
476
+ "valueClass": "value",
477
+ "diagnostics": []
478
+ }
479
+ },
480
+ {
481
+ "id": 17,
482
+ "alias": "S6",
483
+ "cstType": "structure",
484
+ "definitionFormal": "Z",
485
+ "term": "текущий день",
486
+ "definitionText": "",
487
+ "convention": "Номер текущего дня в той же нумерации, что и периоды назначений.",
488
+ "analysis": {
489
+ "success": true,
490
+ "type": {
491
+ "typeID": 2,
492
+ "isOrdered": true,
493
+ "isArithmetic": true,
494
+ "isIntegerCompatible": true
495
+ },
496
+ "valueClass": "value",
497
+ "diagnostics": []
498
+ }
499
+ },
500
+ {
501
+ "id": 18,
502
+ "alias": "A3",
503
+ "cstType": "axiom",
504
+ "definitionFormal": "∀τ∈S5 pr3(τ)≤pr4(τ)",
505
+ "term": "период назначения корректен",
506
+ "definitionText": "Первый день периода не позже последнего.",
507
+ "convention": "",
508
+ "analysis": {
509
+ "success": true,
510
+ "type": {
511
+ "typeID": 6
512
+ },
513
+ "valueClass": "value",
514
+ "diagnostics": []
515
+ }
516
+ }
517
+ ],
518
+ "model": {
519
+ "items": []
520
+ }
521
+ },
522
+ "diagnostics": []
523
+ }
@@ -14,7 +14,15 @@ const sessions = [
14
14
  'examples/movd/rsform-session.json',
15
15
  'examples/movd/rsmodel-session.json',
16
16
  'examples/expression-bank/rsform-session.json',
17
- 'examples/template-apply/rsform-session.json'
17
+ 'examples/template-apply/rsform-session.json',
18
+ 'examples/subordination/rsform-session.json',
19
+ 'examples/kinship-subordination/rsform-session.json',
20
+ 'examples/library-loans/rsform-session-v1.json',
21
+ 'examples/library-loans/rsform-session.json',
22
+ 'examples/access-control/rsform-session-v1.json',
23
+ 'examples/access-control/rsform-session.json',
24
+ 'examples/clinic-booking/rsform-session-v1.json',
25
+ 'examples/clinic-booking/rsform-session.json'
18
26
  ];
19
27
 
20
28
  let total = 0;
@@ -0,0 +1,126 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+
4
+ import { describe, expect, it } from 'vitest';
5
+
6
+ import { type Brief, checkBrief } from '../skills/scripts/brief-check';
7
+
8
+ function read(path: string): string {
9
+ return readFileSync(resolve(import.meta.dirname, path), 'utf8');
10
+ }
11
+
12
+ function brief(path: string): Brief {
13
+ return JSON.parse(read(path)) as Brief;
14
+ }
15
+
16
+ describe('example briefs', () => {
17
+ const cases: Array<[string, string, string, string?]> = [
18
+ ['subordination', 'subordination/rsform-session.json', 'subordination/brief.json'],
19
+ ['kinship', 'kinship/rsform-session.json', 'kinship/brief.json'],
20
+ ['movd', 'movd/rsform-session.json', 'movd/brief.json'],
21
+ ['kinship-subordination', 'kinship-subordination/rsform-session.json', 'kinship-subordination/brief.json'],
22
+ ['library-loans v1', 'library-loans/rsform-session-v1.json', 'library-loans/brief-v1.json'],
23
+ [
24
+ 'library-loans v2',
25
+ 'library-loans/rsform-session.json',
26
+ 'library-loans/brief.json',
27
+ 'library-loans/rsform-session-v1.json'
28
+ ],
29
+ ['access-control v1', 'access-control/rsform-session-v1.json', 'access-control/brief-v1.json'],
30
+ [
31
+ 'access-control v2',
32
+ 'access-control/rsform-session.json',
33
+ 'access-control/brief.json',
34
+ 'access-control/rsform-session-v1.json'
35
+ ],
36
+ ['clinic-booking v1', 'clinic-booking/rsform-session-v1.json', 'clinic-booking/brief-v1.json'],
37
+ [
38
+ 'clinic-booking v2',
39
+ 'clinic-booking/rsform-session.json',
40
+ 'clinic-booking/brief.json',
41
+ 'clinic-booking/rsform-session-v1.json'
42
+ ]
43
+ ];
44
+
45
+ it.each(cases)('%s answers its brief', async (_, session, briefPath, base) => {
46
+ const { readiness } = await checkBrief({
47
+ session: read(session),
48
+ brief: brief(briefPath),
49
+ base: base ? read(base) : undefined
50
+ });
51
+ expect(readiness.blockers).toEqual([]);
52
+ expect(readiness.stage).toBe('review');
53
+ });
54
+ });
55
+
56
+ describe('subordination anti-examples', () => {
57
+ const reference = read('subordination/rsform-session.json');
58
+ const cases: Array<[string, string]> = [
59
+ ['single-relation', 'E4: конституента D5 не найдена'],
60
+ ['weakened', 'I1 «Сам себе не начальник»: нет аксиомы'],
61
+ ['collapsed', 'D8: формула стала тривиальной'],
62
+ ['transitive', 'A3 (допустимый сценарий): ожидалось истина, получено ложь']
63
+ ];
64
+
65
+ it.each(cases)('%s is caught', async (name, blocker) => {
66
+ const { readiness } = await checkBrief({
67
+ session: read(`subordination/anti/${name}.json`),
68
+ brief: brief('subordination/brief.json'),
69
+ base: reference
70
+ });
71
+ expect(readiness.ready).toBe(false);
72
+ expect(readiness.blockers.some(item => item.includes(blocker))).toBe(true);
73
+ });
74
+ });
75
+
76
+ describe('library-loans anti-examples', () => {
77
+ const reference = read('library-loans/rsform-session-v1.json');
78
+ const cases: Array<[string, string]> = [
79
+ ['uncovered', 'E3: конституента D2 не найдена'],
80
+ ['weakened', 'I1 «Экземпляр не выдан двум читателям одновременно»: нет аксиомы'],
81
+ ['species-as-genus', 'ожидался кортеж X2×X1'],
82
+ ['collapsed', 'D6: формула стала тривиальной']
83
+ ];
84
+
85
+ it.each(cases)('%s is caught', async (name, blocker) => {
86
+ const { readiness } = await checkBrief({
87
+ session: read(`library-loans/anti/${name}.json`),
88
+ brief: brief('library-loans/brief-v1.json'),
89
+ base: reference
90
+ });
91
+ expect(readiness.ready).toBe(false);
92
+ expect(readiness.blockers.some(item => item.includes(blocker))).toBe(true);
93
+ });
94
+ });
95
+
96
+ describe('access-control anti-examples', () => {
97
+ const cases: Array<[string, string]> = [
98
+ ['weakened', 'SC3 «Несовместимость через наследование»: A2: ожидалось ложь, получено истина'],
99
+ ['collapsed', 'F6["ann"]: ожидалось']
100
+ ];
101
+
102
+ it.each(cases)('%s is caught', async (name, blocker) => {
103
+ const { readiness } = await checkBrief({
104
+ session: read(`access-control/anti/${name}.json`),
105
+ brief: brief('access-control/brief-v1.json')
106
+ });
107
+ expect(readiness.ready).toBe(false);
108
+ expect(readiness.blockers.some(item => item.includes(blocker))).toBe(true);
109
+ });
110
+ });
111
+
112
+ describe('clinic-booking anti-examples', () => {
113
+ const cases: Array<[string, string]> = [
114
+ ['collapsed', 'F4["p1"]: ожидалось ["s2","s4"]'],
115
+ ['species-as-genus', 'E4: конституента S5 не найдена']
116
+ ];
117
+
118
+ it.each(cases)('%s is caught', async (name, blocker) => {
119
+ const { readiness } = await checkBrief({
120
+ session: read(`clinic-booking/anti/${name}.json`),
121
+ brief: brief('clinic-booking/brief-v1.json')
122
+ });
123
+ expect(readiness.ready).toBe(false);
124
+ expect(readiness.blockers.some(item => item.includes(blocker))).toBe(true);
125
+ });
126
+ });