@cavelang/tree-sitter-cave 0.34.0 → 0.36.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/README.md CHANGED
@@ -14,6 +14,11 @@ Entity and attribute names accept Unicode letters, combining marks and
14
14
  numbers, with `/`, `-`, `_`, and `.` as structural characters. Numeric
15
15
  values include negative scalars and negative trajectory endpoints.
16
16
 
17
+ Explicit full claims use a leading `@claim` marker (§8.6), including inside
18
+ qualifier payloads. The marker is highlighted as a keyword and reserved or
19
+ numeric-looking subjects (such as `42` and `2026-01-01`) as entities; a trailing `@claim` is still a context. Prefix expansion remains the
20
+ semantic parser's responsibility.
21
+
17
22
  ## Contents
18
23
 
19
24
  - `grammar.js` — the grammar (spec §16, §3–§8)
@@ -31,7 +36,39 @@ values include negative scalars and negative trajectory endpoints.
31
36
  tree-sitter CLI and WASI SDK archives listed in
32
37
  `scripts/grammar-toolchain.json`, verifies their SHA-256 digests, and caches
33
38
  them under `~/.cache/cave/grammar-toolchain`. Package installation itself
34
- does not run a binary downloader.
39
+ does not run a binary downloader. After compilation, the Wasm module is
40
+ normalized to file mode `0644`: it is loaded as data, not executed by the OS.
41
+ Keeping both the generated output and tracked artifact non-executable also
42
+ allows the Changesets version-PR action to commit it through the GitHub API.
43
+
44
+ The package test command also regenerates the native sources and WASM before
45
+ running the grammar corpus. Run workspace test matrices one Node version at a
46
+ time in a shared checkout: these commands write the same generated files and
47
+ use Tree-sitter's native parser cache. The workspace's package-concurrency
48
+ setting does not serialize two separate `pnpm test` processes.
49
+
50
+ Each missing archive download has a five-minute deadline covering connection
51
+ setup and the response body. Set `CAVE_GRAMMAR_DOWNLOAD_TIMEOUT_SECONDS` to a
52
+ positive number (up to 2147483.647) for slower links or shorter automation limits.
53
+ Invalid settings fail before cache creation. Failed transfers remove partial
54
+ files, and setup waits for both parallel preparations to settle before reporting
55
+ failure. Verified cached archives continue to support offline builds.
56
+ A local-server regression verifies timeout cleanup, corrected retry with
57
+ checksum-verified fixture archives, and an offline reuse pass with no requests.
58
+ A partial-failure case also verifies that a delayed successful archive remains
59
+ verified and installed when its peer returns HTTP 503; retry fetches only the
60
+ missing archive.
61
+ SDK setup validates the exact first line of `VERSION` before replacing an
62
+ existing installation; subsequent build metadata lines remain supported. A
63
+ missing or mismatched version leaves the prior installation intact and removes
64
+ the rejected staging directory. Cached installations with a version mismatch
65
+ are re-extracted from the verified archive, including in offline mode.
66
+ The same repair applies when installed version or source-marker metadata is a
67
+ directory instead of a file.
68
+ Staging cleanup also runs when reading version metadata or writing the source
69
+ marker fails, so malformed extracted files do not leave temporary SDK trees.
70
+ The fixtures test setup and cache behavior; the separate corpus run exercises
71
+ the real pinned tools.
35
72
 
36
73
  For an offline or pre-provisioned build, copy the two archives for the host
37
74
  platform into `$CAVE_GRAMMAR_CACHE/downloads` (the variable defaults to the
package/grammar.js CHANGED
@@ -41,11 +41,19 @@ module.exports = grammar({
41
41
 
42
42
  comment_line: $ => $.comment,
43
43
 
44
- claim_line: $ => seq(
45
- field('subject', choice($._term, alias($.verb, $.entity))),
46
- $._body
44
+ claim_line: $ => choice(
45
+ seq(field('subject', choice($._term, alias($.verb, $.entity))), $._body),
46
+ $._explicit_claim
47
47
  ),
48
48
 
49
+ _explicit_claim: $ => prec.right(1, seq(
50
+ $.claim_marker,
51
+ field('subject', choice($._term, alias($.verb, $.entity), alias($.qualifier_verb, $.entity), alias($.negation, $.entity), alias($.number, $.entity))),
52
+ $._body
53
+ )),
54
+
55
+ claim_marker: () => '@claim',
56
+
49
57
  // Bare relational verb; the subject is inherited from the parent (§8.3).
50
58
  continuation_line: $ => prec.dynamic(-1, $._body),
51
59
 
@@ -53,8 +61,9 @@ module.exports = grammar({
53
61
  // Indentation and prefix expansion remain consumer responsibilities;
54
62
  // this permissive fallback keeps every fragment highlightable while the
55
63
  // complete line rules above retain precedence.
56
- shorthand_line: $ => prec.dynamic(-2, seq(
57
- repeat1(choice(
64
+ shorthand_line: $ => prec.dynamic(-2, choice(
65
+ prec(2, seq($.claim_marker, optional($.comment))),
66
+ seq(repeat1(choice(
58
67
  $.verb,
59
68
  $.attribute,
60
69
  $._term,
@@ -63,7 +72,7 @@ module.exports = grammar({
63
72
  $._meta,
64
73
  '->'
65
74
  )),
66
- optional($.comment)
75
+ optional($.comment))
67
76
  )),
68
77
 
69
78
  _body: $ => choice(
@@ -120,6 +129,7 @@ module.exports = grammar({
120
129
 
121
130
  // Qualifier payload (§8.2): comparison, nested claim, or bare condition.
122
131
  _qualifier_payload: $ => choice(
132
+ $._explicit_claim,
123
133
  $.comparison,
124
134
  seq(field('subject', $._term), $._body),
125
135
  $._term
@@ -137,6 +147,7 @@ module.exports = grammar({
137
147
 
138
148
  _meta: $ => choice(
139
149
  $.context,
150
+ alias($.claim_marker, $.context),
140
151
  $.confidence,
141
152
  $.tag,
142
153
  $.uncertainty,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cavelang/tree-sitter-cave",
3
- "version": "0.34.0",
3
+ "version": "0.36.0",
4
4
  "description": "Tree-sitter grammar for CAVE — the canonical grammar artifact behind editor and terminal highlighting.",
5
5
  "keywords": [
6
6
  "cave",
@@ -20,7 +20,7 @@
20
20
  "directory": "packages/tree-sitter-cave"
21
21
  },
22
22
  "engines": {
23
- "node": "^22.18.0 || ^24.0.0 || ^26.0.0"
23
+ "node": "^24.16.0 || ^26.1.0"
24
24
  },
25
25
  "exports": {
26
26
  "./wasm": "./tree-sitter-cave.wasm",
@@ -30,3 +30,6 @@
30
30
  (tag ":" @punctuation.delimiter)
31
31
  (tag_key) @tag
32
32
  (tag_value) @constant
33
+
34
+ ; Explicit full-claim disambiguation; trailing @claim remains context.
35
+ (claim_marker) @keyword
package/src/grammar.json CHANGED
@@ -73,95 +73,204 @@
73
73
  "name": "comment"
74
74
  },
75
75
  "claim_line": {
76
- "type": "SEQ",
76
+ "type": "CHOICE",
77
77
  "members": [
78
78
  {
79
- "type": "FIELD",
80
- "name": "subject",
81
- "content": {
82
- "type": "CHOICE",
83
- "members": [
84
- {
85
- "type": "SYMBOL",
86
- "name": "_term"
87
- },
88
- {
89
- "type": "ALIAS",
90
- "content": {
91
- "type": "SYMBOL",
92
- "name": "verb"
93
- },
94
- "named": true,
95
- "value": "entity"
79
+ "type": "SEQ",
80
+ "members": [
81
+ {
82
+ "type": "FIELD",
83
+ "name": "subject",
84
+ "content": {
85
+ "type": "CHOICE",
86
+ "members": [
87
+ {
88
+ "type": "SYMBOL",
89
+ "name": "_term"
90
+ },
91
+ {
92
+ "type": "ALIAS",
93
+ "content": {
94
+ "type": "SYMBOL",
95
+ "name": "verb"
96
+ },
97
+ "named": true,
98
+ "value": "entity"
99
+ }
100
+ ]
96
101
  }
97
- ]
98
- }
102
+ },
103
+ {
104
+ "type": "SYMBOL",
105
+ "name": "_body"
106
+ }
107
+ ]
99
108
  },
100
109
  {
101
110
  "type": "SYMBOL",
102
- "name": "_body"
111
+ "name": "_explicit_claim"
103
112
  }
104
113
  ]
105
114
  },
106
- "continuation_line": {
107
- "type": "PREC_DYNAMIC",
108
- "value": -1,
109
- "content": {
110
- "type": "SYMBOL",
111
- "name": "_body"
112
- }
113
- },
114
- "shorthand_line": {
115
- "type": "PREC_DYNAMIC",
116
- "value": -2,
115
+ "_explicit_claim": {
116
+ "type": "PREC_RIGHT",
117
+ "value": 1,
117
118
  "content": {
118
119
  "type": "SEQ",
119
120
  "members": [
120
121
  {
121
- "type": "REPEAT1",
122
+ "type": "SYMBOL",
123
+ "name": "claim_marker"
124
+ },
125
+ {
126
+ "type": "FIELD",
127
+ "name": "subject",
122
128
  "content": {
123
129
  "type": "CHOICE",
124
130
  "members": [
125
131
  {
126
132
  "type": "SYMBOL",
127
- "name": "verb"
133
+ "name": "_term"
128
134
  },
129
135
  {
130
- "type": "SYMBOL",
131
- "name": "attribute"
136
+ "type": "ALIAS",
137
+ "content": {
138
+ "type": "SYMBOL",
139
+ "name": "verb"
140
+ },
141
+ "named": true,
142
+ "value": "entity"
132
143
  },
133
144
  {
134
- "type": "SYMBOL",
135
- "name": "_term"
145
+ "type": "ALIAS",
146
+ "content": {
147
+ "type": "SYMBOL",
148
+ "name": "qualifier_verb"
149
+ },
150
+ "named": true,
151
+ "value": "entity"
136
152
  },
137
153
  {
138
- "type": "SYMBOL",
139
- "name": "number"
154
+ "type": "ALIAS",
155
+ "content": {
156
+ "type": "SYMBOL",
157
+ "name": "negation"
158
+ },
159
+ "named": true,
160
+ "value": "entity"
140
161
  },
141
162
  {
142
- "type": "SYMBOL",
143
- "name": "negation"
144
- },
163
+ "type": "ALIAS",
164
+ "content": {
165
+ "type": "SYMBOL",
166
+ "name": "number"
167
+ },
168
+ "named": true,
169
+ "value": "entity"
170
+ }
171
+ ]
172
+ }
173
+ },
174
+ {
175
+ "type": "SYMBOL",
176
+ "name": "_body"
177
+ }
178
+ ]
179
+ }
180
+ },
181
+ "claim_marker": {
182
+ "type": "STRING",
183
+ "value": "@claim"
184
+ },
185
+ "continuation_line": {
186
+ "type": "PREC_DYNAMIC",
187
+ "value": -1,
188
+ "content": {
189
+ "type": "SYMBOL",
190
+ "name": "_body"
191
+ }
192
+ },
193
+ "shorthand_line": {
194
+ "type": "PREC_DYNAMIC",
195
+ "value": -2,
196
+ "content": {
197
+ "type": "CHOICE",
198
+ "members": [
199
+ {
200
+ "type": "PREC",
201
+ "value": 2,
202
+ "content": {
203
+ "type": "SEQ",
204
+ "members": [
145
205
  {
146
206
  "type": "SYMBOL",
147
- "name": "_meta"
207
+ "name": "claim_marker"
148
208
  },
149
209
  {
150
- "type": "STRING",
151
- "value": "->"
210
+ "type": "CHOICE",
211
+ "members": [
212
+ {
213
+ "type": "SYMBOL",
214
+ "name": "comment"
215
+ },
216
+ {
217
+ "type": "BLANK"
218
+ }
219
+ ]
152
220
  }
153
221
  ]
154
222
  }
155
223
  },
156
224
  {
157
- "type": "CHOICE",
225
+ "type": "SEQ",
158
226
  "members": [
159
227
  {
160
- "type": "SYMBOL",
161
- "name": "comment"
228
+ "type": "REPEAT1",
229
+ "content": {
230
+ "type": "CHOICE",
231
+ "members": [
232
+ {
233
+ "type": "SYMBOL",
234
+ "name": "verb"
235
+ },
236
+ {
237
+ "type": "SYMBOL",
238
+ "name": "attribute"
239
+ },
240
+ {
241
+ "type": "SYMBOL",
242
+ "name": "_term"
243
+ },
244
+ {
245
+ "type": "SYMBOL",
246
+ "name": "number"
247
+ },
248
+ {
249
+ "type": "SYMBOL",
250
+ "name": "negation"
251
+ },
252
+ {
253
+ "type": "SYMBOL",
254
+ "name": "_meta"
255
+ },
256
+ {
257
+ "type": "STRING",
258
+ "value": "->"
259
+ }
260
+ ]
261
+ }
162
262
  },
163
263
  {
164
- "type": "BLANK"
264
+ "type": "CHOICE",
265
+ "members": [
266
+ {
267
+ "type": "SYMBOL",
268
+ "name": "comment"
269
+ },
270
+ {
271
+ "type": "BLANK"
272
+ }
273
+ ]
165
274
  }
166
275
  ]
167
276
  }
@@ -529,6 +638,10 @@
529
638
  "_qualifier_payload": {
530
639
  "type": "CHOICE",
531
640
  "members": [
641
+ {
642
+ "type": "SYMBOL",
643
+ "name": "_explicit_claim"
644
+ },
532
645
  {
533
646
  "type": "SYMBOL",
534
647
  "name": "comparison"
@@ -647,6 +760,15 @@
647
760
  "type": "SYMBOL",
648
761
  "name": "context"
649
762
  },
763
+ {
764
+ "type": "ALIAS",
765
+ "content": {
766
+ "type": "SYMBOL",
767
+ "name": "claim_marker"
768
+ },
769
+ "named": true,
770
+ "value": "context"
771
+ },
650
772
  {
651
773
  "type": "SYMBOL",
652
774
  "name": "confidence"
@@ -79,7 +79,7 @@
79
79
  },
80
80
  "verb": {
81
81
  "multiple": false,
82
- "required": true,
82
+ "required": false,
83
83
  "types": [
84
84
  {
85
85
  "type": "verb",
@@ -92,6 +92,10 @@
92
92
  "multiple": true,
93
93
  "required": false,
94
94
  "types": [
95
+ {
96
+ "type": "claim_marker",
97
+ "named": true
98
+ },
95
99
  {
96
100
  "type": "comment",
97
101
  "named": true
@@ -307,6 +311,11 @@
307
311
  ]
308
312
  }
309
313
  },
314
+ {
315
+ "type": "entity",
316
+ "named": true,
317
+ "fields": {}
318
+ },
310
319
  {
311
320
  "type": "object",
312
321
  "named": true,
@@ -342,6 +351,10 @@
342
351
  "type": "attr_value",
343
352
  "named": true
344
353
  },
354
+ {
355
+ "type": "claim_marker",
356
+ "named": true
357
+ },
345
358
  {
346
359
  "type": "code",
347
360
  "named": true
@@ -493,6 +506,10 @@
493
506
  "type": "attribute",
494
507
  "named": true
495
508
  },
509
+ {
510
+ "type": "claim_marker",
511
+ "named": true
512
+ },
496
513
  {
497
514
  "type": "code",
498
515
  "named": true
@@ -668,6 +685,10 @@
668
685
  "type": "attribute",
669
686
  "named": true
670
687
  },
688
+ {
689
+ "type": "claim_marker",
690
+ "named": true
691
+ },
671
692
  {
672
693
  "type": "code",
673
694
  "named": true
@@ -684,10 +705,6 @@
684
705
  "type": "context",
685
706
  "named": true
686
707
  },
687
- {
688
- "type": "entity",
689
- "named": true
690
- },
691
708
  {
692
709
  "type": "importance",
693
710
  "named": true