@lokascript/framework 2.0.0 → 2.2.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 (138) hide show
  1. package/dist/aot/index.d.ts +1 -0
  2. package/dist/aot/index.d.ts.map +1 -1
  3. package/dist/aot/registry-bridge.d.ts +27 -0
  4. package/dist/aot/registry-bridge.d.ts.map +1 -0
  5. package/dist/api/create-dsl.d.ts.map +1 -1
  6. package/dist/api/dispatcher.d.ts +22 -0
  7. package/dist/api/dispatcher.d.ts.map +1 -1
  8. package/dist/api/domain-registry.d.ts +41 -0
  9. package/dist/api/domain-registry.d.ts.map +1 -1
  10. package/dist/api/index.js +1438 -21
  11. package/dist/api/index.js.map +1 -1
  12. package/dist/core/index.js +247 -10
  13. package/dist/core/index.js.map +1 -1
  14. package/dist/core/pattern-matching/index.js +74 -10
  15. package/dist/core/pattern-matching/index.js.map +1 -1
  16. package/dist/core/pattern-matching/pattern-matcher.d.ts.map +1 -1
  17. package/dist/core/tokenization/index.js +133 -0
  18. package/dist/core/tokenization/index.js.map +1 -1
  19. package/dist/core/tokenization/morphology/base-normalizer.d.ts +94 -0
  20. package/dist/core/tokenization/morphology/base-normalizer.d.ts.map +1 -0
  21. package/dist/core/tokenization/morphology/index.d.ts +3 -1
  22. package/dist/core/tokenization/morphology/index.d.ts.map +1 -1
  23. package/dist/core/types.d.ts +81 -2
  24. package/dist/core/types.d.ts.map +1 -1
  25. package/dist/core/types.js +40 -0
  26. package/dist/core/types.js.map +1 -1
  27. package/dist/feedback/confidence-gate.d.ts +28 -0
  28. package/dist/feedback/confidence-gate.d.ts.map +1 -0
  29. package/dist/feedback/feedback-formatter.d.ts +21 -0
  30. package/dist/feedback/feedback-formatter.d.ts.map +1 -0
  31. package/dist/feedback/index.d.ts +11 -0
  32. package/dist/feedback/index.d.ts.map +1 -0
  33. package/dist/feedback/pattern-tracker.d.ts +47 -0
  34. package/dist/feedback/pattern-tracker.d.ts.map +1 -0
  35. package/dist/feedback/types.d.ts +113 -0
  36. package/dist/feedback/types.d.ts.map +1 -0
  37. package/dist/generation/index.js +2 -1
  38. package/dist/generation/index.js.map +1 -1
  39. package/dist/index.cjs +3264 -132
  40. package/dist/index.cjs.map +1 -1
  41. package/dist/index.d.ts +8 -2
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +3223 -132
  44. package/dist/index.js.map +1 -1
  45. package/dist/ir/explicit-parser.d.ts +86 -0
  46. package/dist/ir/explicit-parser.d.ts.map +1 -0
  47. package/dist/ir/explicit-renderer.d.ts +34 -0
  48. package/dist/ir/explicit-renderer.d.ts.map +1 -0
  49. package/dist/ir/from-interchange.d.ts +51 -0
  50. package/dist/ir/from-interchange.d.ts.map +1 -0
  51. package/dist/ir/index.d.ts +31 -0
  52. package/dist/ir/index.d.ts.map +1 -0
  53. package/dist/ir/index.js +1934 -0
  54. package/dist/ir/index.js.map +1 -0
  55. package/dist/ir/json-schema.d.ts +40 -0
  56. package/dist/ir/json-schema.d.ts.map +1 -0
  57. package/dist/ir/protocol-json.d.ts +73 -0
  58. package/dist/ir/protocol-json.d.ts.map +1 -0
  59. package/dist/ir/references.d.ts +19 -0
  60. package/dist/ir/references.d.ts.map +1 -0
  61. package/dist/ir/to-runtime-ast.d.ts +53 -0
  62. package/dist/ir/to-runtime-ast.d.ts.map +1 -0
  63. package/dist/ir/types.d.ts +151 -0
  64. package/dist/ir/types.d.ts.map +1 -0
  65. package/dist/parsing/index.js +74 -10
  66. package/dist/parsing/index.js.map +1 -1
  67. package/dist/prompts/index.d.ts +9 -0
  68. package/dist/prompts/index.d.ts.map +1 -0
  69. package/dist/prompts/prompt-generator.d.ts +49 -0
  70. package/dist/prompts/prompt-generator.d.ts.map +1 -0
  71. package/dist/prompts/types.d.ts +64 -0
  72. package/dist/prompts/types.d.ts.map +1 -0
  73. package/dist/schema/command-schema.d.ts +17 -0
  74. package/dist/schema/command-schema.d.ts.map +1 -1
  75. package/dist/schema/index.js.map +1 -1
  76. package/dist/testing/index.js +8673 -8260
  77. package/dist/testing/index.js.map +1 -1
  78. package/dist/training/index.d.ts +11 -0
  79. package/dist/training/index.d.ts.map +1 -0
  80. package/dist/training/jsonl-writer.d.ts +42 -0
  81. package/dist/training/jsonl-writer.d.ts.map +1 -0
  82. package/dist/training/schema-synthesizer.d.ts +20 -0
  83. package/dist/training/schema-synthesizer.d.ts.map +1 -0
  84. package/dist/training/types.d.ts +73 -0
  85. package/dist/training/types.d.ts.map +1 -0
  86. package/package.json +5 -1
  87. package/src/aot/index.ts +1 -0
  88. package/src/aot/registry-bridge.test.ts +104 -0
  89. package/src/aot/registry-bridge.ts +66 -0
  90. package/src/api/create-dsl.test.ts +306 -0
  91. package/src/api/create-dsl.ts +21 -0
  92. package/src/api/dispatcher.test.ts +66 -0
  93. package/src/api/dispatcher.ts +77 -9
  94. package/src/api/domain-registry.ts +120 -4
  95. package/src/core/pattern-matching/pattern-matcher.test.ts +131 -0
  96. package/src/core/pattern-matching/pattern-matcher.ts +102 -19
  97. package/src/core/tokenization/morphology/base-normalizer.ts +249 -0
  98. package/src/core/tokenization/morphology/index.ts +3 -1
  99. package/src/core/types.ts +147 -2
  100. package/src/feedback/confidence-gate.test.ts +111 -0
  101. package/src/feedback/confidence-gate.ts +70 -0
  102. package/src/feedback/feedback-formatter.test.ts +198 -0
  103. package/src/feedback/feedback-formatter.ts +298 -0
  104. package/src/feedback/index.ts +24 -0
  105. package/src/feedback/pattern-tracker.test.ts +198 -0
  106. package/src/feedback/pattern-tracker.ts +140 -0
  107. package/src/feedback/types.ts +149 -0
  108. package/src/generation/pattern-generator.ts +2 -2
  109. package/src/index.ts +29 -0
  110. package/src/integration/llm-lse-integration.test.ts +457 -0
  111. package/src/ir/conformance.test.ts +120 -0
  112. package/src/ir/explicit-parser.test.ts +612 -0
  113. package/src/ir/explicit-parser.ts +793 -0
  114. package/src/ir/explicit-renderer.test.ts +229 -0
  115. package/src/ir/explicit-renderer.ts +198 -0
  116. package/src/ir/from-interchange.test.ts +853 -0
  117. package/src/ir/from-interchange.ts +594 -0
  118. package/src/ir/index.ts +77 -0
  119. package/src/ir/json-schema.test.ts +281 -0
  120. package/src/ir/json-schema.ts +299 -0
  121. package/src/ir/protocol-json.test.ts +1187 -0
  122. package/src/ir/protocol-json.ts +751 -0
  123. package/src/ir/references.test.ts +38 -0
  124. package/src/ir/references.ts +33 -0
  125. package/src/ir/round-trip.test.ts +557 -0
  126. package/src/ir/to-runtime-ast.ts +203 -0
  127. package/src/ir/types.ts +191 -0
  128. package/src/prompts/index.ts +15 -0
  129. package/src/prompts/prompt-generator.test.ts +386 -0
  130. package/src/prompts/prompt-generator.ts +531 -0
  131. package/src/prompts/types.ts +89 -0
  132. package/src/schema/command-schema.ts +19 -0
  133. package/src/training/index.ts +13 -0
  134. package/src/training/jsonl-writer.test.ts +138 -0
  135. package/src/training/jsonl-writer.ts +67 -0
  136. package/src/training/schema-synthesizer.test.ts +250 -0
  137. package/src/training/schema-synthesizer.ts +306 -0
  138. package/src/training/types.ts +103 -0
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Tests for Pattern Hit-Rate Tracker
3
+ */
4
+
5
+ import { describe, it, expect, beforeEach } from 'vitest';
6
+ import { PatternTracker } from './pattern-tracker';
7
+ import type { PatternEvent } from './types';
8
+
9
+ // =============================================================================
10
+ // Test Helpers
11
+ // =============================================================================
12
+
13
+ function makeEvent(overrides?: Partial<PatternEvent>): PatternEvent {
14
+ return {
15
+ timestamp: Date.now(),
16
+ domain: 'flow',
17
+ action: 'fetch',
18
+ language: 'en',
19
+ inputFormat: 'explicit',
20
+ confidence: 0.95,
21
+ outcome: 'accepted',
22
+ ...overrides,
23
+ };
24
+ }
25
+
26
+ // =============================================================================
27
+ // PatternTracker
28
+ // =============================================================================
29
+
30
+ describe('PatternTracker', () => {
31
+ let tracker: PatternTracker;
32
+
33
+ beforeEach(() => {
34
+ tracker = new PatternTracker();
35
+ });
36
+
37
+ // --- Basic recording ---
38
+
39
+ it('starts empty', () => {
40
+ expect(tracker.size).toBe(0);
41
+ });
42
+
43
+ it('records events', () => {
44
+ tracker.record(makeEvent());
45
+ expect(tracker.size).toBe(1);
46
+ });
47
+
48
+ it('records multiple events', () => {
49
+ tracker.record(makeEvent());
50
+ tracker.record(makeEvent({ action: 'toggle' }));
51
+ tracker.record(makeEvent({ action: 'add' }));
52
+ expect(tracker.size).toBe(3);
53
+ });
54
+
55
+ // --- Ring buffer ---
56
+
57
+ it('enforces ring buffer limit', () => {
58
+ const small = new PatternTracker(5);
59
+ for (let i = 0; i < 10; i++) {
60
+ small.record(makeEvent({ action: `action-${i}` }));
61
+ }
62
+ expect(small.size).toBe(5);
63
+ });
64
+
65
+ it('keeps newest events when buffer overflows', () => {
66
+ const small = new PatternTracker(3);
67
+ for (let i = 0; i < 5; i++) {
68
+ small.record(makeEvent({ action: `action-${i}` }));
69
+ }
70
+ const summary = small.getSummary();
71
+ // Should only have action-2, action-3, action-4
72
+ expect(summary.byCommand['action-0']).toBeUndefined();
73
+ expect(summary.byCommand['action-1']).toBeUndefined();
74
+ expect(summary.byCommand['action-2']).toBeDefined();
75
+ });
76
+
77
+ // --- Hit rate by command ---
78
+
79
+ it('computes hit rate by command', () => {
80
+ tracker.record(makeEvent({ action: 'fetch', outcome: 'accepted' }));
81
+ tracker.record(makeEvent({ action: 'fetch', outcome: 'accepted' }));
82
+ tracker.record(makeEvent({ action: 'fetch', outcome: 'rejected' }));
83
+ tracker.record(makeEvent({ action: 'toggle', outcome: 'accepted' }));
84
+
85
+ const rates = tracker.getHitRateByCommand();
86
+ expect(rates['fetch'].attempts).toBe(3);
87
+ expect(rates['fetch'].successes).toBe(2);
88
+ expect(rates['fetch'].rate).toBeCloseTo(2 / 3);
89
+ expect(rates['toggle'].rate).toBe(1);
90
+ });
91
+
92
+ // --- Hit rate by language ---
93
+
94
+ it('computes hit rate by language', () => {
95
+ tracker.record(makeEvent({ language: 'en', outcome: 'accepted' }));
96
+ tracker.record(makeEvent({ language: 'en', outcome: 'rejected' }));
97
+ tracker.record(makeEvent({ language: 'ja', outcome: 'accepted' }));
98
+
99
+ const rates = tracker.getHitRateByLanguage();
100
+ expect(rates['en'].attempts).toBe(2);
101
+ expect(rates['en'].rate).toBe(0.5);
102
+ expect(rates['ja'].rate).toBe(1);
103
+ });
104
+
105
+ // --- Top failures ---
106
+
107
+ it('computes top failures by diagnostic code', () => {
108
+ tracker.record(makeEvent({ outcome: 'rejected', diagnosticCodes: ['missing-role'] }));
109
+ tracker.record(makeEvent({ outcome: 'rejected', diagnosticCodes: ['missing-role'] }));
110
+ tracker.record(makeEvent({ outcome: 'rejected', diagnosticCodes: ['unknown-command'] }));
111
+
112
+ const failures = tracker.getTopFailures();
113
+ expect(failures[0].code).toBe('missing-role');
114
+ expect(failures[0].count).toBe(2);
115
+ expect(failures[1].code).toBe('unknown-command');
116
+ expect(failures[1].count).toBe(1);
117
+ });
118
+
119
+ it('tracks which actions trigger each failure', () => {
120
+ tracker.record(
121
+ makeEvent({ action: 'fetch', outcome: 'rejected', diagnosticCodes: ['missing-role'] })
122
+ );
123
+ tracker.record(
124
+ makeEvent({ action: 'toggle', outcome: 'rejected', diagnosticCodes: ['missing-role'] })
125
+ );
126
+
127
+ const failures = tracker.getTopFailures();
128
+ expect(failures[0].actions).toContain('fetch');
129
+ expect(failures[0].actions).toContain('toggle');
130
+ });
131
+
132
+ it('limits top failures to requested count', () => {
133
+ for (let i = 0; i < 20; i++) {
134
+ tracker.record(makeEvent({ outcome: 'rejected', diagnosticCodes: [`code-${i}`] }));
135
+ }
136
+
137
+ const failures = tracker.getTopFailures(5);
138
+ expect(failures.length).toBe(5);
139
+ });
140
+
141
+ it('ignores non-rejected events for failures', () => {
142
+ tracker.record(makeEvent({ outcome: 'accepted', diagnosticCodes: ['some-code'] }));
143
+ const failures = tracker.getTopFailures();
144
+ expect(failures.length).toBe(0);
145
+ });
146
+
147
+ it('ignores rejected events without diagnostic codes', () => {
148
+ tracker.record(makeEvent({ outcome: 'rejected' }));
149
+ const failures = tracker.getTopFailures();
150
+ expect(failures.length).toBe(0);
151
+ });
152
+
153
+ // --- Summary ---
154
+
155
+ it('produces a complete summary', () => {
156
+ tracker.record(makeEvent({ outcome: 'accepted' }));
157
+ tracker.record(makeEvent({ outcome: 'rejected', diagnosticCodes: ['err'] }));
158
+ tracker.record(makeEvent({ outcome: 'disambiguated' }));
159
+
160
+ const summary = tracker.getSummary();
161
+ expect(summary.totalEvents).toBe(3);
162
+ expect(summary.byOutcome['accepted']).toBe(1);
163
+ expect(summary.byOutcome['rejected']).toBe(1);
164
+ expect(summary.byOutcome['disambiguated']).toBe(1);
165
+ expect(summary.byCommand).toBeDefined();
166
+ expect(summary.byLanguage).toBeDefined();
167
+ expect(summary.topFailures.length).toBe(1);
168
+ });
169
+
170
+ // --- JSONL export ---
171
+
172
+ it('exports events as JSONL', () => {
173
+ tracker.record(makeEvent({ action: 'fetch' }));
174
+ tracker.record(makeEvent({ action: 'toggle' }));
175
+
176
+ const jsonl = tracker.exportJSONL();
177
+ const lines = jsonl.split('\n');
178
+ expect(lines.length).toBe(2);
179
+
180
+ const parsed0 = JSON.parse(lines[0]);
181
+ expect(parsed0.action).toBe('fetch');
182
+ const parsed1 = JSON.parse(lines[1]);
183
+ expect(parsed1.action).toBe('toggle');
184
+ });
185
+
186
+ it('exports empty string when no events', () => {
187
+ expect(tracker.exportJSONL()).toBe('');
188
+ });
189
+
190
+ // --- Clear ---
191
+
192
+ it('clears all events', () => {
193
+ tracker.record(makeEvent());
194
+ tracker.record(makeEvent());
195
+ tracker.clear();
196
+ expect(tracker.size).toBe(0);
197
+ });
198
+ });
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Pattern Hit-Rate Tracker
3
+ *
4
+ * Records pattern events in a ring buffer and computes hit-rate
5
+ * statistics by command, language, and diagnostic code. Patterns
6
+ * with high rejected/attempts ratios indicate miscalibrated confidence.
7
+ */
8
+
9
+ import type { PatternEvent, HitRate, PatternTrackerSummary, TopFailure } from './types';
10
+
11
+ // =============================================================================
12
+ // Public API
13
+ // =============================================================================
14
+
15
+ export class PatternTracker {
16
+ private events: PatternEvent[] = [];
17
+ private readonly maxEvents: number;
18
+
19
+ constructor(maxEvents: number = 1000) {
20
+ this.maxEvents = maxEvents;
21
+ }
22
+
23
+ /**
24
+ * Record a pattern event.
25
+ */
26
+ record(event: PatternEvent): void {
27
+ this.events.push(event);
28
+ // Ring buffer: drop oldest when full
29
+ if (this.events.length > this.maxEvents) {
30
+ this.events = this.events.slice(this.events.length - this.maxEvents);
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Get hit rate by command action.
36
+ */
37
+ getHitRateByCommand(): Record<string, HitRate> {
38
+ return this.computeHitRate(e => e.action);
39
+ }
40
+
41
+ /**
42
+ * Get hit rate by language.
43
+ */
44
+ getHitRateByLanguage(): Record<string, HitRate> {
45
+ return this.computeHitRate(e => e.language);
46
+ }
47
+
48
+ /**
49
+ * Get the most frequent failure diagnostic codes.
50
+ */
51
+ getTopFailures(limit: number = 10): TopFailure[] {
52
+ const codeMap = new Map<string, { count: number; actions: Set<string> }>();
53
+
54
+ for (const event of this.events) {
55
+ if (event.outcome !== 'rejected' || !event.diagnosticCodes) continue;
56
+ for (const code of event.diagnosticCodes) {
57
+ const entry = codeMap.get(code) || { count: 0, actions: new Set() };
58
+ entry.count++;
59
+ entry.actions.add(event.action);
60
+ codeMap.set(code, entry);
61
+ }
62
+ }
63
+
64
+ return Array.from(codeMap.entries())
65
+ .map(([code, { count, actions }]) => ({
66
+ code,
67
+ count,
68
+ actions: Array.from(actions),
69
+ }))
70
+ .sort((a, b) => b.count - a.count)
71
+ .slice(0, limit);
72
+ }
73
+
74
+ /**
75
+ * Get a complete summary of tracking data.
76
+ */
77
+ getSummary(): PatternTrackerSummary {
78
+ const byOutcome: Record<string, number> = {};
79
+ for (const event of this.events) {
80
+ byOutcome[event.outcome] = (byOutcome[event.outcome] || 0) + 1;
81
+ }
82
+
83
+ return {
84
+ totalEvents: this.events.length,
85
+ byOutcome,
86
+ byCommand: this.getHitRateByCommand(),
87
+ byLanguage: this.getHitRateByLanguage(),
88
+ topFailures: this.getTopFailures(),
89
+ };
90
+ }
91
+
92
+ /**
93
+ * Export all events as JSONL.
94
+ */
95
+ exportJSONL(): string {
96
+ return this.events.map(e => JSON.stringify(e)).join('\n');
97
+ }
98
+
99
+ /**
100
+ * Get the number of recorded events.
101
+ */
102
+ get size(): number {
103
+ return this.events.length;
104
+ }
105
+
106
+ /**
107
+ * Clear all events.
108
+ */
109
+ clear(): void {
110
+ this.events = [];
111
+ }
112
+
113
+ // ---------------------------------------------------------------------------
114
+ // Private
115
+ // ---------------------------------------------------------------------------
116
+
117
+ private computeHitRate(keyFn: (e: PatternEvent) => string): Record<string, HitRate> {
118
+ const map = new Map<string, { attempts: number; successes: number }>();
119
+
120
+ for (const event of this.events) {
121
+ const key = keyFn(event);
122
+ const entry = map.get(key) || { attempts: 0, successes: 0 };
123
+ entry.attempts++;
124
+ if (event.outcome === 'accepted') {
125
+ entry.successes++;
126
+ }
127
+ map.set(key, entry);
128
+ }
129
+
130
+ const result: Record<string, HitRate> = {};
131
+ for (const [key, { attempts, successes }] of map) {
132
+ result[key] = {
133
+ attempts,
134
+ successes,
135
+ rate: attempts > 0 ? successes / attempts : 0,
136
+ };
137
+ }
138
+ return result;
139
+ }
140
+ }
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Feedback Loop Types
3
+ *
4
+ * Types for structured error feedback, confidence-aware disambiguation,
5
+ * and pattern hit-rate tracking in the LLM ↔ LSE integration.
6
+ */
7
+
8
+ import type { SemanticJSON } from '../ir/types';
9
+
10
+ // =============================================================================
11
+ // Structured Error Feedback (Level 1)
12
+ // =============================================================================
13
+
14
+ /**
15
+ * Structured feedback for an LSE validation attempt.
16
+ */
17
+ export interface LSEFeedback {
18
+ /** Whether the input was accepted (no errors) */
19
+ readonly accepted: boolean;
20
+
21
+ /** The original input */
22
+ readonly input: {
23
+ readonly format: 'explicit' | 'json' | 'natural';
24
+ readonly text: string;
25
+ };
26
+
27
+ /** Machine-actionable diagnostics */
28
+ readonly diagnostics: readonly FeedbackDiagnostic[];
29
+
30
+ /** Human-readable hints for retrying */
31
+ readonly hints: readonly string[];
32
+
33
+ /** Valid schema structure for the attempted command (if identifiable) */
34
+ readonly schema?: {
35
+ readonly action: string;
36
+ readonly requiredRoles: readonly string[];
37
+ readonly optionalRoles: readonly string[];
38
+ readonly roleDescriptions: Readonly<Record<string, string>>;
39
+ };
40
+
41
+ /** Corrected example (if fixable) */
42
+ readonly correctedExample?: {
43
+ readonly explicit: string;
44
+ readonly json: SemanticJSON;
45
+ };
46
+ }
47
+
48
+ /**
49
+ * A single diagnostic with machine-actionable fix type.
50
+ */
51
+ export interface FeedbackDiagnostic {
52
+ readonly severity: 'error' | 'warning' | 'info';
53
+ readonly code: string;
54
+ readonly message: string;
55
+ readonly suggestion?: string;
56
+ readonly fixType?: FixType;
57
+ }
58
+
59
+ /**
60
+ * Machine-actionable fix type for LLM retry logic.
61
+ */
62
+ export type FixType =
63
+ | 'missing_role'
64
+ | 'invalid_type'
65
+ | 'unknown_command'
66
+ | 'unknown_role'
67
+ | 'syntax_error';
68
+
69
+ // =============================================================================
70
+ // Confidence-Aware Disambiguation (Level 2)
71
+ // =============================================================================
72
+
73
+ /**
74
+ * A disambiguation request presented when confidence is borderline.
75
+ */
76
+ export interface DisambiguationRequest {
77
+ /** The original input that was ambiguous */
78
+ readonly input: string;
79
+
80
+ /** Candidate interpretations ranked by confidence */
81
+ readonly candidates: readonly DisambiguationCandidate[];
82
+
83
+ /** Human/LLM-readable disambiguation prompt */
84
+ readonly question: string;
85
+ }
86
+
87
+ /**
88
+ * A single candidate interpretation.
89
+ */
90
+ export interface DisambiguationCandidate {
91
+ /** Command action */
92
+ readonly action: string;
93
+
94
+ /** Confidence score */
95
+ readonly confidence: number;
96
+
97
+ /** Canonical LSE for this interpretation */
98
+ readonly explicit: string;
99
+
100
+ /** Human-readable description */
101
+ readonly description: string;
102
+ }
103
+
104
+ // =============================================================================
105
+ // Pattern Hit-Rate Instrumentation (Level 3)
106
+ // =============================================================================
107
+
108
+ /**
109
+ * A single pattern event for hit-rate tracking.
110
+ */
111
+ export interface PatternEvent {
112
+ readonly timestamp: number;
113
+ readonly domain: string;
114
+ readonly action: string;
115
+ readonly language: string;
116
+ readonly inputFormat: 'explicit' | 'json' | 'natural';
117
+ readonly confidence: number;
118
+ readonly outcome: 'accepted' | 'rejected' | 'disambiguated';
119
+ readonly diagnosticCodes?: readonly string[];
120
+ }
121
+
122
+ /**
123
+ * Hit-rate statistics for a category.
124
+ */
125
+ export interface HitRate {
126
+ readonly attempts: number;
127
+ readonly successes: number;
128
+ readonly rate: number;
129
+ }
130
+
131
+ /**
132
+ * Summary of pattern tracking data.
133
+ */
134
+ export interface PatternTrackerSummary {
135
+ readonly totalEvents: number;
136
+ readonly byOutcome: Readonly<Record<string, number>>;
137
+ readonly byCommand: Readonly<Record<string, HitRate>>;
138
+ readonly byLanguage: Readonly<Record<string, HitRate>>;
139
+ readonly topFailures: readonly TopFailure[];
140
+ }
141
+
142
+ /**
143
+ * A frequently failing diagnostic code.
144
+ */
145
+ export interface TopFailure {
146
+ readonly code: string;
147
+ readonly count: number;
148
+ readonly actions: readonly string[];
149
+ }
@@ -165,9 +165,9 @@ function addRoleWithMarker(
165
165
 
166
166
  if (marker) {
167
167
  const markerInfo = profile.roleMarkers?.[roleSpec.role];
168
- // Default: SOV languages use postpositions (after), others prepositions (before)
168
+ // Priority: schema markerPosition → profile roleMarkers position → word-order default
169
169
  const defaultPosition = profile.wordOrder === 'SOV' ? 'after' : 'before';
170
- const position = markerInfo?.position ?? defaultPosition;
170
+ const position = roleSpec.markerPosition ?? markerInfo?.position ?? defaultPosition;
171
171
 
172
172
  if (isOptional) {
173
173
  // Optional role: wrap marker + role in optional group
package/src/index.ts CHANGED
@@ -71,6 +71,12 @@ export type {
71
71
  TokenStream,
72
72
  LanguageTokenizer,
73
73
  LanguagePattern,
74
+ // v1.2 types
75
+ Annotation,
76
+ ProtocolDiagnostic,
77
+ AsyncVariant,
78
+ MatchArm,
79
+ LSEEnvelope,
74
80
  } from './core/types';
75
81
 
76
82
  export type { CommandSchema, RoleSpec } from './schema';
@@ -135,12 +141,35 @@ export {
135
141
  createLoopNode,
136
142
  extractValue,
137
143
  extractRoleValue,
144
+ // v1.2 factories
145
+ createTryNode,
146
+ createAsyncNode,
147
+ createMatchNode,
138
148
  } from './core/types';
139
149
 
140
150
  export { defineCommand, defineRole } from './schema';
141
151
  export { createSimpleTokenizer } from './core/tokenization/base-tokenizer';
142
152
  export type { SimpleTokenizerConfig } from './core/tokenization/base-tokenizer';
143
153
 
154
+ // Morphological normalization base class and types
155
+ export { BaseMorphologicalNormalizer } from './core/tokenization/morphology/base-normalizer';
156
+ export type {
157
+ ConjugationEnding,
158
+ NormalizerConfig,
159
+ } from './core/tokenization/morphology/base-normalizer';
160
+
161
+ // IR (Intermediate Representation) — explicit syntax, JSON conversion, reference validation
162
+ export * from './ir';
163
+
164
+ // LLM Prompt Generation — auto-generate system prompts from CommandSchema[]
165
+ export * from './prompts';
166
+
167
+ // Training Data Generation — synthesize (natural_language, LSE) pairs from schemas
168
+ export * from './training';
169
+
170
+ // Feedback Loop — structured errors, disambiguation, pattern tracking
171
+ export * from './feedback';
172
+
144
173
  // Multi-statement parser
145
174
  export { createMultiStatementParser, accumulateBlocks } from './parsing/multi-statement';
146
175
  export type {