@ldclabs/kip-lang 2.1.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.
package/src/exec-ast.ts CHANGED
@@ -172,7 +172,8 @@ export interface KqlQuery {
172
172
  cursor: Scalar | null
173
173
  }
174
174
 
175
- export type AsOf = { Seq: Scalar } | { Tx: Scalar } | { Time: Scalar }
175
+ /** Cognitive time is a sequence coordinate; ids and instants resolve to one first. */
176
+ export type AsOf = { Seq: Scalar }
176
177
 
177
178
  export interface FindClause {
178
179
  expressions: FindExpression[]
@@ -306,17 +307,27 @@ export type MutationClause =
306
307
  | { CreateAssertion: RecordCreate }
307
308
  | { CreateActivity: RecordCreate }
308
309
  | { Update: UpdateStatement }
309
- | { RetractAssertion: RetractAssertion }
310
- | { SupersedeAssertion: SupersedeAssertion }
311
- | { CorrectEvidence: CorrectEvidence }
312
- | { TransitionActivity: TransitionActivity }
310
+ | { Transition: Transition }
313
311
  | { SetRetention: SetRetention }
314
- | { Archive: RemovalStatement }
315
- | { Tombstone: RemovalStatement }
316
312
  | { Purge: PurgeStatement }
317
313
  | { PurgePayload: PurgePayloadStatement }
318
314
  | { MergeConcept: MergeConcept }
319
315
 
316
+ /**
317
+ * `EXPECT VERSION n [OF plane]` (Spec §35.1). Without a plane the guard is
318
+ * on the element's `_system.version`; with one, on that plane's own version.
319
+ */
320
+ export interface ExpectVersion {
321
+ version: Scalar
322
+ plane: VersionPlane | null
323
+ }
324
+
325
+ export type VersionPlane =
326
+ | 'Attributes'
327
+ | 'Structural'
328
+ | 'Retention'
329
+ | { Facet: SymbolRef }
330
+
320
331
  export interface ConceptCreate {
321
332
  handle: string
322
333
  type: SymbolRef | null
@@ -331,7 +342,7 @@ export interface ConceptCreate {
331
342
  export interface ConceptUpsert {
332
343
  handle: string
333
344
  match: ObjectMatcher | null
334
- expect_version: Scalar | null
345
+ expect_versions: ExpectVersion[]
335
346
  set_fields: Assignments | null
336
347
  set_attributes: Assignments | null
337
348
  set_facets: FacetAssignment[]
@@ -355,7 +366,7 @@ export interface EnsureProposition {
355
366
  subject: Term
356
367
  predicate: PredAtom
357
368
  object: Term
358
- expect_version: Scalar | null
369
+ expect_versions: ExpectVersion[]
359
370
  }
360
371
 
361
372
  export interface FacetAssignment {
@@ -406,14 +417,14 @@ export type UpdateFunction = 'Add' | 'Mul' | 'Clamp' | 'Coalesce'
406
417
 
407
418
  export interface UpdateStatement {
408
419
  target: ElementRef
409
- expect_version: Scalar | null
410
420
  actions: UpdateAction[]
411
421
  /**
412
422
  * `null` when the statement names its target directly and omits WHERE —
413
- * the same shape as the removal family (Spec §58).
423
+ * the same shape as TRANSITION and the removal family (Spec §58).
414
424
  */
415
425
  where_clauses: WhereClause[] | null
416
426
  limit: Scalar | null
427
+ expect_versions: ExpectVersion[]
417
428
  }
418
429
 
419
430
  export type UpdateAction =
@@ -425,52 +436,36 @@ export type UpdateAction =
425
436
  | { SetStructural: StructuralEdge[] }
426
437
  | { UnsetStructural: StructuralRemoval[] }
427
438
 
428
- export interface RetractAssertion {
429
- target: ElementRef
430
- where_clauses: WhereClause[] | null
431
- limit: Scalar | null
432
- expect_state: Scalar | null
433
- }
434
-
435
- export interface SupersedeAssertion {
436
- target: ElementRef
437
- by: ElementRef
438
- expect_state: Scalar | null
439
- }
440
-
441
- export interface CorrectEvidence {
442
- target: ElementRef
443
- by: ElementRef
444
- expect_state: Scalar | null
445
- }
446
-
447
- export interface TransitionActivity {
439
+ /**
440
+ * The one lifecycle statement (Spec §52.5): `to` names the move, the engine
441
+ * validates it against the target's kind and current state. `by` carries the
442
+ * replacing element for `superseded` / `corrected`; `set_fields` and
443
+ * `set_structural` finalize a pending Activity in the same transition.
444
+ */
445
+ export interface Transition {
448
446
  target: ElementRef
449
447
  to: Scalar
448
+ by: ElementRef | null
450
449
  set_fields: Assignments | null
451
450
  set_structural: StructuralEdge[] | null
452
- expect_state: Scalar | null
453
- }
454
-
455
- export interface SetRetention {
456
- target: ElementRef
457
- values: Assignments
458
451
  where_clauses: WhereClause[] | null
459
452
  limit: Scalar | null
460
- expect_version: Scalar | null
453
+ expect_versions: ExpectVersion[]
461
454
  }
462
455
 
463
- export interface RemovalStatement {
456
+ export interface SetRetention {
464
457
  target: ElementRef
458
+ values: Assignments
465
459
  where_clauses: WhereClause[] | null
466
460
  limit: Scalar | null
467
- expect_state: Scalar | null
461
+ expect_versions: ExpectVersion[]
468
462
  }
469
463
 
470
464
  export interface PurgeStatement {
471
465
  target: ElementRef
472
466
  where_clauses: WhereClause[] | null
473
467
  limit: Scalar | null
468
+ expect_versions: ExpectVersion[]
474
469
  reference_policy: Scalar | null
475
470
  /** Always the literal `PURGE`; the grammar freezes the spelling. */
476
471
  confirm: string
@@ -484,6 +479,7 @@ export interface PurgePayloadStatement {
484
479
  target: ElementRef
485
480
  where_clauses: WhereClause[] | null
486
481
  limit: Scalar | null
482
+ expect_versions: ExpectVersion[]
487
483
  /** Always the literal `PURGE`; the grammar freezes the spelling. */
488
484
  confirm: string
489
485
  }
@@ -492,7 +488,7 @@ export interface MergeConcept {
492
488
  source: ElementRef
493
489
  into: ElementRef
494
490
  where_clauses: WhereClause[] | null
495
- expect_version: Scalar | null
491
+ expect_versions: ExpectVersion[]
496
492
  }
497
493
 
498
494
  // ---------------------------------------------------------------------------
@@ -508,13 +504,11 @@ export type MetaCommand =
508
504
  | { Preview: PreviewCommand }
509
505
  | { History: HistoryCommand }
510
506
  | { Changes: ChangesCommand }
511
- | { Snapshot: { as_of: AsOf | null } }
512
507
  | { ExportCapsule: ExportCapsuleCommand }
513
508
 
514
509
  export type DescribeTarget =
515
510
  | { Primer: { mode: Scalar | null } }
516
511
  | 'Protocol'
517
- | 'ExecutionContext'
518
512
  | 'Capabilities'
519
513
  | { Space: { value: Scalar | null } }
520
514
  | { SchemaEnvironment: { as_of: AsOf | null } }
@@ -527,10 +521,9 @@ export type DescribeTarget =
527
521
  | { Error: Scalar }
528
522
  | { Transaction: Scalar }
529
523
  | { TransactionByIdempotencyKey: Scalar }
530
- | { Snapshot: { as_of: AsOf | null } }
524
+ | { Snapshot: { as_of: AsOf | null; at_time: Scalar | null } }
531
525
  | { Capsule: Scalar }
532
526
  | { EpistemicPolicy: { value: Scalar | null } }
533
- | 'ProjectionCapability'
534
527
  | { Trust: { value: Scalar | null } }
535
528
  | { Access: { with: Record<string, BoundValue> | null } }
536
529
 
package/src/formatter.ts CHANGED
@@ -34,13 +34,9 @@ import type {
34
34
  UnsetFacetClause,
35
35
  UpdateStatement,
36
36
  UpdateAction,
37
- RetractAssertionStatement,
38
- SupersedeAssertionStatement,
39
- CorrectEvidenceStatement,
40
- TransitionActivityStatement,
37
+ ExpectVersionClause,
38
+ TransitionStatement,
41
39
  SetRetentionStatement,
42
- ArchiveStatement,
43
- TombstoneStatement,
44
40
  PurgeStatement,
45
41
  PurgePayloadStatement,
46
42
  MergeConceptStatement,
@@ -52,7 +48,6 @@ import type {
52
48
  PreviewStatement,
53
49
  HistoryStatement,
54
50
  ChangesStatement,
55
- SnapshotStatement,
56
51
  ExportCapsuleStatement,
57
52
  Expression,
58
53
  ScalarValue,
@@ -198,9 +193,6 @@ class Formatter {
198
193
  case 'ChangesStatement':
199
194
  this.formatChanges(stmt)
200
195
  break
201
- case 'SnapshotStatement':
202
- this.formatSnapshot(stmt)
203
- break
204
196
  case 'ExportCapsuleStatement':
205
197
  this.formatExport(stmt)
206
198
  break
@@ -235,27 +227,12 @@ class Formatter {
235
227
  case 'UpdateStatement':
236
228
  this.formatUpdate(stmt)
237
229
  break
238
- case 'RetractAssertionStatement':
239
- this.formatRetract(stmt)
240
- break
241
- case 'SupersedeAssertionStatement':
242
- this.formatSupersede(stmt)
243
- break
244
- case 'CorrectEvidenceStatement':
245
- this.formatCorrect(stmt)
246
- break
247
- case 'TransitionActivityStatement':
230
+ case 'TransitionStatement':
248
231
  this.formatTransition(stmt)
249
232
  break
250
233
  case 'SetRetentionStatement':
251
234
  this.formatSetRetention(stmt)
252
235
  break
253
- case 'ArchiveStatement':
254
- this.formatRemoval('ARCHIVE', stmt)
255
- break
256
- case 'TombstoneStatement':
257
- this.formatRemoval('TOMBSTONE', stmt)
258
- break
259
236
  case 'PurgeStatement':
260
237
  this.formatPurge(stmt)
261
238
  break
@@ -329,7 +306,28 @@ class Formatter {
329
306
  }
330
307
 
331
308
  private asOfToString(clause: AsOfClause): string {
332
- return `AS OF ${clause.basis} ${this.scalar(clause.value)}`
309
+ return `AS OF SEQ ${this.scalar(clause.value)}`
310
+ }
311
+
312
+ private expectVersionToString(clause: ExpectVersionClause): string {
313
+ let text = `EXPECT VERSION ${this.scalar(clause.value)}`
314
+ if (clause.plane) {
315
+ text +=
316
+ clause.plane.kind === 'FACET'
317
+ ? ` OF FACET ${this.symbol(clause.plane.facet)}`
318
+ : ` OF ${clause.plane.kind}`
319
+ }
320
+ return text
321
+ }
322
+
323
+ /** Trailing guards, one per line at the statement's own indentation. */
324
+ private formatExpectVersions(clauses: ExpectVersionClause[]): void {
325
+ for (const clause of clauses) {
326
+ this.emitCommentsBefore(clause.range.start.line)
327
+ this.writeIndent()
328
+ this.write(this.expectVersionToString(clause))
329
+ this.newline()
330
+ }
333
331
  }
334
332
 
335
333
  // ────────────────────────────────────────────────────────────────────
@@ -602,17 +600,6 @@ class Formatter {
602
600
  }
603
601
  })
604
602
  }
605
- if (stmt.expectVersion) {
606
- const node = stmt.expectVersion
607
- clauses.push({
608
- node,
609
- print: () => {
610
- this.writeIndent()
611
- this.write(`EXPECT VERSION ${this.scalar(node.value)}`)
612
- this.newline()
613
- }
614
- })
615
- }
616
603
  if (stmt.setFields) {
617
604
  const node = stmt.setFields
618
605
  clauses.push({
@@ -655,6 +642,7 @@ class Formatter {
655
642
  stmt.range.end.line,
656
643
  clauses
657
644
  )
645
+ this.formatExpectVersions(stmt.expectVersions)
658
646
  }
659
647
 
660
648
  private formatRecordCreate(
@@ -702,8 +690,8 @@ class Formatter {
702
690
  this.write('ENSURE PROPOSITION ')
703
691
  if (stmt.handle) this.write(`${stmt.handle.name} `)
704
692
  this.write(this.tupleToString(stmt.tuple))
705
- if (stmt.expectVersion) {
706
- this.write(` EXPECT VERSION ${this.scalar(stmt.expectVersion.value)}`)
693
+ for (const clause of stmt.expectVersions) {
694
+ this.write(` ${this.expectVersionToString(clause)}`)
707
695
  }
708
696
  this.newline()
709
697
  }
@@ -730,12 +718,6 @@ class Formatter {
730
718
  this.write(`UPDATE ${this.targetRef(stmt.target)}`)
731
719
  this.newline()
732
720
 
733
- if (stmt.expectVersion) {
734
- this.emitCommentsBefore(stmt.expectVersion.range.start.line)
735
- this.writeIndent()
736
- this.write(`EXPECT VERSION ${this.scalar(stmt.expectVersion.value)}`)
737
- this.newline()
738
- }
739
721
  for (const action of stmt.actions) {
740
722
  this.emitCommentsBefore(action.range.start.line)
741
723
  this.formatUpdateAction(action)
@@ -748,6 +730,7 @@ class Formatter {
748
730
  this.emitCommentsBefore(stmt.limit.range.start.line)
749
731
  this.formatLimit(stmt.limit)
750
732
  }
733
+ this.formatExpectVersions(stmt.expectVersions)
751
734
  }
752
735
 
753
736
  private formatUpdateAction(action: UpdateAction): void {
@@ -780,52 +763,13 @@ class Formatter {
780
763
  }
781
764
  }
782
765
 
783
- private formatRetract(stmt: RetractAssertionStatement): void {
784
- this.writeIndent()
785
- this.write(`RETRACT ASSERTION ${this.targetRef(stmt.target)}`)
786
- if (!stmt.where && !stmt.limit && stmt.expectState) {
787
- this.write(` EXPECT STATE ${this.scalar(stmt.expectState.value)}`)
788
- this.newline()
789
- return
790
- }
791
- this.newline()
792
- if (stmt.where) this.formatWhere(stmt.where, 'WHERE')
793
- if (stmt.limit) this.formatLimit(stmt.limit)
794
- if (stmt.expectState) {
795
- this.writeIndent()
796
- this.write(`EXPECT STATE ${this.scalar(stmt.expectState.value)}`)
797
- this.newline()
798
- }
799
- }
800
-
801
- private formatSupersede(stmt: SupersedeAssertionStatement): void {
766
+ private formatTransition(stmt: TransitionStatement): void {
802
767
  this.writeIndent()
803
- this.write(
804
- `SUPERSEDE ASSERTION ${this.targetRef(stmt.target)} BY ${this.targetRef(stmt.by)}`
805
- )
806
- if (stmt.expectState) {
807
- this.write(` EXPECT STATE ${this.scalar(stmt.expectState.value)}`)
808
- }
809
- this.newline()
810
- }
811
-
812
- private formatCorrect(stmt: CorrectEvidenceStatement): void {
813
- this.writeIndent()
814
- this.write(
815
- `CORRECT EVIDENCE ${this.targetRef(stmt.target)} BY ${this.targetRef(stmt.by)}`
816
- )
817
- if (stmt.expectState) {
818
- this.write(` EXPECT STATE ${this.scalar(stmt.expectState.value)}`)
819
- }
820
- this.newline()
821
- }
822
-
823
- private formatTransition(stmt: TransitionActivityStatement): void {
824
- this.writeIndent()
825
- this.write(
826
- `TRANSITION ACTIVITY ${this.targetRef(stmt.target)} TO ${this.scalar(stmt.to)}`
827
- )
768
+ this.write(`TRANSITION ${this.targetRef(stmt.target)} TO ${this.scalar(stmt.to)}`)
769
+ if (stmt.by) this.write(` BY ${this.targetRef(stmt.by)}`)
770
+ const tail = stmt.finalize.length > 0 || stmt.where || stmt.limit || stmt.expectVersions.length > 0
828
771
  this.newline()
772
+ if (!tail) return
829
773
  if (stmt.finalize.length > 0) {
830
774
  this.indentLevel++
831
775
  for (const clause of stmt.finalize) {
@@ -838,14 +782,9 @@ class Formatter {
838
782
  }
839
783
  this.indentLevel--
840
784
  }
841
- if (stmt.expectState) {
842
- this.indentLevel++
843
- this.emitCommentsBefore(stmt.expectState.range.start.line)
844
- this.writeIndent()
845
- this.write(`EXPECT STATE ${this.scalar(stmt.expectState.value)}`)
846
- this.newline()
847
- this.indentLevel--
848
- }
785
+ if (stmt.where) this.formatWhere(stmt.where, 'WHERE')
786
+ if (stmt.limit) this.formatLimit(stmt.limit)
787
+ this.formatExpectVersions(stmt.expectVersions)
849
788
  }
850
789
 
851
790
  private formatSetRetention(stmt: SetRetentionStatement): void {
@@ -855,34 +794,7 @@ class Formatter {
855
794
  this.newline()
856
795
  if (stmt.where) this.formatWhere(stmt.where, 'WHERE')
857
796
  if (stmt.limit) this.formatLimit(stmt.limit)
858
- if (stmt.expectVersion) {
859
- this.writeIndent()
860
- this.write(`EXPECT VERSION ${this.scalar(stmt.expectVersion.value)}`)
861
- this.newline()
862
- }
863
- }
864
-
865
- private formatRemoval(
866
- keyword: string,
867
- stmt: ArchiveStatement | TombstoneStatement
868
- ): void {
869
- this.writeIndent()
870
- this.write(`${keyword} ${this.targetRef(stmt.target)}`)
871
- if (!stmt.where && !stmt.limit) {
872
- if (stmt.expectState) {
873
- this.write(` EXPECT STATE ${this.scalar(stmt.expectState.value)}`)
874
- }
875
- this.newline()
876
- return
877
- }
878
- this.newline()
879
- if (stmt.where) this.formatWhere(stmt.where, 'WHERE')
880
- if (stmt.limit) this.formatLimit(stmt.limit)
881
- if (stmt.expectState) {
882
- this.writeIndent()
883
- this.write(`EXPECT STATE ${this.scalar(stmt.expectState.value)}`)
884
- this.newline()
885
- }
797
+ this.formatExpectVersions(stmt.expectVersions)
886
798
  }
887
799
 
888
800
  private formatPurge(stmt: PurgeStatement): void {
@@ -891,6 +803,7 @@ class Formatter {
891
803
  this.newline()
892
804
  if (stmt.where) this.formatWhere(stmt.where, 'WHERE')
893
805
  if (stmt.limit) this.formatLimit(stmt.limit)
806
+ this.formatExpectVersions(stmt.expectVersions)
894
807
  this.indentLevel++
895
808
  if (stmt.referencePolicy) {
896
809
  this.writeIndent()
@@ -909,6 +822,7 @@ class Formatter {
909
822
  this.newline()
910
823
  if (stmt.where) this.formatWhere(stmt.where, 'WHERE')
911
824
  if (stmt.limit) this.formatLimit(stmt.limit)
825
+ this.formatExpectVersions(stmt.expectVersions)
912
826
  this.indentLevel++
913
827
  this.writeIndent()
914
828
  this.write(`CONFIRM ${stmt.confirm.value}`)
@@ -923,11 +837,7 @@ class Formatter {
923
837
  )
924
838
  this.newline()
925
839
  if (stmt.where) this.formatWhere(stmt.where, 'WHERE')
926
- if (stmt.expectVersion) {
927
- this.writeIndent()
928
- this.write(`EXPECT VERSION ${this.scalar(stmt.expectVersion.value)}`)
929
- this.newline()
930
- }
840
+ this.formatExpectVersions(stmt.expectVersions)
931
841
  }
932
842
 
933
843
  // ────────────────────────────────────────────────────────────────────
@@ -1018,7 +928,6 @@ class Formatter {
1018
928
  const words: Record<DescribeStatement['target'], string> = {
1019
929
  PRIMER: 'PRIMER',
1020
930
  PROTOCOL: 'PROTOCOL',
1021
- EXECUTION_CONTEXT: 'EXECUTION CONTEXT',
1022
931
  CAPABILITIES: 'CAPABILITIES',
1023
932
  SPACE: 'SPACE',
1024
933
  SCHEMA_ENVIRONMENT: 'SCHEMA ENVIRONMENT',
@@ -1034,7 +943,6 @@ class Formatter {
1034
943
  SNAPSHOT: 'SNAPSHOT',
1035
944
  CAPSULE: 'CAPSULE',
1036
945
  EPISTEMIC_POLICY: 'EPISTEMIC POLICY',
1037
- PROJECTION_CAPABILITY: 'PROJECTION CAPABILITY',
1038
946
  TRUST: 'TRUST',
1039
947
  ACCESS: 'ACCESS'
1040
948
  }
@@ -1047,6 +955,7 @@ class Formatter {
1047
955
  }
1048
956
  if (stmt.mode) this.write(` MODE ${this.scalar(stmt.mode)}`)
1049
957
  if (stmt.asOf) this.write(` ${this.asOfToString(stmt.asOf)}`)
958
+ if (stmt.atTime) this.write(` AT TIME ${this.scalar(stmt.atTime)}`)
1050
959
  if (stmt.with) this.write(` WITH ${this.objectLiteralToString(stmt.with)}`)
1051
960
  this.newline()
1052
961
  }
@@ -1147,13 +1056,6 @@ class Formatter {
1147
1056
  this.newline()
1148
1057
  }
1149
1058
 
1150
- private formatSnapshot(stmt: SnapshotStatement): void {
1151
- this.writeIndent()
1152
- this.write('SNAPSHOT')
1153
- if (stmt.asOf) this.write(` ${this.asOfToString(stmt.asOf)}`)
1154
- this.newline()
1155
- }
1156
-
1157
1059
  private formatExport(stmt: ExportCapsuleStatement): void {
1158
1060
  this.writeIndent()
1159
1061
  this.write(`EXPORT CAPSULE ${this.targetRef(stmt.target)}`)
package/src/index.ts CHANGED
@@ -88,16 +88,11 @@ export type {
88
88
  UnsetStructuralClause,
89
89
  StructuralRemoval,
90
90
  ExpectVersionClause,
91
- ExpectStateClause,
91
+ VersionPlane,
92
92
  UpdateStatement,
93
93
  UpdateAction,
94
- RetractAssertionStatement,
95
- SupersedeAssertionStatement,
96
- CorrectEvidenceStatement,
97
- TransitionActivityStatement,
94
+ TransitionStatement,
98
95
  SetRetentionStatement,
99
- ArchiveStatement,
100
- TombstoneStatement,
101
96
  PurgeStatement,
102
97
  PurgePayloadStatement,
103
98
  MergeConceptStatement,
@@ -115,7 +110,6 @@ export type {
115
110
  PreviewStatement,
116
111
  HistoryStatement,
117
112
  ChangesStatement,
118
- SnapshotStatement,
119
113
  ExportCapsuleStatement,
120
114
  // Expressions
121
115
  Expression,
@@ -200,12 +194,10 @@ export type {
200
194
  UpdateFunction,
201
195
  UpdateStatement as ExecUpdateStatement,
202
196
  UpdateAction as ExecUpdateAction,
203
- RetractAssertion,
204
- SupersedeAssertion,
205
- CorrectEvidence,
206
- TransitionActivity,
197
+ ExpectVersion,
198
+ VersionPlane as ExecVersionPlane,
199
+ Transition,
207
200
  SetRetention,
208
- RemovalStatement,
209
201
  PurgeStatement as ExecPurgeStatement,
210
202
  PurgePayloadStatement as ExecPurgePayloadStatement,
211
203
  MergeConcept,