@lokascript/framework 4.6.0 → 4.8.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 (116) hide show
  1. package/CHANGELOG.md +121 -1
  2. package/dist/api/create-dsl.d.ts +18 -2
  3. package/dist/api/create-dsl.d.ts.map +1 -1
  4. package/dist/api/index.d.ts +1 -0
  5. package/dist/api/index.d.ts.map +1 -1
  6. package/dist/api/index.js +1799 -713
  7. package/dist/api/index.js.map +1 -1
  8. package/dist/api/translation-loss.d.ts +84 -0
  9. package/dist/api/translation-loss.d.ts.map +1 -0
  10. package/dist/core/index.d.ts +1 -0
  11. package/dist/core/index.d.ts.map +1 -1
  12. package/dist/core/index.js +1057 -684
  13. package/dist/core/index.js.map +1 -1
  14. package/dist/core/matching/confidence-model.d.ts +54 -0
  15. package/dist/core/matching/confidence-model.d.ts.map +1 -0
  16. package/dist/core/matching/index.d.ts +12 -0
  17. package/dist/core/matching/index.d.ts.map +1 -0
  18. package/dist/core/matching/match-skeleton.d.ts +114 -0
  19. package/dist/core/matching/match-skeleton.d.ts.map +1 -0
  20. package/dist/core/matching/stock-confidence.d.ts +15 -0
  21. package/dist/core/matching/stock-confidence.d.ts.map +1 -0
  22. package/dist/core/matching/stock-reader.d.ts +63 -0
  23. package/dist/core/matching/stock-reader.d.ts.map +1 -0
  24. package/dist/core/matching/stock-reading.d.ts +44 -0
  25. package/dist/core/matching/stock-reading.d.ts.map +1 -0
  26. package/dist/core/matching/value-reader.d.ts +62 -0
  27. package/dist/core/matching/value-reader.d.ts.map +1 -0
  28. package/dist/core/pattern-matching/index.js +561 -660
  29. package/dist/core/pattern-matching/index.js.map +1 -1
  30. package/dist/core/pattern-matching/pattern-matcher.d.ts +0 -117
  31. package/dist/core/pattern-matching/pattern-matcher.d.ts.map +1 -1
  32. package/dist/core/types.d.ts +53 -0
  33. package/dist/core/types.d.ts.map +1 -1
  34. package/dist/core/types.js.map +1 -1
  35. package/dist/generation/index.d.ts +2 -0
  36. package/dist/generation/index.d.ts.map +1 -1
  37. package/dist/generation/index.js +593 -1
  38. package/dist/generation/index.js.map +1 -1
  39. package/dist/generation/pattern-render.d.ts +72 -0
  40. package/dist/generation/pattern-render.d.ts.map +1 -0
  41. package/dist/generation/schema-patterns.d.ts +152 -0
  42. package/dist/generation/schema-patterns.d.ts.map +1 -0
  43. package/dist/index.cjs +2016 -904
  44. package/dist/index.cjs.map +1 -1
  45. package/dist/index.js +1998 -903
  46. package/dist/index.js.map +1 -1
  47. package/dist/ir/index.js.map +1 -1
  48. package/dist/parsing/index.js +561 -660
  49. package/dist/parsing/index.js.map +1 -1
  50. package/dist/testing/gate/index.d.ts +8 -0
  51. package/dist/testing/gate/index.d.ts.map +1 -0
  52. package/dist/testing/gate/index.js +664 -0
  53. package/dist/testing/gate/index.js.map +1 -0
  54. package/dist/testing/gate/lint/format.d.ts +7 -0
  55. package/dist/testing/gate/lint/format.d.ts.map +1 -0
  56. package/dist/testing/gate/lint/index.d.ts +30 -0
  57. package/dist/testing/gate/lint/index.d.ts.map +1 -0
  58. package/dist/testing/gate/lint/rules/extractor-coverage.d.ts +18 -0
  59. package/dist/testing/gate/lint/rules/extractor-coverage.d.ts.map +1 -0
  60. package/dist/testing/gate/lint/rules/index.d.ts +14 -0
  61. package/dist/testing/gate/lint/rules/index.d.ts.map +1 -0
  62. package/dist/testing/gate/lint/rules/keyword-classification.d.ts +19 -0
  63. package/dist/testing/gate/lint/rules/keyword-classification.d.ts.map +1 -0
  64. package/dist/testing/gate/lint/rules/keyword-coverage.d.ts +13 -0
  65. package/dist/testing/gate/lint/rules/keyword-coverage.d.ts.map +1 -0
  66. package/dist/testing/gate/lint/rules/marker-tokenization.d.ts +20 -0
  67. package/dist/testing/gate/lint/rules/marker-tokenization.d.ts.map +1 -0
  68. package/dist/testing/gate/lint/rules/position-ordering.d.ts +25 -0
  69. package/dist/testing/gate/lint/rules/position-ordering.d.ts.map +1 -0
  70. package/dist/testing/gate/lint/rules/renderer-coherence.d.ts +24 -0
  71. package/dist/testing/gate/lint/rules/renderer-coherence.d.ts.map +1 -0
  72. package/dist/testing/gate/lint/rules/schema-rules.d.ts +10 -0
  73. package/dist/testing/gate/lint/rules/schema-rules.d.ts.map +1 -0
  74. package/dist/testing/gate/lint/types.d.ts +74 -0
  75. package/dist/testing/gate/lint/types.d.ts.map +1 -0
  76. package/dist/testing/gate/round-trip.d.ts +184 -0
  77. package/dist/testing/gate/round-trip.d.ts.map +1 -0
  78. package/package.json +6 -2
  79. package/src/__test__/fixtures/sql-dsl.ts +8 -2
  80. package/src/api/create-dsl-engine.test.ts +150 -0
  81. package/src/api/create-dsl.test.ts +7 -0
  82. package/src/api/create-dsl.ts +173 -22
  83. package/src/api/index.ts +1 -0
  84. package/src/api/translation-loss.test.ts +89 -0
  85. package/src/api/translation-loss.ts +128 -0
  86. package/src/core/index.ts +1 -0
  87. package/src/core/matching/confidence-model.ts +58 -0
  88. package/src/core/matching/index.ts +12 -0
  89. package/src/core/matching/match-skeleton.test.ts +179 -0
  90. package/src/core/matching/match-skeleton.ts +621 -0
  91. package/src/core/matching/stock-confidence.ts +238 -0
  92. package/src/core/matching/stock-reader.test.ts +265 -0
  93. package/src/core/matching/stock-reader.ts +205 -0
  94. package/src/core/matching/stock-reading.ts +681 -0
  95. package/src/core/matching/value-reader.ts +85 -0
  96. package/src/core/pattern-matching/pattern-matcher.ts +11 -876
  97. package/src/core/types.ts +53 -0
  98. package/src/generation/index.ts +2 -0
  99. package/src/generation/pattern-render.ts +378 -0
  100. package/src/generation/schema-patterns.test.ts +139 -0
  101. package/src/generation/schema-patterns.ts +974 -0
  102. package/src/testing/gate/index.ts +8 -0
  103. package/src/testing/gate/lint/format.ts +23 -0
  104. package/src/testing/gate/lint/index.ts +73 -0
  105. package/src/testing/gate/lint/lint.test.ts +131 -0
  106. package/src/testing/gate/lint/rules/extractor-coverage.ts +63 -0
  107. package/src/testing/gate/lint/rules/index.ts +37 -0
  108. package/src/testing/gate/lint/rules/keyword-classification.ts +52 -0
  109. package/src/testing/gate/lint/rules/keyword-coverage.ts +38 -0
  110. package/src/testing/gate/lint/rules/marker-tokenization.ts +129 -0
  111. package/src/testing/gate/lint/rules/position-ordering.ts +87 -0
  112. package/src/testing/gate/lint/rules/renderer-coherence.ts +100 -0
  113. package/src/testing/gate/lint/rules/schema-rules.ts +35 -0
  114. package/src/testing/gate/lint/types.ts +83 -0
  115. package/src/testing/gate/round-trip.test.ts +208 -0
  116. package/src/testing/gate/round-trip.ts +503 -0
@@ -0,0 +1,179 @@
1
+ /**
2
+ * The matcher's skeleton with a reader that knows no hyperscript: every role
3
+ * slot takes one token. What the skeleton does on its own — literals, group
4
+ * rollback, the speculative skip, spans, ranking — and that every value comes
5
+ * from the reader (domains rethink Phase 4.2-4.3).
6
+ */
7
+ import { describe, expect, it } from 'vitest';
8
+ import { MatchSkeleton } from './match-skeleton';
9
+ import type { MatchView, RoleSlot, ValueReader } from './value-reader';
10
+ import type { ConfidenceContext, ConfidenceModel } from './confidence-model';
11
+ import { TokenStreamImpl } from '../tokenization/token-utils';
12
+ import type {
13
+ LanguagePattern,
14
+ LanguageToken,
15
+ PatternMatchResult,
16
+ PatternToken,
17
+ SemanticRole,
18
+ SemanticValue,
19
+ TokenStream,
20
+ } from '../types';
21
+
22
+ class OneTokenReader implements ValueReader {
23
+ readonly began: string[] = [];
24
+ readonly owed: string[][] = [];
25
+
26
+ constructor(private readonly view: MatchView) {}
27
+
28
+ beginPattern(pattern: LanguagePattern): void {
29
+ this.began.push(pattern.id);
30
+ }
31
+
32
+ readRole(
33
+ tokens: TokenStream,
34
+ slot: RoleSlot,
35
+ captured: Map<SemanticRole, SemanticValue>
36
+ ): boolean {
37
+ this.owed.push(
38
+ this.view.patternRest().flatMap(pt => (pt.type === 'literal' ? [pt.value] : []))
39
+ );
40
+ const token = tokens.peek();
41
+ if (!token) return slot.optional ?? false;
42
+ captured.set(slot.role, { type: 'literal', value: token.value });
43
+ tokens.advance();
44
+ return true;
45
+ }
46
+
47
+ maySkipSlot(patternToken: PatternToken, token: LanguageToken | null): boolean {
48
+ return patternToken.type === 'role' && !!patternToken.optional && token?.value === 'now';
49
+ }
50
+
51
+ atClauseEnd(tokens: TokenStream): boolean {
52
+ return tokens.isAtEnd();
53
+ }
54
+
55
+ resultFields(): Partial<PatternMatchResult> {
56
+ return { eventSource: { type: 'literal', value: 'from-reader' } };
57
+ }
58
+ }
59
+
60
+ function model(score: (ctx: ConfidenceContext) => number): ConfidenceModel {
61
+ return {
62
+ calculate: score,
63
+ calculateWithBreakdown: ctx => ({
64
+ roleCoverage: score(ctx),
65
+ stemPenalty: 0,
66
+ languageBoost: 0,
67
+ languageAdjustment: 0,
68
+ final: score(ctx),
69
+ }),
70
+ };
71
+ }
72
+
73
+ const flat = model(() => 1);
74
+
75
+ function matcher(confidence: ConfidenceModel = flat): {
76
+ skeleton: MatchSkeleton;
77
+ reader: () => OneTokenReader;
78
+ } {
79
+ let reader: OneTokenReader | undefined;
80
+ const skeleton = new MatchSkeleton(view => (reader = new OneTokenReader(view)), confidence);
81
+ return { skeleton, reader: () => reader! };
82
+ }
83
+
84
+ function stream(text: string): TokenStream {
85
+ let offset = 0;
86
+ const tokens = text.split(' ').map(value => {
87
+ const token: LanguageToken = {
88
+ value,
89
+ kind: 'identifier',
90
+ position: { start: offset, end: offset + value.length },
91
+ };
92
+ offset += value.length + 1;
93
+ return token;
94
+ });
95
+ return new TokenStreamImpl(tokens, 'xx');
96
+ }
97
+
98
+ const lit = (value: string): PatternToken => ({ type: 'literal', value });
99
+ const role = (name: string, optional = false): PatternToken => ({
100
+ type: 'role',
101
+ role: name as SemanticRole,
102
+ ...(optional ? { optional } : {}),
103
+ });
104
+ const group = (...tokens: PatternToken[]): PatternToken => ({
105
+ type: 'group',
106
+ optional: true,
107
+ tokens,
108
+ });
109
+
110
+ function pattern(id: string, tokens: PatternToken[], priority = 100): LanguagePattern {
111
+ return {
112
+ id,
113
+ language: 'xx',
114
+ command: 'go',
115
+ priority,
116
+ template: { format: id, tokens },
117
+ extraction: {},
118
+ };
119
+ }
120
+
121
+ const values = (result: PatternMatchResult | null) =>
122
+ Object.fromEntries(
123
+ [...(result?.captured ?? [])].map(([r, v]) => [r, (v as { value?: unknown }).value])
124
+ );
125
+
126
+ describe('MatchSkeleton', () => {
127
+ it('matches literals itself and reads every role slot through the reader', () => {
128
+ const { skeleton, reader } = matcher();
129
+ const result = skeleton.matchPattern(
130
+ stream('go home now'),
131
+ pattern('p', [lit('go'), role('destination'), lit('now')])
132
+ );
133
+ expect(values(result)).toEqual({ destination: 'home' });
134
+ expect(result?.consumedTokens).toBe(3);
135
+ expect(result?.roleStarts?.get('destination' as SemanticRole)).toBe(1);
136
+ expect(reader().began).toEqual(['p']);
137
+ // The view shows the reader what the pattern still owes after the slot.
138
+ expect(reader().owed).toEqual([['now']]);
139
+ });
140
+
141
+ it("adds the reader's result fields", () => {
142
+ const { skeleton } = matcher();
143
+ const result = skeleton.matchPattern(stream('go home'), pattern('p', [lit('go'), role('x')]));
144
+ expect(result?.eventSource).toEqual({ type: 'literal', value: 'from-reader' });
145
+ });
146
+
147
+ it('rolls a failed group back, restoring a value it overwrote', () => {
148
+ const { skeleton } = matcher();
149
+ // The group reads `b` into destination, then fails on its marker.
150
+ const result = skeleton.matchPattern(
151
+ stream('a b c'),
152
+ pattern('p', [role('destination'), group(role('destination'), lit('に'))])
153
+ );
154
+ expect(values(result)).toEqual({ destination: 'a' });
155
+ expect(result?.consumedTokens).toBe(1);
156
+ });
157
+
158
+ it('skips an optional slot when the reader allows it and the rest reaches a clause end', () => {
159
+ const { skeleton } = matcher();
160
+ const result = skeleton.matchPattern(
161
+ stream('go now'),
162
+ pattern('p', [lit('go'), role('patient', true), lit('now')])
163
+ );
164
+ expect(values(result)).toEqual({});
165
+ expect(result?.consumedTokens).toBe(2);
166
+ });
167
+
168
+ it('ranks matches by priority, then confidence', () => {
169
+ const byId = model(ctx => (ctx.pattern.id === 'high' ? 0.9 : 0.5));
170
+ const { skeleton } = matcher(byId);
171
+ const tokens = [lit('go'), role('x')];
172
+ const best = skeleton.matchBest(stream('go home'), [
173
+ pattern('low', tokens),
174
+ pattern('high', tokens),
175
+ pattern('priority', tokens, 50),
176
+ ]);
177
+ expect(best?.pattern.id).toBe('high');
178
+ });
179
+ });