@ldclabs/kip-lang 2.0.2 → 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/parser.ts CHANGED
@@ -63,17 +63,13 @@ import type {
63
63
  UnsetStructuralClause,
64
64
  StructuralRemoval,
65
65
  ExpectVersionClause,
66
- ExpectStateClause,
66
+ VersionPlane,
67
67
  UpdateStatement,
68
68
  UpdateAction,
69
- RetractAssertionStatement,
70
- SupersedeAssertionStatement,
71
- CorrectEvidenceStatement,
72
- TransitionActivityStatement,
69
+ TransitionStatement,
73
70
  SetRetentionStatement,
74
- ArchiveStatement,
75
- TombstoneStatement,
76
71
  PurgeStatement,
72
+ PurgePayloadStatement,
77
73
  MergeConceptStatement,
78
74
  DescribeStatement,
79
75
  DescribeTargetKind,
@@ -88,7 +84,6 @@ import type {
88
84
  PreviewStatement,
89
85
  HistoryStatement,
90
86
  ChangesStatement,
91
- SnapshotStatement,
92
87
  ExportCapsuleStatement,
93
88
  Expression,
94
89
  FunctionCallExpr,
@@ -199,13 +194,8 @@ class Parser {
199
194
  case TokenType.Ensure:
200
195
  case TokenType.Assert:
201
196
  case TokenType.Update:
202
- case TokenType.Retract:
203
- case TokenType.Supersede:
204
- case TokenType.Correct:
205
197
  case TokenType.Transition:
206
198
  case TokenType.Set:
207
- case TokenType.Archive:
208
- case TokenType.Tombstone:
209
199
  case TokenType.Purge:
210
200
  case TokenType.Merge:
211
201
  return this.parseMutationClause()
@@ -227,8 +217,6 @@ class Parser {
227
217
  return this.parseHistoryStatement()
228
218
  case TokenType.Changes:
229
219
  return this.parseChangesStatement()
230
- case TokenType.Snapshot:
231
- return this.parseSnapshotStatement()
232
220
  case TokenType.Export:
233
221
  return this.parseExportCapsuleStatement()
234
222
 
@@ -255,20 +243,10 @@ class Parser {
255
243
  return this.parseAssertStatement()
256
244
  case TokenType.Update:
257
245
  return this.parseUpdateStatement()
258
- case TokenType.Retract:
259
- return this.parseRetractAssertion()
260
- case TokenType.Supersede:
261
- return this.parseSupersedeAssertion()
262
- case TokenType.Correct:
263
- return this.parseCorrectEvidence()
264
246
  case TokenType.Transition:
265
- return this.parseTransitionActivity()
247
+ return this.parseTransitionStatement()
266
248
  case TokenType.Set:
267
249
  return this.parseSetRetention()
268
- case TokenType.Archive:
269
- return this.parseArchiveStatement()
270
- case TokenType.Tombstone:
271
- return this.parseTombstoneStatement()
272
250
  case TokenType.Purge:
273
251
  return this.parsePurgeStatement()
274
252
  case TokenType.Merge:
@@ -385,25 +363,18 @@ class Parser {
385
363
  const start = this.currentPos()
386
364
  const first = this.expect(TokenType.As)
387
365
  this.expectSecondWord(TokenType.Of, first)
388
-
389
- let basis: 'SEQ' | 'TX' | 'TIME'
390
- if (this.match(TokenType.Seq)) {
391
- basis = 'SEQ'
392
- } else if (this.match(TokenType.Tx)) {
393
- basis = 'TX'
394
- } else if (this.match(TokenType.Time)) {
395
- basis = 'TIME'
396
- } else {
366
+ // Cognitive time is a sequence coordinate. A transaction id or an instant
367
+ // is resolved to one first (DESCRIBE TRANSACTION / DESCRIBE SNAPSHOT AT
368
+ // TIME), so the read names the sequence it actually ran against.
369
+ if (!this.match(TokenType.Seq)) {
397
370
  this.error(
398
- `Expected SEQ, TX or TIME after AS OF but got '${this.current().value}'`,
371
+ `Expected SEQ after AS OF but got '${this.current().value}'`,
399
372
  this.current()
400
373
  )
401
- basis = 'SEQ'
402
374
  }
403
375
  const value = this.parseScalarValue()
404
376
  return {
405
377
  kind: 'AsOfClause',
406
- basis,
407
378
  value,
408
379
  range: { start, end: this.endPos() }
409
380
  }
@@ -1263,6 +1234,7 @@ class Parser {
1263
1234
  handle,
1264
1235
  setFacets: [],
1265
1236
  unsetFacets: [],
1237
+ expectVersions: [],
1266
1238
  range: { start, end: start },
1267
1239
  leadingComments: leadingComments.length ? leadingComments : undefined
1268
1240
  }
@@ -1277,10 +1249,6 @@ class Parser {
1277
1249
  this.rejectRepeat(stmt.match, 'MATCH', tok)
1278
1250
  stmt.match = this.parseMatchClause()
1279
1251
  break
1280
- case TokenType.Expect:
1281
- this.rejectRepeat(stmt.expectVersion, 'EXPECT VERSION', tok)
1282
- stmt.expectVersion = this.parseExpectVersionClause()
1283
- break
1284
1252
  case TokenType.Set: {
1285
1253
  const clause = this.parseSetClause()
1286
1254
  if (clause.kind === 'SetFieldsClause') {
@@ -1319,6 +1287,9 @@ class Parser {
1319
1287
  if (this.pos === before) break
1320
1288
  }
1321
1289
  this.expect(TokenType.RBrace)
1290
+ // Preconditions trail the body, in the one tail order every mutation
1291
+ // shares: [WHERE] [LIMIT] {EXPECT VERSION} (Spec §52.8).
1292
+ stmt.expectVersions = this.parseExpectVersions()
1322
1293
  stmt.range = { start, end: this.endPos() }
1323
1294
  return stmt
1324
1295
  }
@@ -1334,15 +1305,13 @@ class Parser {
1334
1305
  : undefined
1335
1306
  this.dialect = 'raw'
1336
1307
  const tuple = this.parsePropositionTuple()
1337
- const expectVersion = this.check(TokenType.Expect)
1338
- ? this.parseExpectVersionClause()
1339
- : undefined
1308
+ const expectVersions = this.parseExpectVersions()
1340
1309
 
1341
1310
  return {
1342
1311
  kind: 'EnsurePropositionStatement',
1343
1312
  handle,
1344
1313
  tuple,
1345
- expectVersion,
1314
+ expectVersions,
1346
1315
  range: { start, end: this.endPos() },
1347
1316
  leadingComments: leadingComments.length ? leadingComments : undefined
1348
1317
  }
@@ -1613,23 +1582,52 @@ class Parser {
1613
1582
  const expect = this.expect(TokenType.Expect)
1614
1583
  this.expectSecondWord(TokenType.Version, expect)
1615
1584
  const value = this.parseScalarValue()
1585
+
1586
+ // `OF <plane>` guards one plane's own version instead of the element's
1587
+ // (Spec §35.1): a verdict guarded on ATTRIBUTES is not spoiled by a
1588
+ // metabolism sweep that touched a Facet.
1589
+ let plane: VersionPlane | undefined
1590
+ if (this.match(TokenType.Of)) {
1591
+ const tok = this.current()
1592
+ switch (tok.type) {
1593
+ case TokenType.Attributes:
1594
+ this.advance()
1595
+ plane = { kind: 'ATTRIBUTES' }
1596
+ break
1597
+ case TokenType.Structural:
1598
+ this.advance()
1599
+ plane = { kind: 'STRUCTURAL' }
1600
+ break
1601
+ case TokenType.Retention:
1602
+ this.advance()
1603
+ plane = { kind: 'RETENTION' }
1604
+ break
1605
+ case TokenType.Facet:
1606
+ this.advance()
1607
+ plane = { kind: 'FACET', facet: this.parseSchemaSymbol() }
1608
+ break
1609
+ default:
1610
+ this.error(
1611
+ `Expected ATTRIBUTES, STRUCTURAL, RETENTION or FACET after OF but got '${tok.value}'`,
1612
+ tok
1613
+ )
1614
+ }
1615
+ }
1616
1616
  return {
1617
1617
  kind: 'ExpectVersionClause',
1618
1618
  value,
1619
+ plane,
1619
1620
  range: { start, end: this.endPos() }
1620
1621
  }
1621
1622
  }
1622
1623
 
1623
- private parseExpectStateClause(): ExpectStateClause {
1624
- const start = this.currentPos()
1625
- const expect = this.expect(TokenType.Expect)
1626
- this.expectSecondWord(TokenType.State, expect)
1627
- const value = this.parseScalarValue()
1628
- return {
1629
- kind: 'ExpectStateClause',
1630
- value,
1631
- range: { start, end: this.endPos() }
1624
+ /** `{ expect_version_clause }` — the trailing precondition list. */
1625
+ private parseExpectVersions(): ExpectVersionClause[] {
1626
+ const clauses: ExpectVersionClause[] = []
1627
+ while (this.check(TokenType.Expect)) {
1628
+ clauses.push(this.parseExpectVersionClause())
1632
1629
  }
1630
+ return clauses
1633
1631
  }
1634
1632
 
1635
1633
  // ────────────────────────────────────────────────────────────────────
@@ -1642,10 +1640,6 @@ class Parser {
1642
1640
  this.expectKeywordWithSpace(TokenType.Update)
1643
1641
  const target = this.parseTargetRef()
1644
1642
 
1645
- const expectVersion = this.check(TokenType.Expect)
1646
- ? this.parseExpectVersionClause()
1647
- : undefined
1648
-
1649
1643
  const actions: UpdateAction[] = []
1650
1644
  for (;;) {
1651
1645
  if (this.check(TokenType.Set)) {
@@ -1669,9 +1663,9 @@ class Parser {
1669
1663
  }
1670
1664
 
1671
1665
  // WHERE binds a ?variable target; a direct :id / "id" target already names
1672
- // the element and may omit it, exactly as ARCHIVE / TOMBSTONE / PURGE /
1673
- // SET RETENTION / RETRACT ASSERTION do (Spec §58). Whether a bare
1674
- // ?variable is bound is semantic — inside MUTATE it may be a local handle.
1666
+ // the element and may omit it, exactly as TRANSITION / PURGE /
1667
+ // SET RETENTION do (Spec §58). Whether a bare ?variable is bound is
1668
+ // semantic — inside MUTATE it may be a local handle.
1675
1669
  let where: WhereClause | undefined
1676
1670
  if (this.check(TokenType.Where)) {
1677
1671
  this.expectKeywordWithSpace(TokenType.Where)
@@ -1679,107 +1673,40 @@ class Parser {
1679
1673
  where = this.parseWhereClause()
1680
1674
  }
1681
1675
  const limit = this.check(TokenType.Limit) ? this.parseLimitClause() : undefined
1676
+ const expectVersions = this.parseExpectVersions()
1682
1677
 
1683
1678
  return {
1684
1679
  kind: 'UpdateStatement',
1685
1680
  target,
1686
- expectVersion,
1687
1681
  actions,
1688
1682
  where,
1689
1683
  limit,
1684
+ expectVersions,
1690
1685
  range: { start, end: this.endPos() },
1691
1686
  leadingComments: leadingComments.length ? leadingComments : undefined
1692
1687
  }
1693
1688
  }
1694
1689
 
1695
1690
  // ────────────────────────────────────────────────────────────────────
1696
- // KML — lifecycle and correction
1691
+ // KML — TRANSITION (the one lifecycle statement, Spec §52.5)
1697
1692
  // ────────────────────────────────────────────────────────────────────
1698
1693
 
1699
- private parseRetractAssertion(): RetractAssertionStatement {
1700
- const leadingComments = this.collectLeadingComments()
1701
- const start = this.currentPos()
1702
- const retract = this.expectKeywordWithSpace(TokenType.Retract)
1703
- this.expectSecondWord(TokenType.Assertion, retract)
1704
- const target = this.parseTargetRef()
1705
-
1706
- let where: WhereClause | undefined
1707
- if (this.check(TokenType.Where)) {
1708
- this.expectKeywordWithSpace(TokenType.Where)
1709
- this.dialect = 'raw'
1710
- where = this.parseWhereClause()
1711
- }
1712
- const limit = this.check(TokenType.Limit) ? this.parseLimitClause() : undefined
1713
- const expectState = this.check(TokenType.Expect)
1714
- ? this.parseExpectStateClause()
1715
- : undefined
1716
-
1717
- return {
1718
- kind: 'RetractAssertionStatement',
1719
- target,
1720
- where,
1721
- limit,
1722
- expectState,
1723
- range: { start, end: this.endPos() },
1724
- leadingComments: leadingComments.length ? leadingComments : undefined
1725
- }
1726
- }
1727
-
1728
- private parseSupersedeAssertion(): SupersedeAssertionStatement {
1729
- const leadingComments = this.collectLeadingComments()
1730
- const start = this.currentPos()
1731
- const supersede = this.expectKeywordWithSpace(TokenType.Supersede)
1732
- this.expectSecondWord(TokenType.Assertion, supersede)
1733
- const target = this.parseTargetRef()
1734
- this.expect(TokenType.By)
1735
- const by = this.parseTargetRef()
1736
- const expectState = this.check(TokenType.Expect)
1737
- ? this.parseExpectStateClause()
1738
- : undefined
1739
-
1740
- return {
1741
- kind: 'SupersedeAssertionStatement',
1742
- target,
1743
- by,
1744
- expectState,
1745
- range: { start, end: this.endPos() },
1746
- leadingComments: leadingComments.length ? leadingComments : undefined
1747
- }
1748
- }
1749
-
1750
- private parseCorrectEvidence(): CorrectEvidenceStatement {
1694
+ private parseTransitionStatement(): TransitionStatement {
1751
1695
  const leadingComments = this.collectLeadingComments()
1752
1696
  const start = this.currentPos()
1753
- const correct = this.expectKeywordWithSpace(TokenType.Correct)
1754
- this.expectSecondWord(TokenType.Evidence, correct)
1755
- const target = this.parseTargetRef()
1756
- this.expect(TokenType.By)
1757
- const by = this.parseTargetRef()
1758
- const expectState = this.check(TokenType.Expect)
1759
- ? this.parseExpectStateClause()
1760
- : undefined
1761
-
1762
- return {
1763
- kind: 'CorrectEvidenceStatement',
1764
- target,
1765
- by,
1766
- expectState,
1767
- range: { start, end: this.endPos() },
1768
- leadingComments: leadingComments.length ? leadingComments : undefined
1769
- }
1770
- }
1771
-
1772
- private parseTransitionActivity(): TransitionActivityStatement {
1773
- const leadingComments = this.collectLeadingComments()
1774
- const start = this.currentPos()
1775
- const transition = this.expectKeywordWithSpace(TokenType.Transition)
1776
- this.expectSecondWord(TokenType.Activity, transition)
1697
+ this.expectKeywordWithSpace(TokenType.Transition)
1777
1698
  const target = this.parseTargetRef()
1778
1699
  this.expect(TokenType.To)
1779
1700
  const to = this.parseScalarValue()
1780
1701
 
1781
- // Terminal outputs and ended_at may be finalized in the same statement
1782
- // that moves the Activity to its terminal state.
1702
+ // `BY` names the replacing element for "superseded" / "corrected".
1703
+ let by: TargetRef | undefined
1704
+ if (this.match(TokenType.By)) {
1705
+ by = this.parseTargetRef()
1706
+ }
1707
+
1708
+ // A pending Activity finalizes terminal fields and topology in the same
1709
+ // statement that moves it (Spec §17.5, §52.5).
1783
1710
  const finalize: (SetFieldsClause | SetStructuralClause)[] = []
1784
1711
  while (this.check(TokenType.Set)) {
1785
1712
  const clause = this.parseSetClause()
@@ -1787,23 +1714,31 @@ class Parser {
1787
1714
  finalize.push(clause)
1788
1715
  } else {
1789
1716
  this.error(
1790
- 'TRANSITION ACTIVITY accepts only SET FIELDS and SET STRUCTURAL',
1717
+ 'TRANSITION accepts only SET FIELDS and SET STRUCTURAL',
1791
1718
  this.current()
1792
1719
  )
1793
1720
  break
1794
1721
  }
1795
1722
  }
1796
1723
 
1797
- const expectState = this.check(TokenType.Expect)
1798
- ? this.parseExpectStateClause()
1799
- : undefined
1724
+ let where: WhereClause | undefined
1725
+ if (this.check(TokenType.Where)) {
1726
+ this.expectKeywordWithSpace(TokenType.Where)
1727
+ this.dialect = 'raw'
1728
+ where = this.parseWhereClause()
1729
+ }
1730
+ const limit = this.check(TokenType.Limit) ? this.parseLimitClause() : undefined
1731
+ const expectVersions = this.parseExpectVersions()
1800
1732
 
1801
1733
  return {
1802
- kind: 'TransitionActivityStatement',
1734
+ kind: 'TransitionStatement',
1803
1735
  target,
1804
1736
  to,
1737
+ by,
1805
1738
  finalize,
1806
- expectState,
1739
+ where,
1740
+ limit,
1741
+ expectVersions,
1807
1742
  range: { start, end: this.endPos() },
1808
1743
  leadingComments: leadingComments.length ? leadingComments : undefined
1809
1744
  }
@@ -1828,9 +1763,7 @@ class Parser {
1828
1763
  where = this.parseWhereClause()
1829
1764
  }
1830
1765
  const limit = this.check(TokenType.Limit) ? this.parseLimitClause() : undefined
1831
- const expectVersion = this.check(TokenType.Expect)
1832
- ? this.parseExpectVersionClause()
1833
- : undefined
1766
+ const expectVersions = this.parseExpectVersions()
1834
1767
 
1835
1768
  return {
1836
1769
  kind: 'SetRetentionStatement',
@@ -1838,52 +1771,19 @@ class Parser {
1838
1771
  assignments,
1839
1772
  where,
1840
1773
  limit,
1841
- expectVersion,
1774
+ expectVersions,
1842
1775
  range: { start, end: this.endPos() },
1843
1776
  leadingComments: leadingComments.length ? leadingComments : undefined
1844
1777
  }
1845
1778
  }
1846
1779
 
1847
- private parseArchiveStatement(): ArchiveStatement {
1848
- const { start, target, where, limit, expectState, leadingComments } =
1849
- this.parseRemovalBody(TokenType.Archive)
1850
- return {
1851
- kind: 'ArchiveStatement',
1852
- target,
1853
- where,
1854
- limit,
1855
- expectState,
1856
- range: { start, end: this.endPos() },
1857
- leadingComments
1858
- }
1859
- }
1860
-
1861
- private parseTombstoneStatement(): TombstoneStatement {
1862
- const { start, target, where, limit, expectState, leadingComments } =
1863
- this.parseRemovalBody(TokenType.Tombstone)
1864
- return {
1865
- kind: 'TombstoneStatement',
1866
- target,
1867
- where,
1868
- limit,
1869
- expectState,
1870
- range: { start, end: this.endPos() },
1871
- leadingComments
1872
- }
1873
- }
1874
-
1875
- /** ARCHIVE and TOMBSTONE share one shape; PURGE adds its confirmation. */
1876
- private parseRemovalBody(keyword: TokenType): {
1877
- start: Position
1878
- target: TargetRef
1879
- where?: WhereClause
1880
- limit?: LimitClause
1881
- expectState?: ExpectStateClause
1882
- leadingComments?: string[]
1883
- } {
1884
- const comments = this.collectLeadingComments()
1780
+ private parsePurgeStatement(): PurgeStatement | PurgePayloadStatement {
1781
+ const leadingComments = this.collectLeadingComments()
1885
1782
  const start = this.currentPos()
1886
- this.expectKeywordWithSpace(keyword)
1783
+ const purge = this.expectKeywordWithSpace(TokenType.Purge)
1784
+ if (this.check(TokenType.Payload)) {
1785
+ return this.parsePurgePayloadTail(start, purge, leadingComments)
1786
+ }
1887
1787
  const target = this.parseTargetRef()
1888
1788
 
1889
1789
  let where: WhereClause | undefined
@@ -1892,25 +1792,54 @@ class Parser {
1892
1792
  this.dialect = 'raw'
1893
1793
  where = this.parseWhereClause()
1894
1794
  }
1795
+
1895
1796
  const limit = this.check(TokenType.Limit) ? this.parseLimitClause() : undefined
1896
- const expectState = this.check(TokenType.Expect)
1897
- ? this.parseExpectStateClause()
1898
- : undefined
1797
+ const expectVersions = this.parseExpectVersions()
1798
+
1799
+ let referencePolicy: ScalarValue | undefined
1800
+ if (this.check(TokenType.Reference)) {
1801
+ const reference = this.expect(TokenType.Reference)
1802
+ this.expectSecondWord(TokenType.Policy, reference)
1803
+ referencePolicy = this.parseScalarValue()
1804
+ }
1805
+
1806
+ // The grammar freezes the confirmation spelling. Physical erasure is
1807
+ // exceptional, so the literal is required and checked here rather than
1808
+ // left for the engine to discover.
1809
+ this.expect(TokenType.Confirm)
1810
+ const confirmTok = this.current()
1811
+ const confirm = this.parseStringLiteral()
1812
+ if (confirm.parsed !== 'PURGE') {
1813
+ this.error(
1814
+ `PURGE must be confirmed with the exact literal "PURGE", got ${confirmTok.value}`,
1815
+ confirmTok
1816
+ )
1817
+ }
1899
1818
 
1900
1819
  return {
1901
- start,
1820
+ kind: 'PurgeStatement',
1902
1821
  target,
1903
1822
  where,
1904
1823
  limit,
1905
- expectState,
1906
- leadingComments: comments.length ? comments : undefined
1824
+ expectVersions,
1825
+ referencePolicy,
1826
+ confirm,
1827
+ range: { start, end: this.endPos() },
1828
+ leadingComments: leadingComments.length ? leadingComments : undefined
1907
1829
  }
1908
1830
  }
1909
1831
 
1910
- private parsePurgeStatement(): PurgeStatement {
1911
- const leadingComments = this.collectLeadingComments()
1912
- const start = this.currentPos()
1913
- this.expectKeywordWithSpace(TokenType.Purge)
1832
+ /**
1833
+ * `PURGE PAYLOAD` erases Evidence bytes while the element survives
1834
+ * (Spec §60.6), so there is no REFERENCE POLICY clause; the confirmation
1835
+ * literal is the same as element purge.
1836
+ */
1837
+ private parsePurgePayloadTail(
1838
+ start: Position,
1839
+ purge: Token,
1840
+ leadingComments: string[]
1841
+ ): PurgePayloadStatement {
1842
+ this.expectSecondWord(TokenType.Payload, purge)
1914
1843
  const target = this.parseTargetRef()
1915
1844
 
1916
1845
  let where: WhereClause | undefined
@@ -1921,33 +1850,24 @@ class Parser {
1921
1850
  }
1922
1851
 
1923
1852
  const limit = this.check(TokenType.Limit) ? this.parseLimitClause() : undefined
1853
+ const expectVersions = this.parseExpectVersions()
1924
1854
 
1925
- let referencePolicy: ScalarValue | undefined
1926
- if (this.check(TokenType.Reference)) {
1927
- const reference = this.expect(TokenType.Reference)
1928
- this.expectSecondWord(TokenType.Policy, reference)
1929
- referencePolicy = this.parseScalarValue()
1930
- }
1931
-
1932
- // The grammar freezes the confirmation spelling. Physical erasure is
1933
- // exceptional, so the literal is required and checked here rather than
1934
- // left for the engine to discover.
1935
1855
  this.expect(TokenType.Confirm)
1936
1856
  const confirmTok = this.current()
1937
1857
  const confirm = this.parseStringLiteral()
1938
1858
  if (confirm.parsed !== 'PURGE') {
1939
1859
  this.error(
1940
- `PURGE must be confirmed with the exact literal "PURGE", got ${confirmTok.value}`,
1860
+ `PURGE PAYLOAD must be confirmed with the exact literal "PURGE", got ${confirmTok.value}`,
1941
1861
  confirmTok
1942
1862
  )
1943
1863
  }
1944
1864
 
1945
1865
  return {
1946
- kind: 'PurgeStatement',
1866
+ kind: 'PurgePayloadStatement',
1947
1867
  target,
1948
1868
  where,
1949
1869
  limit,
1950
- referencePolicy,
1870
+ expectVersions,
1951
1871
  confirm,
1952
1872
  range: { start, end: this.endPos() },
1953
1873
  leadingComments: leadingComments.length ? leadingComments : undefined
@@ -1969,16 +1889,14 @@ class Parser {
1969
1889
  this.dialect = 'raw'
1970
1890
  where = this.parseWhereClause()
1971
1891
  }
1972
- const expectVersion = this.check(TokenType.Expect)
1973
- ? this.parseExpectVersionClause()
1974
- : undefined
1892
+ const expectVersions = this.parseExpectVersions()
1975
1893
 
1976
1894
  return {
1977
1895
  kind: 'MergeConceptStatement',
1978
1896
  source,
1979
1897
  into,
1980
1898
  where,
1981
- expectVersion,
1899
+ expectVersions,
1982
1900
  range: { start, end: this.endPos() },
1983
1901
  leadingComments: leadingComments.length ? leadingComments : undefined
1984
1902
  }
@@ -2015,11 +1933,6 @@ class Parser {
2015
1933
  case TokenType.Protocol:
2016
1934
  this.expectSecondWord(TokenType.Protocol, describe)
2017
1935
  return stmt('PROTOCOL')
2018
- case TokenType.Execution: {
2019
- const exec = this.expectSecondWord(TokenType.Execution, describe)
2020
- this.expectSecondWord(TokenType.Context, exec)
2021
- return stmt('EXECUTION_CONTEXT')
2022
- }
2023
1936
  case TokenType.Capabilities:
2024
1937
  this.expectSecondWord(TokenType.Capabilities, describe)
2025
1938
  return stmt('CAPABILITIES')
@@ -2076,8 +1989,18 @@ class Parser {
2076
1989
  }
2077
1990
  case TokenType.Snapshot: {
2078
1991
  this.expectSecondWord(TokenType.Snapshot, describe)
2079
- const asOf = this.check(TokenType.As) ? this.parseAsOfClause() : undefined
2080
- return stmt('SNAPSHOT', { asOf })
1992
+ // A snapshot is addressed by sequence, or resolved from an instant:
1993
+ // the one place wall-clock time enters cognitive-time addressing.
1994
+ let asOf: AsOfClause | undefined
1995
+ let atTime: ScalarValue | undefined
1996
+ if (this.check(TokenType.As)) {
1997
+ asOf = this.parseAsOfClause()
1998
+ } else if (this.check(TokenType.At)) {
1999
+ const at = this.expect(TokenType.At)
2000
+ this.expectSecondWord(TokenType.Time, at)
2001
+ atTime = this.parseScalarValue()
2002
+ }
2003
+ return stmt('SNAPSHOT', { asOf, atTime })
2081
2004
  }
2082
2005
  case TokenType.Capsule:
2083
2006
  this.expectSecondWord(TokenType.Capsule, describe)
@@ -2088,11 +2011,6 @@ class Parser {
2088
2011
  const value = this.isMetaValueStart() ? this.parseScalarValue() : undefined
2089
2012
  return stmt('EPISTEMIC_POLICY', { value })
2090
2013
  }
2091
- case TokenType.Projection: {
2092
- const projection = this.expectSecondWord(TokenType.Projection, describe)
2093
- this.expectSecondWord(TokenType.Capability, projection)
2094
- return stmt('PROJECTION_CAPABILITY')
2095
- }
2096
2014
  case TokenType.Trust: {
2097
2015
  this.expectSecondWord(TokenType.Trust, describe)
2098
2016
  const value = this.isMetaValueStart() ? this.parseScalarValue() : undefined
@@ -2123,6 +2041,8 @@ class Parser {
2123
2041
 
2124
2042
  let target: ListTargetKind
2125
2043
  let status: ScalarValue | undefined
2044
+ let element: ScalarValue | undefined
2045
+ let depth: ScalarValue | undefined
2126
2046
 
2127
2047
  switch (tok.type) {
2128
2048
  case TokenType.Spaces:
@@ -2160,6 +2080,14 @@ class Parser {
2160
2080
  target = 'EPISTEMIC_POLICIES'
2161
2081
  break
2162
2082
  }
2083
+ case TokenType.Dependents:
2084
+ // Bounded reverse provenance closure (Spec §63.5): the operand is
2085
+ // required, the DEPTH bound is optional and defaults engine-side to 1.
2086
+ this.expectSecondWord(TokenType.Dependents, list)
2087
+ target = 'DEPENDENTS'
2088
+ element = this.parseScalarValue()
2089
+ if (this.match(TokenType.Depth)) depth = this.parseScalarValue()
2090
+ break
2163
2091
  default:
2164
2092
  this.error(`Unknown LIST target '${tok.value}'`, tok)
2165
2093
  throw new ParseAbort()
@@ -2174,6 +2102,8 @@ class Parser {
2174
2102
  kind: 'ListStatement',
2175
2103
  target,
2176
2104
  status,
2105
+ element,
2106
+ depth,
2177
2107
  limit,
2178
2108
  cursor,
2179
2109
  range: { start, end: this.endPos() },
@@ -2419,7 +2349,7 @@ class Parser {
2419
2349
  }
2420
2350
 
2421
2351
  // ────────────────────────────────────────────────────────────────────
2422
- // META — HISTORY / CHANGES / SNAPSHOT
2352
+ // META — HISTORY / CHANGES
2423
2353
  // ────────────────────────────────────────────────────────────────────
2424
2354
 
2425
2355
  private parseHistoryStatement(): HistoryStatement {
@@ -2510,19 +2440,6 @@ class Parser {
2510
2440
  }
2511
2441
  }
2512
2442
 
2513
- private parseSnapshotStatement(): SnapshotStatement {
2514
- const leadingComments = this.collectLeadingComments()
2515
- const start = this.currentPos()
2516
- this.expect(TokenType.Snapshot)
2517
- const asOf = this.check(TokenType.As) ? this.parseAsOfClause() : undefined
2518
- return {
2519
- kind: 'SnapshotStatement',
2520
- asOf,
2521
- range: { start, end: this.endPos() },
2522
- leadingComments: leadingComments.length ? leadingComments : undefined
2523
- }
2524
- }
2525
-
2526
2443
  // ────────────────────────────────────────────────────────────────────
2527
2444
  // META — EXPORT CAPSULE
2528
2445
  // ────────────────────────────────────────────────────────────────────
@@ -3449,13 +3366,8 @@ class Parser {
3449
3366
  TokenType.Ensure,
3450
3367
  TokenType.Assert,
3451
3368
  TokenType.Update,
3452
- TokenType.Retract,
3453
- TokenType.Supersede,
3454
- TokenType.Correct,
3455
3369
  TokenType.Transition,
3456
3370
  TokenType.Set,
3457
- TokenType.Archive,
3458
- TokenType.Tombstone,
3459
3371
  TokenType.Purge,
3460
3372
  TokenType.Merge,
3461
3373
  TokenType.Describe,
@@ -3466,7 +3378,6 @@ class Parser {
3466
3378
  TokenType.Preview,
3467
3379
  TokenType.History,
3468
3380
  TokenType.Changes,
3469
- TokenType.Snapshot,
3470
3381
  TokenType.Export,
3471
3382
  TokenType.EOF
3472
3383
  ])