@ldclabs/kip-lang 2.1.0 → 2.3.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.
package/src/semantics.ts CHANGED
@@ -48,13 +48,27 @@ const MODES = new Set([
48
48
  'imported'
49
49
  ])
50
50
  const SEARCH_MODES = new Set(['keyword', 'semantic', 'hybrid'])
51
- const ASSERTION_STATES = new Set([
52
- 'active',
51
+ /**
52
+ * Everything `TRANSITION ... TO` may name (Spec §52.5): Assertion revision,
53
+ * Evidence correction, Activity status, and the storage lifecycle any element
54
+ * has. The engine matches the state to the target's kind; the toolkit can only
55
+ * reject a word that belongs to none of them.
56
+ */
57
+ const TRANSITION_STATES = new Set([
53
58
  'retracted',
54
59
  'superseded',
55
- 'expired'
60
+ 'corrected',
61
+ 'running',
62
+ 'completed',
63
+ 'failed',
64
+ 'cancelled',
65
+ 'archived',
66
+ 'tombstoned'
56
67
  ])
57
- const ACTIVITY_TERMINAL = new Set(['completed', 'failed', 'cancelled'])
68
+ /** Moves that name the replacing element with `BY`. */
69
+ const TRANSITION_WITH_BY = new Set(['superseded', 'corrected'])
70
+ /** Moves that may finalize an Activity's fields and topology. */
71
+ const ACTIVITY_STATES = new Set(['running', 'completed', 'failed', 'cancelled'])
58
72
  const EVIDENCE_ROLES = new Set(['support', 'challenge', 'context'])
59
73
 
60
74
  /** Signals the Profile fixes to `[0,1]`; none of them is truth. */
@@ -127,36 +141,44 @@ function analyzeMutationClause(stmt: Statement, diags: Diagnostic[]): void {
127
141
  if (stmt.where) checkWhere(stmt.where, !!stmt.limit, diags)
128
142
  break
129
143
 
130
- // `EXPECT STATE` is checkable only where the target's kind is fixed by the
131
- // statement itself. RETRACT and SUPERSEDE always name an Assertion, so the
132
- // Assertion lifecycle registry applies. ARCHIVE and TOMBSTONE take any
133
- // element — a Concept is not `retracted` and may well be `archived` — and
134
- // Core registers no element-lifecycle vocabulary, so checking them here
135
- // rejected commands the Specification admits.
136
- case 'RetractAssertionStatement':
137
- if (stmt.expectState) {
138
- checkEnum(stmt.expectState.value, ASSERTION_STATES, 'EXPECT STATE', diags)
139
- }
140
- if (stmt.where) checkWhere(stmt.where, !!stmt.limit, diags)
141
- break
142
-
143
- case 'SupersedeAssertionStatement':
144
- if (stmt.expectState) {
145
- checkEnum(stmt.expectState.value, ASSERTION_STATES, 'EXPECT STATE', diags)
144
+ // The target's kind is not known statically, so only the vocabulary is
145
+ // checkable: a state no kind has, a `BY` on a move that takes none, a
146
+ // finalize clause on a move that is not an Activity's.
147
+ case 'TransitionStatement': {
148
+ checkEnum(stmt.to, TRANSITION_STATES, 'TRANSITION TO', diags)
149
+ if (stmt.to.kind === 'StringLiteral') {
150
+ const to = stmt.to.parsed
151
+ if (TRANSITION_WITH_BY.has(to) && !stmt.by) {
152
+ diags.push({
153
+ range: stmt.to.range,
154
+ severity: 'error',
155
+ message: `TRANSITION TO "${to}" names the replacing element with BY`,
156
+ code: 'KIP_2001'
157
+ })
158
+ }
159
+ if (!TRANSITION_WITH_BY.has(to) && stmt.by && TRANSITION_STATES.has(to)) {
160
+ diags.push({
161
+ range: stmt.by.range,
162
+ severity: 'error',
163
+ message: `TRANSITION TO "${to}" takes no BY`,
164
+ code: 'KIP_2001'
165
+ })
166
+ }
167
+ if (stmt.finalize.length > 0 && !ACTIVITY_STATES.has(to) && TRANSITION_STATES.has(to)) {
168
+ diags.push({
169
+ range: stmt.finalize[0].range,
170
+ severity: 'error',
171
+ message: `TRANSITION TO "${to}" cannot finalize fields or topology; only a pending Activity does`,
172
+ code: 'KIP_2001'
173
+ })
174
+ }
146
175
  }
147
- break
148
-
149
- case 'ArchiveStatement':
150
- case 'TombstoneStatement':
151
- if (stmt.where) checkWhere(stmt.where, !!stmt.limit, diags)
152
- break
153
-
154
- case 'TransitionActivityStatement':
155
- checkEnum(stmt.to, ACTIVITY_TERMINAL, 'TRANSITION ACTIVITY TO', diags)
156
176
  checkStructural(stmt.finalize.find(
157
177
  (c): c is SetStructuralClause => c.kind === 'SetStructuralClause'
158
178
  ), diags)
179
+ if (stmt.where) checkWhere(stmt.where, !!stmt.limit, diags)
159
180
  break
181
+ }
160
182
 
161
183
  // Spec §52.7 names seven statements whose WHERE can select an unbounded
162
184
  // set and which SHOULD therefore carry a LIMIT. Warning on the read and on
@@ -377,12 +399,15 @@ function collectHandleRefs(
377
399
  }
378
400
  break
379
401
 
380
- case 'SupersedeAssertionStatement':
381
- case 'CorrectEvidenceStatement':
382
- for (const ref of [clause.target, clause.by]) {
383
- if (ref.kind === 'VariableRef') {
384
- out.push({ name: ref.name.slice(1), range: ref.range })
385
- }
402
+ case 'TransitionStatement':
403
+ // `BY ?new` resolves inside the plan; a `?target` is bound by WHERE or
404
+ // by a handle, so only the replacing element is a plan reference.
405
+ if (clause.by && clause.by.kind === 'VariableRef') {
406
+ out.push({ name: clause.by.name.slice(1), range: clause.by.range })
407
+ }
408
+ for (const fin of clause.finalize) {
409
+ if (fin.kind === 'SetFieldsClause') fromObject(fin.assignments)
410
+ else for (const edge of fin.assignments) fromExpression(edge.value)
386
411
  }
387
412
  break
388
413
  }
package/src/token.ts CHANGED
@@ -33,8 +33,8 @@ export enum TokenType {
33
33
  Distinct = 'DISTINCT',
34
34
  As = 'AS',
35
35
  Of = 'OF',
36
+ At = 'AT',
36
37
  Seq = 'SEQ',
37
- Tx = 'TX',
38
38
  Time = 'TIME',
39
39
  For = 'FOR',
40
40
  Epistemic = 'EPISTEMIC',
@@ -55,15 +55,10 @@ export enum TokenType {
55
55
  Assert = 'ASSERT',
56
56
  Superseding = 'SUPERSEDING',
57
57
  Update = 'UPDATE',
58
- Retract = 'RETRACT',
59
- Supersede = 'SUPERSEDE',
60
- Correct = 'CORRECT',
61
58
  Transition = 'TRANSITION',
62
59
  Set = 'SET',
63
60
  Unset = 'UNSET',
64
61
  Retention = 'RETENTION',
65
- Archive = 'ARCHIVE',
66
- Tombstone = 'TOMBSTONE',
67
62
  Purge = 'PURGE',
68
63
  Payload = 'PAYLOAD',
69
64
  Confirm = 'CONFIRM',
@@ -82,7 +77,6 @@ export enum TokenType {
82
77
  Facet = 'FACET',
83
78
  Expect = 'EXPECT',
84
79
  Version = 'VERSION',
85
- State = 'STATE',
86
80
 
87
81
  // ── Keywords — META ───────────────────────────────────────────────
88
82
  Describe = 'DESCRIBE',
@@ -98,10 +92,7 @@ export enum TokenType {
98
92
  Primer = 'PRIMER',
99
93
  Mode = 'MODE',
100
94
  Protocol = 'PROTOCOL',
101
- Execution = 'EXECUTION',
102
- Context = 'CONTEXT',
103
95
  Capabilities = 'CAPABILITIES',
104
- Capability = 'CAPABILITY',
105
96
  Space = 'SPACE',
106
97
  Spaces = 'SPACES',
107
98
  Schema = 'SCHEMA',
@@ -122,7 +113,6 @@ export enum TokenType {
122
113
  Transaction = 'TRANSACTION',
123
114
  Idempotency = 'IDEMPOTENCY',
124
115
  Capsule = 'CAPSULE',
125
- Projection = 'PROJECTION',
126
116
  Trust = 'TRUST',
127
117
  Access = 'ACCESS',
128
118
  With = 'WITH',
@@ -130,8 +120,6 @@ export enum TokenType {
130
120
  Cognition = 'COGNITION',
131
121
  Threshold = 'THRESHOLD',
132
122
  Receipt = 'RECEIPT',
133
- Blob = 'BLOB',
134
- Checkpoint = 'CHECKPOINT',
135
123
  Kql = 'KQL',
136
124
  Kml = 'KML',
137
125
  Import = 'IMPORT',
@@ -216,8 +204,8 @@ export const KEYWORDS: ReadonlyMap<string, TokenType> = new Map([
216
204
  ['DISTINCT', TokenType.Distinct],
217
205
  ['AS', TokenType.As],
218
206
  ['OF', TokenType.Of],
207
+ ['AT', TokenType.At],
219
208
  ['SEQ', TokenType.Seq],
220
- ['TX', TokenType.Tx],
221
209
  ['TIME', TokenType.Time],
222
210
  ['FOR', TokenType.For],
223
211
  ['EPISTEMIC', TokenType.Epistemic],
@@ -238,15 +226,10 @@ export const KEYWORDS: ReadonlyMap<string, TokenType> = new Map([
238
226
  ['ASSERT', TokenType.Assert],
239
227
  ['SUPERSEDING', TokenType.Superseding],
240
228
  ['UPDATE', TokenType.Update],
241
- ['RETRACT', TokenType.Retract],
242
- ['SUPERSEDE', TokenType.Supersede],
243
- ['CORRECT', TokenType.Correct],
244
229
  ['TRANSITION', TokenType.Transition],
245
230
  ['SET', TokenType.Set],
246
231
  ['UNSET', TokenType.Unset],
247
232
  ['RETENTION', TokenType.Retention],
248
- ['ARCHIVE', TokenType.Archive],
249
- ['TOMBSTONE', TokenType.Tombstone],
250
233
  ['PURGE', TokenType.Purge],
251
234
  ['PAYLOAD', TokenType.Payload],
252
235
  ['CONFIRM', TokenType.Confirm],
@@ -265,7 +248,6 @@ export const KEYWORDS: ReadonlyMap<string, TokenType> = new Map([
265
248
  ['FACET', TokenType.Facet],
266
249
  ['EXPECT', TokenType.Expect],
267
250
  ['VERSION', TokenType.Version],
268
- ['STATE', TokenType.State],
269
251
 
270
252
  // META
271
253
  ['DESCRIBE', TokenType.Describe],
@@ -281,10 +263,7 @@ export const KEYWORDS: ReadonlyMap<string, TokenType> = new Map([
281
263
  ['PRIMER', TokenType.Primer],
282
264
  ['MODE', TokenType.Mode],
283
265
  ['PROTOCOL', TokenType.Protocol],
284
- ['EXECUTION', TokenType.Execution],
285
- ['CONTEXT', TokenType.Context],
286
266
  ['CAPABILITIES', TokenType.Capabilities],
287
- ['CAPABILITY', TokenType.Capability],
288
267
  ['SPACE', TokenType.Space],
289
268
  ['SPACES', TokenType.Spaces],
290
269
  ['SCHEMA', TokenType.Schema],
@@ -305,7 +284,6 @@ export const KEYWORDS: ReadonlyMap<string, TokenType> = new Map([
305
284
  ['TRANSACTION', TokenType.Transaction],
306
285
  ['IDEMPOTENCY', TokenType.Idempotency],
307
286
  ['CAPSULE', TokenType.Capsule],
308
- ['PROJECTION', TokenType.Projection],
309
287
  ['TRUST', TokenType.Trust],
310
288
  ['ACCESS', TokenType.Access],
311
289
  ['WITH', TokenType.With],
@@ -313,8 +291,6 @@ export const KEYWORDS: ReadonlyMap<string, TokenType> = new Map([
313
291
  ['COGNITION', TokenType.Cognition],
314
292
  ['THRESHOLD', TokenType.Threshold],
315
293
  ['RECEIPT', TokenType.Receipt],
316
- ['BLOB', TokenType.Blob],
317
- ['CHECKPOINT', TokenType.Checkpoint],
318
294
  ['KQL', TokenType.Kql],
319
295
  ['KML', TokenType.Kml],
320
296
  ['IMPORT', TokenType.Import],
package/src/version.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  * has to load in runtimes with no filesystem; `test/lower.test.mjs` asserts the
8
8
  * two stay in step.
9
9
  */
10
- export const PARSER_VERSION = '2.1.0'
10
+ export const PARSER_VERSION = '2.3.0'
11
11
 
12
12
  /** The KIP specification revision this grammar targets. */
13
13
  export const KIP_SPEC_REVISION = '2.0-draft'