@lokascript/framework 4.7.0 → 5.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 (96) hide show
  1. package/CHANGELOG.md +76 -1
  2. package/dist/api/create-dsl.d.ts +14 -12
  3. package/dist/api/create-dsl.d.ts.map +1 -1
  4. package/dist/api/index.js +888 -1683
  5. package/dist/api/index.js.map +1 -1
  6. package/dist/core/index.d.ts +0 -1
  7. package/dist/core/index.d.ts.map +1 -1
  8. package/dist/core/index.js +560 -1133
  9. package/dist/core/index.js.map +1 -1
  10. package/dist/core/matching/index.d.ts +2 -0
  11. package/dist/core/matching/index.d.ts.map +1 -1
  12. package/dist/core/matching/possessive-keywords.d.ts.map +1 -0
  13. package/dist/core/matching/stock-confidence.d.ts +3 -4
  14. package/dist/core/matching/stock-confidence.d.ts.map +1 -1
  15. package/dist/core/matching/stock-reader.d.ts +8 -1
  16. package/dist/core/matching/stock-reader.d.ts.map +1 -1
  17. package/dist/core/matching/stock-reading.d.ts +4 -4
  18. package/dist/core/{pattern-matching/utils → matching}/type-validation.d.ts +1 -1
  19. package/dist/core/matching/type-validation.d.ts.map +1 -0
  20. package/dist/core/types.d.ts +5 -0
  21. package/dist/core/types.d.ts.map +1 -1
  22. package/dist/core/types.js.map +1 -1
  23. package/dist/generation/index.d.ts +1 -1
  24. package/dist/generation/index.d.ts.map +1 -1
  25. package/dist/generation/index.js +32 -171
  26. package/dist/generation/index.js.map +1 -1
  27. package/dist/generation/profile.d.ts +30 -0
  28. package/dist/generation/profile.d.ts.map +1 -0
  29. package/dist/generation/renderer.d.ts +1 -1
  30. package/dist/generation/renderer.d.ts.map +1 -1
  31. package/dist/generation/schema-patterns.d.ts +3 -3
  32. package/dist/index.cjs +969 -1674
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.js +969 -1668
  35. package/dist/index.js.map +1 -1
  36. package/dist/ir/index.js.map +1 -1
  37. package/dist/multilingual/builders.d.ts +3 -3
  38. package/dist/multilingual/builders.d.ts.map +1 -1
  39. package/dist/multilingual/index.js.map +1 -1
  40. package/dist/parsing/index.d.ts +0 -1
  41. package/dist/parsing/index.d.ts.map +1 -1
  42. package/dist/parsing/index.js +0 -1145
  43. package/dist/parsing/index.js.map +1 -1
  44. package/dist/testing/gate/index.js +44 -12
  45. package/dist/testing/gate/index.js.map +1 -1
  46. package/dist/testing/gate/lint/types.d.ts +1 -1
  47. package/dist/testing/gate/lint/types.d.ts.map +1 -1
  48. package/dist/testing/gate/round-trip.d.ts +24 -3
  49. package/dist/testing/gate/round-trip.d.ts.map +1 -1
  50. package/package.json +2 -7
  51. package/src/__test__/test-utils.ts +1 -1
  52. package/src/api/create-dsl-engine.test.ts +123 -34
  53. package/src/api/create-dsl.test.ts +7 -0
  54. package/src/api/create-dsl.ts +56 -39
  55. package/src/core/index.ts +0 -1
  56. package/src/core/matching/index.ts +2 -0
  57. package/src/core/matching/stock-confidence.ts +3 -4
  58. package/src/core/matching/stock-reader.test.ts +87 -3
  59. package/src/core/matching/stock-reader.ts +20 -1
  60. package/src/core/matching/stock-reading.ts +6 -6
  61. package/src/core/{pattern-matching/utils → matching}/type-validation.test.ts +2 -2
  62. package/src/core/{pattern-matching/utils → matching}/type-validation.ts +1 -1
  63. package/src/core/types.ts +5 -0
  64. package/src/generation/domain-renderer.test.ts +1 -1
  65. package/src/generation/index.ts +1 -1
  66. package/src/generation/profile.ts +41 -0
  67. package/src/generation/renderer.test.ts +1 -1
  68. package/src/generation/renderer.ts +1 -1
  69. package/src/generation/schema-patterns.test.ts +41 -1
  70. package/src/generation/schema-patterns.ts +15 -3
  71. package/src/multilingual/bridge.test.ts +31 -23
  72. package/src/multilingual/builders.ts +3 -3
  73. package/src/parsing/index.ts +0 -1
  74. package/src/testing/gate/lint/types.ts +1 -1
  75. package/src/testing/gate/round-trip.test.ts +99 -9
  76. package/src/testing/gate/round-trip.ts +76 -11
  77. package/dist/core/pattern-matching/index.d.ts +0 -6
  78. package/dist/core/pattern-matching/index.d.ts.map +0 -1
  79. package/dist/core/pattern-matching/index.js +0 -1211
  80. package/dist/core/pattern-matching/index.js.map +0 -1
  81. package/dist/core/pattern-matching/pattern-matcher.d.ts +0 -122
  82. package/dist/core/pattern-matching/pattern-matcher.d.ts.map +0 -1
  83. package/dist/core/pattern-matching/utils/index.d.ts +0 -6
  84. package/dist/core/pattern-matching/utils/index.d.ts.map +0 -1
  85. package/dist/core/pattern-matching/utils/possessive-keywords.d.ts.map +0 -1
  86. package/dist/core/pattern-matching/utils/type-validation.d.ts.map +0 -1
  87. package/dist/generation/pattern-generator.d.ts +0 -55
  88. package/dist/generation/pattern-generator.d.ts.map +0 -1
  89. package/src/core/pattern-matching/index.ts +0 -6
  90. package/src/core/pattern-matching/pattern-matcher.test.ts +0 -1031
  91. package/src/core/pattern-matching/pattern-matcher.ts +0 -765
  92. package/src/core/pattern-matching/utils/index.ts +0 -6
  93. package/src/generation/pattern-generator.test.ts +0 -532
  94. package/src/generation/pattern-generator.ts +0 -327
  95. /package/dist/core/{pattern-matching/utils → matching}/possessive-keywords.d.ts +0 -0
  96. /package/src/core/{pattern-matching/utils → matching}/possessive-keywords.ts +0 -0
@@ -1,6 +0,0 @@
1
- /**
2
- * Pattern matching utilities
3
- */
4
-
5
- export * from './type-validation';
6
- export * from './possessive-keywords';
@@ -1,532 +0,0 @@
1
- /**
2
- * Pattern Generator Tests
3
- *
4
- * Tests the pattern generation system that creates LanguagePattern objects
5
- * from CommandSchema + LanguageProfile combinations.
6
- */
7
-
8
- import { describe, it, expect } from 'vitest';
9
- import { generatePattern, type PatternGenLanguageProfile } from './pattern-generator';
10
- import { defineCommand, defineRole } from '../schema';
11
-
12
- describe('PatternGenerator', () => {
13
- describe('generatePattern', () => {
14
- it('should generate a basic SVO pattern', () => {
15
- const schema = defineCommand({
16
- action: 'toggle',
17
- roles: [
18
- defineRole({
19
- role: 'patient',
20
- required: true,
21
- expectedTypes: ['selector'],
22
- }),
23
- ],
24
- });
25
-
26
- const profile: PatternGenLanguageProfile = {
27
- code: 'en',
28
- wordOrder: 'SVO',
29
- keywords: {
30
- toggle: { primary: 'toggle' },
31
- },
32
- };
33
-
34
- const pattern = generatePattern(schema, profile);
35
-
36
- expect(pattern.id).toBe('toggle-en-generated');
37
- expect(pattern.language).toBe('en');
38
- expect(pattern.command).toBe('toggle');
39
- expect(pattern.priority).toBe(100);
40
- expect(pattern.template.tokens).toHaveLength(2);
41
- expect(pattern.template.tokens[0]).toEqual({ type: 'literal', value: 'toggle' });
42
- expect(pattern.template.tokens[1]).toMatchObject({ type: 'role', role: 'patient' });
43
- });
44
-
45
- it('should generate an SOV pattern with verb last', () => {
46
- const schema = defineCommand({
47
- action: 'toggle',
48
- roles: [
49
- defineRole({
50
- role: 'patient',
51
- required: true,
52
- expectedTypes: ['selector'],
53
- sovPosition: 1,
54
- }),
55
- ],
56
- });
57
-
58
- const profile: PatternGenLanguageProfile = {
59
- code: 'ja',
60
- wordOrder: 'SOV',
61
- keywords: {
62
- toggle: { primary: 'トグル' },
63
- },
64
- };
65
-
66
- const pattern = generatePattern(schema, profile);
67
-
68
- expect(pattern.template.tokens).toHaveLength(2);
69
- // In SOV, role comes first, then verb
70
- expect(pattern.template.tokens[0]).toMatchObject({ type: 'role', role: 'patient' });
71
- expect(pattern.template.tokens[1]).toEqual({ type: 'literal', value: 'トグル' });
72
- });
73
-
74
- it('should place a sovSlot:postVerb role after the verb in SOV', () => {
75
- // The renderer buckets by this field (`renderer.ts`), writing voice's
76
- // page count after the verb: `戻る 2`. Generation has to agree, or the
77
- // rendered surface re-parses as a bare verb with its argument dropped.
78
- const schema = defineCommand({
79
- action: 'back',
80
- roles: [
81
- defineRole({
82
- role: 'quantity',
83
- required: true,
84
- expectedTypes: ['expression'],
85
- sovPosition: 1,
86
- sovSlot: 'postVerb',
87
- }),
88
- ],
89
- });
90
-
91
- const profile: PatternGenLanguageProfile = {
92
- code: 'ja',
93
- wordOrder: 'SOV',
94
- keywords: { back: { primary: '戻る' } },
95
- };
96
-
97
- const pattern = generatePattern(schema, profile);
98
-
99
- expect(pattern.template.tokens).toHaveLength(2);
100
- expect(pattern.template.tokens[0]).toEqual({ type: 'literal', value: '戻る' });
101
- expect(pattern.template.tokens[1]).toMatchObject({ type: 'role', role: 'quantity' });
102
- expect(pattern.template.format).toBe('戻る {quantity}');
103
- });
104
-
105
- it('should split pre-verb and post-verb roles around the verb in SOV', () => {
106
- const schema = defineCommand({
107
- action: 'fetch',
108
- roles: [
109
- defineRole({
110
- role: 'source',
111
- required: true,
112
- expectedTypes: ['expression'],
113
- sovPosition: 2,
114
- }),
115
- defineRole({
116
- role: 'destination',
117
- required: true,
118
- expectedTypes: ['selector'],
119
- sovPosition: 1,
120
- sovSlot: 'postVerb',
121
- markerOverride: { ja: 'に' },
122
- }),
123
- ],
124
- });
125
-
126
- const profile: PatternGenLanguageProfile = {
127
- code: 'ja',
128
- wordOrder: 'SOV',
129
- keywords: { fetch: { primary: '取得' } },
130
- };
131
-
132
- const pattern = generatePattern(schema, profile);
133
-
134
- expect(pattern.template.tokens).toEqual([
135
- expect.objectContaining({ type: 'role', role: 'source' }),
136
- { type: 'literal', value: '取得' },
137
- expect.objectContaining({ type: 'role', role: 'destination' }),
138
- // SOV markers default to following their value
139
- { type: 'literal', value: 'に' },
140
- ]);
141
- // The role PHRASE moves as a unit. Note the marker sits before its role
142
- // here while the tokens put it after: `format` resolves marker position
143
- // from the profile alone, missing `markerPosition` and the SOV default
144
- // that `addRoleWithMarker` applies. Pre-existing and documentation-only
145
- // (nothing reads `format`), left alone deliberately — fixing it would
146
- // move every SOV golden entry with a marker and bury this change's diff.
147
- expect(pattern.template.format).toBe('{source} 取得 に {destination}');
148
- });
149
-
150
- it('should ignore sovSlot outside SOV languages', () => {
151
- const schema = defineCommand({
152
- action: 'back',
153
- roles: [
154
- defineRole({
155
- role: 'quantity',
156
- required: true,
157
- expectedTypes: ['expression'],
158
- svoPosition: 1,
159
- sovSlot: 'postVerb',
160
- }),
161
- ],
162
- });
163
-
164
- for (const wordOrder of ['SVO', 'VSO'] as const) {
165
- const pattern = generatePattern(schema, {
166
- code: 'en',
167
- wordOrder,
168
- keywords: { back: { primary: 'back' } },
169
- });
170
-
171
- expect(pattern.template.tokens[0]).toEqual({ type: 'literal', value: 'back' });
172
- expect(pattern.template.tokens[1]).toMatchObject({ type: 'role', role: 'quantity' });
173
- }
174
- });
175
-
176
- it('should generate a VSO pattern with verb first', () => {
177
- const schema = defineCommand({
178
- action: 'toggle',
179
- roles: [
180
- defineRole({
181
- role: 'patient',
182
- required: true,
183
- expectedTypes: ['selector'],
184
- }),
185
- ],
186
- });
187
-
188
- const profile: PatternGenLanguageProfile = {
189
- code: 'ar',
190
- wordOrder: 'VSO',
191
- keywords: {
192
- toggle: { primary: 'بدّل' },
193
- },
194
- };
195
-
196
- const pattern = generatePattern(schema, profile);
197
-
198
- expect(pattern.template.tokens).toHaveLength(2);
199
- // VSO is like SVO - verb first
200
- expect(pattern.template.tokens[0]).toEqual({ type: 'literal', value: 'بدّل' });
201
- expect(pattern.template.tokens[1]).toMatchObject({ type: 'role', role: 'patient' });
202
- });
203
-
204
- it('should include role markers when specified', () => {
205
- const schema = defineCommand({
206
- action: 'get',
207
- roles: [
208
- defineRole({
209
- role: 'target',
210
- required: true,
211
- expectedTypes: ['expression'],
212
- markerOverride: { en: 'from' },
213
- }),
214
- ],
215
- });
216
-
217
- const profile: PatternGenLanguageProfile = {
218
- code: 'en',
219
- wordOrder: 'SVO',
220
- keywords: {
221
- get: { primary: 'get' },
222
- },
223
- roleMarkers: {
224
- target: { primary: 'from', position: 'before' },
225
- },
226
- };
227
-
228
- const pattern = generatePattern(schema, profile);
229
-
230
- // Should have: get, from (marker), target (role)
231
- expect(pattern.template.tokens).toHaveLength(3);
232
- expect(pattern.template.tokens[0]).toEqual({ type: 'literal', value: 'get' });
233
- expect(pattern.template.tokens[1]).toEqual({ type: 'literal', value: 'from' });
234
- expect(pattern.template.tokens[2]).toMatchObject({ type: 'role', role: 'target' });
235
- });
236
-
237
- it('should handle optional roles with groups', () => {
238
- const schema = defineCommand({
239
- action: 'select',
240
- roles: [
241
- defineRole({
242
- role: 'columns',
243
- required: true,
244
- expectedTypes: ['expression'],
245
- }),
246
- defineRole({
247
- role: 'source',
248
- required: false,
249
- expectedTypes: ['expression'],
250
- markerOverride: { en: 'from' },
251
- }),
252
- ],
253
- });
254
-
255
- const profile: PatternGenLanguageProfile = {
256
- code: 'en',
257
- wordOrder: 'SVO',
258
- keywords: {
259
- select: { primary: 'select' },
260
- },
261
- roleMarkers: {
262
- source: { primary: 'from', position: 'before' },
263
- },
264
- };
265
-
266
- const pattern = generatePattern(schema, profile);
267
-
268
- // Should have optional group for source
269
- expect(
270
- pattern.template.tokens.some(t => t.type === 'group' && 'optional' in t && t.optional)
271
- ).toBe(true);
272
- });
273
-
274
- it('should build extraction rules for all roles', () => {
275
- const schema = defineCommand({
276
- action: 'select',
277
- roles: [
278
- defineRole({
279
- role: 'columns',
280
- required: true,
281
- expectedTypes: ['expression'],
282
- }),
283
- defineRole({
284
- role: 'source',
285
- required: true,
286
- expectedTypes: ['expression'],
287
- markerOverride: { en: 'from' },
288
- }),
289
- ],
290
- });
291
-
292
- const profile: PatternGenLanguageProfile = {
293
- code: 'en',
294
- wordOrder: 'SVO',
295
- keywords: {
296
- select: { primary: 'select' },
297
- },
298
- };
299
-
300
- const pattern = generatePattern(schema, profile);
301
-
302
- expect(pattern.extraction).toHaveProperty('columns');
303
- expect(pattern.extraction).toHaveProperty('source');
304
- });
305
-
306
- it('should use marker-based extraction when marker exists', () => {
307
- const schema = defineCommand({
308
- action: 'get',
309
- roles: [
310
- defineRole({
311
- role: 'target',
312
- required: true,
313
- expectedTypes: ['expression'],
314
- markerOverride: { en: 'from' },
315
- }),
316
- ],
317
- });
318
-
319
- const profile: PatternGenLanguageProfile = {
320
- code: 'en',
321
- wordOrder: 'SVO',
322
- keywords: {
323
- get: { primary: 'get' },
324
- },
325
- roleMarkers: {
326
- target: { primary: 'from', position: 'before' },
327
- },
328
- };
329
-
330
- const pattern = generatePattern(schema, profile);
331
-
332
- expect(pattern.extraction.target).toHaveProperty('marker', 'from');
333
- });
334
-
335
- it('should throw error for missing keyword translation', () => {
336
- const schema = defineCommand({
337
- action: 'unknown',
338
- roles: [],
339
- });
340
-
341
- const profile: PatternGenLanguageProfile = {
342
- code: 'en',
343
- wordOrder: 'SVO',
344
- keywords: {
345
- toggle: { primary: 'toggle' },
346
- },
347
- };
348
-
349
- expect(() => generatePattern(schema, profile)).toThrow(
350
- "No keyword translation for 'unknown' in en"
351
- );
352
- });
353
-
354
- it('should respect custom priority configuration', () => {
355
- const schema = defineCommand({
356
- action: 'toggle',
357
- roles: [],
358
- });
359
-
360
- const profile: PatternGenLanguageProfile = {
361
- code: 'en',
362
- wordOrder: 'SVO',
363
- keywords: {
364
- toggle: { primary: 'toggle' },
365
- },
366
- };
367
-
368
- const pattern = generatePattern(schema, profile, { basePriority: 50 });
369
-
370
- expect(pattern.priority).toBe(50);
371
- });
372
-
373
- it('should handle multiple roles with correct ordering', () => {
374
- const schema = defineCommand({
375
- action: 'put',
376
- roles: [
377
- defineRole({
378
- role: 'value',
379
- required: true,
380
- expectedTypes: ['expression'],
381
- svoPosition: 2,
382
- }),
383
- defineRole({
384
- role: 'destination',
385
- required: true,
386
- expectedTypes: ['selector'],
387
- svoPosition: 1,
388
- markerOverride: { en: 'into' },
389
- }),
390
- ],
391
- });
392
-
393
- const profile: PatternGenLanguageProfile = {
394
- code: 'en',
395
- wordOrder: 'SVO',
396
- keywords: {
397
- put: { primary: 'put' },
398
- },
399
- roleMarkers: {
400
- destination: { primary: 'into', position: 'before' },
401
- },
402
- };
403
-
404
- const pattern = generatePattern(schema, profile);
405
-
406
- // Should be: put, value (higher svoPosition = first), into, destination
407
- expect(pattern.template.tokens[0]).toEqual({ type: 'literal', value: 'put' });
408
- expect(pattern.template.tokens[1]).toMatchObject({ type: 'role', role: 'value' });
409
- expect(pattern.template.tokens[2]).toEqual({ type: 'literal', value: 'into' });
410
- expect(pattern.template.tokens[3]).toMatchObject({ type: 'role', role: 'destination' });
411
- });
412
-
413
- it('should generate format string for documentation', () => {
414
- const schema = defineCommand({
415
- action: 'toggle',
416
- roles: [
417
- defineRole({
418
- role: 'patient',
419
- required: true,
420
- expectedTypes: ['selector'],
421
- }),
422
- ],
423
- });
424
-
425
- const profile: PatternGenLanguageProfile = {
426
- code: 'en',
427
- wordOrder: 'SVO',
428
- keywords: {
429
- toggle: { primary: 'toggle' },
430
- },
431
- };
432
-
433
- const pattern = generatePattern(schema, profile);
434
-
435
- expect(pattern.template.format).toBeTruthy();
436
- expect(typeof pattern.template.format).toBe('string');
437
- expect(pattern.template.format).toContain('toggle');
438
- });
439
-
440
- it('should handle empty roles array', () => {
441
- const schema = defineCommand({
442
- action: 'reload',
443
- roles: [],
444
- });
445
-
446
- const profile: PatternGenLanguageProfile = {
447
- code: 'en',
448
- wordOrder: 'SVO',
449
- keywords: {
450
- reload: { primary: 'reload' },
451
- },
452
- };
453
-
454
- const pattern = generatePattern(schema, profile);
455
-
456
- expect(pattern.template.tokens).toHaveLength(1);
457
- expect(pattern.template.tokens[0]).toEqual({ type: 'literal', value: 'reload' });
458
- });
459
-
460
- it('should handle alternative keywords', () => {
461
- const schema = defineCommand({
462
- action: 'toggle',
463
- roles: [
464
- defineRole({
465
- role: 'patient',
466
- required: true,
467
- expectedTypes: ['selector'],
468
- }),
469
- ],
470
- });
471
-
472
- const profile: PatternGenLanguageProfile = {
473
- code: 'en',
474
- wordOrder: 'SVO',
475
- keywords: {
476
- toggle: { primary: 'toggle', alternatives: ['switch'] },
477
- },
478
- };
479
-
480
- const pattern = generatePattern(schema, profile);
481
-
482
- // Primary keyword should be used in tokens, alternatives passed through
483
- expect(pattern.template.tokens[0]).toEqual({
484
- type: 'literal',
485
- value: 'toggle',
486
- alternatives: ['switch'],
487
- });
488
- });
489
-
490
- it('should use markerOverride from role spec', () => {
491
- const schema = defineCommand({
492
- action: 'get',
493
- roles: [
494
- defineRole({
495
- role: 'source',
496
- required: true,
497
- expectedTypes: ['expression'],
498
- markerOverride: { en: 'from', es: 'de' },
499
- }),
500
- ],
501
- });
502
-
503
- const englishProfile: PatternGenLanguageProfile = {
504
- code: 'en',
505
- wordOrder: 'SVO',
506
- keywords: {
507
- get: { primary: 'get' },
508
- },
509
- };
510
-
511
- const spanishProfile: PatternGenLanguageProfile = {
512
- code: 'es',
513
- wordOrder: 'SVO',
514
- keywords: {
515
- get: { primary: 'obtener' },
516
- },
517
- };
518
-
519
- const enPattern = generatePattern(schema, englishProfile);
520
- const esPattern = generatePattern(schema, spanishProfile);
521
-
522
- // English should have 'from' marker
523
- expect(enPattern.template.tokens.some(t => t.type === 'literal' && t.value === 'from')).toBe(
524
- true
525
- );
526
- // Spanish should have 'de' marker
527
- expect(esPattern.template.tokens.some(t => t.type === 'literal' && t.value === 'de')).toBe(
528
- true
529
- );
530
- });
531
- });
532
- });