functionalscript 0.33.0 → 0.34.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 (70) hide show
  1. package/README.md +1 -1
  2. package/fs/asserts/module.f.d.ts +1 -1
  3. package/fs/asserts/module.f.js +4 -1
  4. package/fs/bnf/data/module.f.d.ts +0 -103
  5. package/fs/bnf/data/module.f.js +10 -246
  6. package/fs/bnf/data/proof.f.d.ts +0 -10
  7. package/fs/bnf/data/proof.f.js +2 -642
  8. package/fs/bnf/descent/module.f.d.ts +56 -0
  9. package/fs/bnf/descent/module.f.js +119 -0
  10. package/fs/bnf/descent/proof.f.d.ts +5 -0
  11. package/fs/bnf/descent/proof.f.js +296 -0
  12. package/fs/bnf/ll1/module.f.d.ts +72 -0
  13. package/fs/bnf/ll1/module.f.js +153 -0
  14. package/fs/bnf/ll1/proof.f.d.ts +9 -0
  15. package/fs/bnf/ll1/proof.f.js +358 -0
  16. package/fs/cas/cli/module.f.d.ts +6 -0
  17. package/fs/cas/cli/module.f.js +56 -0
  18. package/fs/cas/cli/proof.f.d.ts +14 -0
  19. package/fs/cas/cli/proof.f.js +149 -0
  20. package/fs/cas/mcp/module.f.d.ts +9 -17
  21. package/fs/cas/mcp/module.f.js +116 -84
  22. package/fs/cas/mcp/proof.f.d.ts +5 -1
  23. package/fs/cas/mcp/proof.f.js +74 -32
  24. package/fs/cas/module.f.d.ts +35 -15
  25. package/fs/cas/module.f.js +168 -131
  26. package/fs/cas/proof.f.d.ts +16 -13
  27. package/fs/cas/proof.f.js +255 -121
  28. package/fs/ci/config/module.f.d.ts +14 -14
  29. package/fs/ci/config/module.f.js +14 -14
  30. package/fs/djs/tokenizer-new/module.f.js +1 -1
  31. package/fs/djs/tokenizer-new/proof.f.d.ts +2 -0
  32. package/fs/djs/tokenizer-new/proof.f.js +357 -229
  33. package/fs/effects/list/module.f.d.ts +31 -0
  34. package/fs/effects/list/module.f.js +16 -0
  35. package/fs/effects/module.f.d.ts +11 -5
  36. package/fs/effects/module.f.js +16 -6
  37. package/fs/effects/node/module.f.d.ts +29 -3
  38. package/fs/effects/node/module.f.js +35 -1
  39. package/fs/effects/node/module.js +32 -18
  40. package/fs/effects/node/virtual/module.f.js +57 -0
  41. package/fs/effects/proof.f.d.ts +4 -0
  42. package/fs/effects/proof.f.js +18 -1
  43. package/fs/fjs/module.f.js +2 -8
  44. package/fs/html/module.f.js +6 -8
  45. package/fs/mcp/module.f.d.ts +1 -1
  46. package/fs/mime/module.f.d.ts +101 -5
  47. package/fs/mime/module.f.js +159 -6
  48. package/fs/mime/proof.f.d.ts +25 -0
  49. package/fs/mime/proof.f.js +193 -3
  50. package/fs/text/code_point/module.f.d.ts +39 -2
  51. package/fs/text/code_point/module.f.js +74 -2
  52. package/fs/text/code_point/proof.f.d.ts +8 -0
  53. package/fs/text/code_point/proof.f.js +72 -0
  54. package/fs/text/utf16/module.f.js +4 -26
  55. package/fs/text/utf8/module.f.d.ts +27 -0
  56. package/fs/text/utf8/module.f.js +8 -14
  57. package/fs/types/function/operator/module.f.d.ts +26 -0
  58. package/fs/types/list/module.f.d.ts +3 -0
  59. package/fs/types/result/module.d.ts +2 -4
  60. package/fs/types/result/module.js +9 -3
  61. package/package.json +3 -3
  62. package/issues/demo/data/data.f.js +0 -12
  63. package/issues/demo/data/shared.f.js +0 -3
  64. package/issues/demo/fs/app.js +0 -4
  65. package/issues/demo/fs/math.f.js +0 -4
  66. package/issues/demo/sample/proof.f.js +0 -13
  67. /package/{issues → todo}/031-json.f.d.ts +0 -0
  68. /package/{issues → todo}/031-json.f.js +0 -0
  69. /package/{issues → todo}/proof.f.d.ts +0 -0
  70. /package/{issues → todo}/proof.f.js +0 -0
package/fs/cas/proof.f.js CHANGED
@@ -1,160 +1,294 @@
1
- import { commands } from "./module.f.js";
1
+ import { length, maxLength, msb, vec, vec8 } from "../types/bit_vec/module.f.js";
2
+ import { cBase32ToVec, vecToCBase32 } from "../cbase32/module.f.js";
2
3
  import { computeSync, sha256 } from "../crypto/sha2/module.f.js";
3
- import { empty, length, vec8 } from "../types/bit_vec/module.f.js";
4
+ import { fileCas, casAddFile, casUpload } from "./module.f.js";
4
5
  import { pure } from "../effects/module.f.js";
5
- import { run } from "../effects/mock/module.f.js";
6
- import { defaultNodeProgramOptions, emptyState, virtual } from "../effects/node/virtual/module.f.js";
7
- import { dispatch } from "../cli/module.f.js";
8
- import { assert } from "../asserts/module.f.js";
9
- const makeOptions = (args) => ({ ...defaultNodeProgramOptions, args });
10
- const main = dispatch(commands);
6
+ import { mkdir, writeFile, rm, readFile, access } from "../effects/node/module.f.js";
7
+ import { error, ok } from "../types/result/module.f.js";
8
+ import { emptyState, virtual } from "../effects/node/virtual/module.f.js";
9
+ import { join } from "../path/module.f.js";
10
+ import { nonEmpty, empty } from "../effects/list/module.f.js";
11
+ const testDir = './test-cas-cli';
12
+ // Create a 128 KiB big file content (at the max Vec size limit)
13
+ // This tests the boundary where files are at the chunk size limit
14
+ const createBigFileContent = () => {
15
+ const byteCount = 128n * 1024n; // 128 KiB
16
+ // Create a repeating pattern: 0x42 repeated across the file
17
+ return vec(byteCount * 8n)(0x42424242n);
18
+ };
19
+ // Test adding a big file and verifying the hash
20
+ const testAddBigFile = () => mkdir(testDir, { recursive: true }).step(() => {
21
+ const bigContent = createBigFileContent();
22
+ const bigFilePath = `${testDir}/big-file.bin`;
23
+ return writeFile(bigFilePath, bigContent).step(writeRes => {
24
+ if (writeRes[0] === 'error') {
25
+ throw new Error(`Failed to write test file: ${writeRes[1]}`);
26
+ }
27
+ const cas = fileCas(sha256)(testDir);
28
+ return casAddFile(cas)(bigFilePath).step(addRes => {
29
+ if (addRes[0] === 'error') {
30
+ throw new Error(`Failed to add file to CAS: ${addRes[1]}`);
31
+ }
32
+ const hash = addRes[1];
33
+ // Verify hash is 256 bits (SHA-256)
34
+ if (length(hash) !== 256n) {
35
+ throw new Error(`Expected hash length 256 bits, got ${length(hash)}`);
36
+ }
37
+ // Verify hash can be encoded/decoded
38
+ const hashCBase32 = vecToCBase32(hash);
39
+ const decodedHash = cBase32ToVec(hashCBase32);
40
+ if (decodedHash === null) {
41
+ throw new Error('Failed to decode hash from base32');
42
+ }
43
+ return rm(testDir).step(() => pure(undefined));
44
+ });
45
+ });
46
+ });
47
+ // Test adding and retrieving a big file
48
+ const testAddAndGetBigFile = () => mkdir(testDir, { recursive: true })
49
+ .step(() => {
50
+ const bigContent = createBigFileContent();
51
+ const bigFilePath = `${testDir}/big-file.bin`;
52
+ return writeFile(bigFilePath, bigContent)
53
+ .step(writeRes => {
54
+ if (writeRes[0] === 'error') {
55
+ throw new Error(`Failed to write test file: ${writeRes[1]}`);
56
+ }
57
+ const cas = fileCas(sha256)(testDir);
58
+ return casAddFile(cas)(bigFilePath)
59
+ .step(addRes => {
60
+ if (addRes[0] === 'error') {
61
+ throw new Error(`Failed to add file to CAS: ${addRes[1]}`);
62
+ }
63
+ const hash = addRes[1];
64
+ const storedPath = cas.url(hash);
65
+ // Verify file is stored at the expected location
66
+ return readFile(storedPath).step(readRes => {
67
+ if (readRes[0] === 'error') {
68
+ throw new Error(`Failed to read stored file: ${readRes[1]}`);
69
+ }
70
+ const storedContent = readRes[1];
71
+ // Verify content is the same size as original
72
+ const storedLen = length(storedContent);
73
+ const originalLen = length(bigContent);
74
+ if (storedLen !== originalLen) {
75
+ throw new Error(`Content size mismatch: stored ${storedLen} bits, expected ${originalLen} bits`);
76
+ }
77
+ return rm(testDir).step(() => pure(undefined));
78
+ });
79
+ });
80
+ });
81
+ });
11
82
  export const proof = {
12
- mainAdd: () => {
83
+ addBigFile: testAddBigFile,
84
+ addAndGetBigFile: testAddAndGetBigFile,
85
+ //
86
+ casWriteRead: () => {
87
+ // Round-trip a single-chunk payload through the real streaming CAS: `write` returns
88
+ // the content hash, and `read` streams the same bytes back as `ok` chunk items.
13
89
  const content = vec8(0x2an);
14
- const state = { ...emptyState, root: { myfile: [content] } };
15
- const [finalState, exitCode] = virtual(state)(main(makeOptions(['add', 'myfile'])));
16
- if (exitCode !== 0) {
17
- throw ['expected exit 0', exitCode];
90
+ const c = fileCas(sha256)('.');
91
+ const payload = nonEmpty(ok(content), empty());
92
+ const [state1, writeResult] = virtual(emptyState)(c.write(payload));
93
+ if (writeResult[0] !== 'ok') {
94
+ throw ['expected write ok', writeResult];
18
95
  }
19
- if (finalState.stdout.length === 0) {
20
- throw 'expected hash in stdout';
21
- }
22
- },
23
- mainAddWrongArgs: () => {
24
- const [finalState, exitCode] = virtual(emptyState)(main(makeOptions(['add'])));
25
- if (exitCode !== 1) {
26
- throw ['expected exit 1', exitCode];
96
+ const hash = writeResult[1];
97
+ if (length(hash) !== 256n) {
98
+ throw ['expected 256-bit hash', length(hash)];
27
99
  }
28
- if (finalState.stderr.length === 0) {
29
- throw 'expected error in stderr';
100
+ if (msb.cmp(hash)(computeSync(sha256)([content])) !== 0) {
101
+ throw 'write hash mismatch';
30
102
  }
31
- },
32
- mainGetFound: () => {
33
- const content = vec8(0x2an);
34
- const state = { ...emptyState, root: { myfile: [content] } };
35
- const [state1, exitCode1] = virtual(state)(main(makeOptions(['add', 'myfile'])));
36
- if (exitCode1 !== 0) {
37
- throw ['expected add exit 0', exitCode1];
103
+ const drain = (acc) => (stream) => stream.step((node) => {
104
+ if (node === undefined) {
105
+ return pure(ok(acc));
106
+ }
107
+ const { first, tail } = node;
108
+ if (first[0] === 'error') {
109
+ return pure(first);
110
+ }
111
+ return drain([...acc, first[1]])(tail);
112
+ });
113
+ const [, readResult] = virtual(state1)(drain([])(c.read(hash)));
114
+ if (readResult[0] !== 'ok') {
115
+ throw ['expected read ok', readResult];
38
116
  }
39
- const hashStr = state1.stdout.trim();
40
- const [, exitCode2] = virtual(state1)(main(makeOptions(['get', hashStr, 'output'])));
41
- if (exitCode2 !== 0) {
42
- throw ['expected get exit 0', exitCode2];
117
+ if (msb.cmp(msb.listToVec(readResult[1]))(content) !== 0) {
118
+ throw 'read content mismatch';
43
119
  }
44
120
  },
45
- mainGetNotFound: () => {
46
- // valid cBase32 hash that has not been stored
47
- const content = vec8(0x2an);
48
- const state = { ...emptyState, root: { myfile: [content] } };
49
- const [state1] = virtual(state)(main(makeOptions(['add', 'myfile'])));
50
- const hashStr = state1.stdout.trim();
51
- // use an empty store so the hash is not found
52
- const [finalState, exitCode] = virtual(emptyState)(main(makeOptions(['get', hashStr, 'output'])));
53
- if (exitCode !== 1) {
54
- throw ['expected exit 1', exitCode];
121
+ casReadMissingShard: () => {
122
+ // A missing shard surfaces as an explicit error *item*, never as end-of-stream.
123
+ const c = fileCas(sha256)('.');
124
+ const hash = computeSync(sha256)([vec8(0x2an)]);
125
+ const node = virtual(emptyState)(c.read(hash))[1];
126
+ if (node === undefined) {
127
+ throw 'missing shard must not be EOF';
55
128
  }
56
- if (finalState.stderr.length === 0) {
57
- throw 'expected error in stderr';
129
+ if (node.first[0] !== 'error') {
130
+ throw ['expected error item', node.tail];
58
131
  }
59
132
  },
60
- mainGetWrongArgs: () => {
61
- const [finalState, exitCode] = virtual(emptyState)(main(makeOptions(['get'])));
62
- if (exitCode !== 1) {
63
- throw ['expected exit 1', exitCode];
133
+ casWriteMultiChunk: () => {
134
+ // A multi-chunk payload streams through `writeBytes` chunk-by-chunk (the lease is
135
+ // renewed between chunks); the hash equals the SHA-256 of the concatenated bytes,
136
+ // and read streams the same content back.
137
+ const chunks = [vec8(0x11n), vec8(0x22n), vec8(0x33n)];
138
+ const c = fileCas(sha256)('.');
139
+ const payload = chunks.reduceRight((tail, chunk) => nonEmpty(ok(chunk), tail), empty());
140
+ const [state1, writeResult] = virtual(emptyState)(c.write(payload));
141
+ if (writeResult[0] !== 'ok') {
142
+ throw ['expected write ok', writeResult];
64
143
  }
65
- if (finalState.stderr.length === 0) {
66
- throw 'expected error in stderr';
144
+ const hash = writeResult[1];
145
+ if (msb.cmp(hash)(computeSync(sha256)(chunks)) !== 0) {
146
+ throw 'multi-chunk write hash mismatch';
67
147
  }
68
- },
69
- mainGetInvalidHash: () => {
70
- const [finalState, exitCode] = virtual(emptyState)(main(makeOptions(['get', 'not-a-valid-hash', 'output'])));
71
- if (exitCode !== 1) {
72
- throw ['expected exit 1', exitCode];
148
+ const drain = (acc) => (stream) => stream.step((node) => {
149
+ if (node === undefined) {
150
+ return pure(ok(acc));
151
+ }
152
+ const { first, tail } = node;
153
+ if (first[0] === 'error') {
154
+ return pure(first);
155
+ }
156
+ return drain([...acc, first[1]])(tail);
157
+ });
158
+ const [, readResult] = virtual(state1)(drain([])(c.read(hash)));
159
+ if (readResult[0] !== 'ok') {
160
+ throw ['expected read ok', readResult];
73
161
  }
74
- if (finalState.stderr.length === 0) {
75
- throw 'expected error in stderr';
162
+ const expected = msb.concat(msb.concat(chunks[0])(chunks[1]))(chunks[2]);
163
+ if (msb.cmp(msb.listToVec(readResult[1]))(expected) !== 0) {
164
+ throw 'multi-chunk read content mismatch';
76
165
  }
77
166
  },
78
- mainList: () => {
167
+ casWriteDedup: () => {
168
+ // Same content ⇒ same hash; the second upload's replace-`rename` publishes over the
169
+ // first, leaving exactly one shard in the store.
79
170
  const content = vec8(0x2an);
80
- const state = { ...emptyState, root: { myfile: [content] } };
81
- const [state1] = virtual(state)(main(makeOptions(['add', 'myfile'])));
82
- const [, exitCode] = virtual(state1)(main(makeOptions(['list'])));
83
- if (exitCode !== 0) {
84
- throw ['expected exit 0', exitCode];
171
+ const c = fileCas(sha256)('.');
172
+ const payload = () => nonEmpty(ok(content), empty());
173
+ const [state1, w1] = virtual(emptyState)(c.write(payload()));
174
+ const [state2, w2] = virtual(state1)(c.write(payload()));
175
+ if (w1[0] !== 'ok' || w2[0] !== 'ok') {
176
+ throw ['expected both writes ok', w1, w2];
177
+ }
178
+ if (msb.cmp(w1[1])(w2[1]) !== 0) {
179
+ throw 'dedup hash mismatch';
180
+ }
181
+ const [, hashes] = virtual(state2)(c.list());
182
+ if (hashes.length !== 1) {
183
+ throw ['expected one shard after dedup', hashes.length];
85
184
  }
86
185
  },
87
- mainListEmptyStore: () => {
88
- // A fresh directory has no `.cas` yet; listing must succeed (empty),
89
- // not crash unwrapping a readdir ENOENT.
90
- const [finalState, exitCode] = virtual(emptyState)(main(makeOptions(['list'])));
91
- if (exitCode !== 0) {
92
- throw ['expected exit 0', exitCode];
186
+ casWriteErrorItemAborts: () => {
187
+ // An error item mid-stream deletes the partial staging file and fails; nothing is
188
+ // published, so the store stays empty.
189
+ const c = fileCas(sha256)('.');
190
+ const okItem = ok(vec8(0x11n));
191
+ const errItem = error({ code: 'BOOM' });
192
+ const payload = nonEmpty(okItem, nonEmpty(errItem, empty()));
193
+ const [state1, result] = virtual(emptyState)(c.write(payload));
194
+ if (result[0] !== 'error') {
195
+ throw ['expected write error', result];
93
196
  }
94
- if (finalState.stdout !== '') {
95
- throw ['expected empty stdout', finalState.stdout];
197
+ const [, hashes] = virtual(state1)(c.list());
198
+ if (hashes.length !== 0) {
199
+ throw ['expected nothing published on abort', hashes];
96
200
  }
97
201
  },
98
- mainListCorruptStore: () => {
99
- // `.cas` exists but is a file, not a directory: a real storage error
100
- // that must surface, not be masked as an empty list.
101
- const state = { ...emptyState, root: { '.cas': [vec8(0x2an)] } };
102
- let threw = false;
103
- try {
104
- virtual(state)(main(makeOptions(['list'])));
202
+ casWriteReadExceedsMaxLength: () => {
203
+ // The point of streaming: a payload larger than a single `Vec`'s `maxLength`
204
+ // (128 KiB) must round-trip. `write` lands the chunks on disk without ever
205
+ // holding them as one `Vec`, and `read` streams them back the same way — so the
206
+ // round-trip is verified by hashing the read stream incrementally rather than
207
+ // concatenating it (which would itself overflow `maxLength`).
208
+ const big = vec(maxLength)(0xabn); // one full-size chunk: exactly maxLength bits
209
+ const tail = vec8(0x2an); // one more byte ⇒ total > maxLength
210
+ const chunks = [big, tail];
211
+ const c = fileCas(sha256)('.');
212
+ const payload = chunks.reduceRight((tl, chunk) => nonEmpty(ok(chunk), tl), empty());
213
+ const [state1, w] = virtual(emptyState)(c.write(payload));
214
+ if (w[0] !== 'ok') {
215
+ throw ['expected write ok', w];
216
+ }
217
+ const hash = w[1];
218
+ if (msb.cmp(hash)(computeSync(sha256)(chunks)) !== 0) {
219
+ throw 'oversized write hash mismatch';
105
220
  }
106
- catch {
107
- threw = true;
221
+ // Fold the read stream straight into a fresh SHA-2 state — never one `Vec`.
222
+ const rehash = (state) => (stream) => stream.step((node) => {
223
+ if (node === undefined) {
224
+ return pure(ok(sha256.end(state)));
225
+ }
226
+ const { first, tail } = node;
227
+ if (first[0] === 'error') {
228
+ return pure(first);
229
+ }
230
+ return rehash(sha256.append(first[1])(state))(tail);
231
+ });
232
+ const [, readBack] = virtual(state1)(rehash(sha256.init)(c.read(hash)));
233
+ if (readBack[0] !== 'ok') {
234
+ throw ['expected read ok', readBack];
108
235
  }
109
- if (!threw) {
110
- throw 'expected list to surface the storage error';
236
+ if (msb.cmp(readBack[1])(hash) !== 0) {
237
+ throw 'oversized read-back hash mismatch';
111
238
  }
112
239
  },
113
- mainNoCmd: () => {
114
- const [finalState, exitCode] = virtual(emptyState)(main(makeOptions([])));
115
- if (exitCode !== 1) {
116
- throw ['expected exit 1', exitCode];
240
+ casWriteGcReclaimsExpired: () => {
241
+ // A staging file whose deadline is in the past is reclaimed by the GC that `write`
242
+ // runs before staging its own file.
243
+ const stalePath = join('.', '.cas', '_stage', '0000000000000000000-stale');
244
+ const state0 = {
245
+ ...emptyState,
246
+ epochNs: 1_000_000,
247
+ root: { '.cas': { '_stage': { '0000000000000000000-stale': [vec8(0x99n)] } } },
248
+ };
249
+ const content = vec8(0x2an);
250
+ const c = fileCas(sha256)('.');
251
+ const x = c.write(nonEmpty(ok(content), empty()));
252
+ const [state1, w] = virtual(state0)(x);
253
+ if (w[0] !== 'ok') {
254
+ throw ['expected write ok', w];
117
255
  }
118
- if (finalState.stderr.length === 0) {
119
- throw 'expected error in stderr';
256
+ const [, present] = virtual(state1)(access(stalePath));
257
+ if (present[0] !== 'error') {
258
+ throw 'expected GC to reclaim the expired staging file';
120
259
  }
121
260
  },
122
- mainUnknownCmd: () => {
123
- const [finalState, exitCode] = virtual(emptyState)(main(makeOptions(['bogus'])));
124
- if (exitCode !== 1) {
125
- throw ['expected exit 1', exitCode];
261
+ casUploadSuccess: () => {
262
+ // A successful upload returns the hash and deletes the source file from cas_upload/.
263
+ const content = vec8(0x2an);
264
+ const state0 = { ...emptyState, root: { 'cas_upload': { 'myfile': [content] } } };
265
+ const [state1, result] = virtual(state0)(casUpload('.')('myfile'));
266
+ if (result[0] !== 'ok') {
267
+ throw ['expected casUpload ok', result];
126
268
  }
127
- if (finalState.stderr.length === 0) {
128
- throw 'expected error in stderr';
269
+ if (length(result[1]) !== 256n) {
270
+ throw ['expected 256-bit hash', length(result[1])];
129
271
  }
130
- },
131
- casWrite: () => {
132
- const c = {
133
- read: (_key) => pure(undefined),
134
- write: (value) => pure(computeSync(sha256)([value])),
135
- list: () => pure([]),
136
- };
137
- const [, hash] = run({})(undefined)(c.write(empty));
138
- // sha256 of empty input produces a 256-bit hash
139
- assert(hash !== undefined);
140
- if (length(hash) !== 256n) {
141
- throw ['expected 256-bit hash', length(hash)];
272
+ // Source must be deleted after successful publish.
273
+ const srcPath = join('.', 'cas_upload', 'myfile');
274
+ const [, srcAccess] = virtual(state1)(access(srcPath));
275
+ if (srcAccess[0] !== 'error') {
276
+ throw 'expected source to be deleted after successful upload';
142
277
  }
143
278
  },
144
- casReadPassthrough: () => {
145
- const stored = empty;
146
- const c = {
147
- read: (_key) => pure(stored),
148
- write: (value) => pure(computeSync(sha256)([value])),
149
- list: () => pure([stored]),
150
- };
151
- const [, readResult] = run({})(undefined)(c.read(empty));
152
- if (readResult !== stored) {
153
- throw ['read should pass through', readResult];
279
+ casUploadFailureKeepsSource: () => {
280
+ // A missing source file causes write to fail; casUpload returns error and the
281
+ // source is left in place (trivially: it was never there, but the upload is not published).
282
+ const state0 = { ...emptyState, root: {} };
283
+ const [state1, result] = virtual(state0)(casUpload('.')('nonexistent'));
284
+ if (result[0] !== 'error') {
285
+ throw ['expected casUpload to fail on missing source', result];
154
286
  }
155
- const [, listResult] = run({})(undefined)(c.list());
156
- if (listResult.length !== 1) {
157
- throw ['list should pass through', listResult];
287
+ // Nothing published to the store.
288
+ const c = fileCas(sha256)('.');
289
+ const [, hashes] = virtual(state1)(c.list());
290
+ if (hashes.length !== 0) {
291
+ throw ['expected nothing published on failed upload', hashes];
158
292
  }
159
293
  },
160
294
  };
@@ -7,8 +7,8 @@
7
7
  */
8
8
  export declare const images: {
9
9
  readonly ubuntu: {
10
- readonly intel: "ubuntu-24.04";
11
- readonly arm: "ubuntu-24.04-arm";
10
+ readonly intel: "ubuntu-26.04";
11
+ readonly arm: "ubuntu-26.04-arm";
12
12
  };
13
13
  readonly macos: {
14
14
  readonly intel: "macos-26-intel";
@@ -19,24 +19,24 @@ export declare const images: {
19
19
  readonly arm: "windows-11-arm";
20
20
  };
21
21
  };
22
- export declare const functionalscript: "0.32.4";
22
+ export declare const functionalscript: "0.33.0";
23
23
  export declare const bun = "1.3.14";
24
- export declare const deno = "2.8.3";
25
- export declare const playwright = "1.61.0";
24
+ export declare const deno = "2.9.0";
25
+ export declare const playwright = "1.61.1";
26
26
  export declare const node: {
27
- readonly default: "26.3.1";
28
- readonly node22: "22.23.0";
29
- readonly node24: "24.17.0";
27
+ readonly default: "26.4.0";
28
+ readonly node22: "22.23.1";
29
+ readonly node24: "24.18.0";
30
30
  };
31
- export declare const wasmtime = "45.0.2";
31
+ export declare const wasmtime = "46.0.1";
32
32
  export declare const wasmer = "7.1.0";
33
- export declare const tsgo = "7.0.0-dev.20260620.1";
33
+ export declare const tsgo = "7.0.0-dev.20260627.2";
34
34
  export declare const actions: {
35
35
  readonly 'actions/checkout': "v7";
36
- readonly 'actions/setup-node': "v6";
37
- readonly 'actions/cache': "v5";
38
- readonly 'denoland/setup-deno': "v2";
39
- readonly 'oven-sh/setup-bun': "v2";
36
+ readonly 'actions/setup-node': "v6.4.0";
37
+ readonly 'actions/cache': "v6.1.0";
38
+ readonly 'denoland/setup-deno': "v2.0.4";
39
+ readonly 'oven-sh/setup-bun': "v2.2.0";
40
40
  readonly 'bytecodealliance/actions/wasmtime/setup': "v1";
41
41
  readonly 'wasmerio/setup-wasmer': "v3.1";
42
42
  readonly 'dtolnay/rust-toolchain': "1.96.0";
@@ -8,8 +8,8 @@
8
8
  // https://docs.github.com/en/actions/reference/runners/github-hosted-runners#standard-github-hosted-runners-for-public-repositories
9
9
  export const images = {
10
10
  ubuntu: {
11
- intel: 'ubuntu-24.04',
12
- arm: 'ubuntu-24.04-arm'
11
+ intel: 'ubuntu-26.04',
12
+ arm: 'ubuntu-26.04-arm'
13
13
  },
14
14
  macos: {
15
15
  intel: 'macos-26-intel',
@@ -24,25 +24,25 @@ export const images = {
24
24
  // published FunctionalScript release; do not tie it to package.json's current
25
25
  // in-repo version. A separate maintenance job advances this pin.
26
26
  // https://www.npmjs.com/package/functionalscript
27
- export const functionalscript = '0.32.4';
27
+ export const functionalscript = '0.33.0';
28
28
  // https://bun.sh/
29
29
  export const bun = '1.3.14';
30
30
  // https://deno.com/
31
- export const deno = '2.8.3';
31
+ export const deno = '2.9.0';
32
32
  // https://www.npmjs.com/package/playwright
33
- export const playwright = '1.61.0';
33
+ export const playwright = '1.61.1';
34
34
  // https://nodejs.org/en/download
35
35
  export const node = {
36
- default: '26.3.1',
37
- node22: '22.23.0',
38
- node24: '24.17.0',
36
+ default: '26.4.0',
37
+ node22: '22.23.1',
38
+ node24: '24.18.0',
39
39
  };
40
40
  // https://github.com/bytecodealliance/wasmtime/releases
41
- export const wasmtime = '45.0.2';
41
+ export const wasmtime = '46.0.1';
42
42
  // https://github.com/wasmerio/wasmer/releases
43
43
  export const wasmer = '7.1.0';
44
44
  // https://www.npmjs.com/package/@typescript/native-preview?activeTab=versions
45
- export const tsgo = '7.0.0-dev.20260620.1';
45
+ export const tsgo = '7.0.0-dev.20260627.2';
46
46
  // GitHub Action versions used by CI step builders. The key is the action
47
47
  // `owner/name`; call sites compose the full ref as
48
48
  // `` `${name}@${actions[name]}` ``.
@@ -51,13 +51,13 @@ export const actions = {
51
51
  // https://github.com/marketplace/actions/checkout
52
52
  'actions/checkout': 'v7',
53
53
  // https://github.com/marketplace/actions/setup-node-js-environment
54
- 'actions/setup-node': 'v6',
54
+ 'actions/setup-node': 'v6.4.0',
55
55
  // https://github.com/marketplace/actions/cache
56
- 'actions/cache': 'v5',
56
+ 'actions/cache': 'v6.1.0',
57
57
  // https://github.com/marketplace/actions/setup-deno
58
- 'denoland/setup-deno': 'v2',
58
+ 'denoland/setup-deno': 'v2.0.4',
59
59
  // https://github.com/marketplace/actions/setup-bun
60
- 'oven-sh/setup-bun': 'v2',
60
+ 'oven-sh/setup-bun': 'v2.2.0',
61
61
  // https://github.com/bytecodealliance/actions
62
62
  'bytecodealliance/actions/wasmtime/setup': 'v1',
63
63
  // https://github.com/wasmerio/setup-wasmer
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * @module
5
5
  */
6
- import { descentParser } from "../../bnf/data/module.f.js";
6
+ import { descentParser } from "../../bnf/descent/module.f.js";
7
7
  import { eof, join0Plus, max, none, not, notSet, oneEncode, option, range, remove, repeat, repeat0Plus, repeat1Plus, set, unicodeRange } from "../../bnf/module.f.js";
8
8
  import { todo } from "../../asserts/module.f.js";
9
9
  export const parse = (input) => {
@@ -4,6 +4,8 @@ export declare const proof: {
4
4
  djs: (() => void)[];
5
5
  operators: (() => void)[];
6
6
  ws: (() => void)[];
7
+ id: (() => void)[];
8
+ keywords: (() => void)[];
7
9
  throw: {
8
10
  parse: () => void;
9
11
  };