@nimbus-sh/platform 0.8.2 → 0.14.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 (67) hide show
  1. package/dist/composition.d.ts +3 -2
  2. package/dist/composition.d.ts.map +1 -1
  3. package/dist/composition.js +34 -19
  4. package/dist/crc32.d.ts +5 -5
  5. package/dist/crc32.d.ts.map +1 -1
  6. package/dist/crc32.js +8 -12
  7. package/dist/diag-counters.d.ts +18 -10
  8. package/dist/diag-counters.d.ts.map +1 -1
  9. package/dist/diag-counters.js +7 -20
  10. package/dist/heap-estimate.d.ts +5 -20
  11. package/dist/heap-estimate.d.ts.map +1 -1
  12. package/dist/heap-estimate.js +6 -33
  13. package/dist/heavy-alloc-coord.d.ts +131 -11
  14. package/dist/heavy-alloc-coord.d.ts.map +1 -1
  15. package/dist/heavy-alloc-coord.js +241 -22
  16. package/dist/hex.d.ts +20 -0
  17. package/dist/hex.d.ts.map +1 -0
  18. package/dist/hex.js +29 -0
  19. package/dist/install-phase.d.ts +1 -15
  20. package/dist/install-phase.d.ts.map +1 -1
  21. package/dist/lexical-path.d.ts +11 -0
  22. package/dist/lexical-path.d.ts.map +1 -0
  23. package/dist/lexical-path.js +19 -0
  24. package/dist/limits.d.ts +4 -0
  25. package/dist/limits.d.ts.map +1 -1
  26. package/dist/limits.js +25 -0
  27. package/dist/module-source.d.ts.map +1 -1
  28. package/dist/module-source.js +2 -1
  29. package/dist/oom-classify.d.ts +4 -0
  30. package/dist/oom-classify.d.ts.map +1 -1
  31. package/dist/oom-classify.js +6 -0
  32. package/dist/realm-builtin.d.ts +2 -0
  33. package/dist/realm-builtin.d.ts.map +1 -0
  34. package/dist/realm-builtin.js +11 -0
  35. package/dist/utf8.d.ts +21 -1
  36. package/dist/utf8.d.ts.map +1 -1
  37. package/dist/utf8.js +73 -1
  38. package/dist/w7-frame.d.ts +92 -17
  39. package/dist/w7-frame.d.ts.map +1 -1
  40. package/dist/w7-frame.js +87 -35
  41. package/dist/wave-writer.d.ts +11 -6
  42. package/dist/wave-writer.d.ts.map +1 -1
  43. package/dist/wave-writer.js +28 -29
  44. package/dist/weighted-credit-pool.d.ts +43 -0
  45. package/dist/weighted-credit-pool.d.ts.map +1 -1
  46. package/dist/weighted-credit-pool.js +250 -46
  47. package/dist/worker-code.d.ts +48 -0
  48. package/dist/worker-code.d.ts.map +1 -0
  49. package/dist/worker-code.js +10 -0
  50. package/package.json +2 -2
  51. package/src/composition.ts +41 -21
  52. package/src/crc32.ts +9 -12
  53. package/src/diag-counters.ts +23 -22
  54. package/src/heap-estimate.ts +11 -40
  55. package/src/heavy-alloc-coord.ts +275 -20
  56. package/src/hex.ts +29 -0
  57. package/src/install-phase.ts +1 -15
  58. package/src/lexical-path.ts +17 -0
  59. package/src/limits.ts +29 -0
  60. package/src/module-source.ts +3 -1
  61. package/src/oom-classify.ts +8 -0
  62. package/src/realm-builtin.ts +22 -0
  63. package/src/utf8.ts +75 -1
  64. package/src/w7-frame.ts +152 -53
  65. package/src/wave-writer.ts +28 -27
  66. package/src/weighted-credit-pool.ts +256 -51
  67. package/src/worker-code.ts +38 -0
@@ -7,8 +7,35 @@
7
7
  * budget. Full-budget owners are exclusive; weighted owners may overlap only
8
8
  * while their retained-byte claims fit together.
9
9
  */
10
- import { CHUNK_SIZE, SUPERVISOR_IN_FLIGHT_ALLOCATION_BUDGET_BYTES, SUPERVISOR_READ_RESERVE_BYTES, } from './limits.js';
10
+ import { CHUNK_SIZE, SUPERVISOR_IN_FLIGHT_ALLOCATION_BUDGET_BYTES, SUPERVISOR_LOAD_WAIT_MS, SUPERVISOR_READ_RESERVE_BYTES, } from './limits.js';
11
11
  import { WeightedCreditPool, } from './weighted-credit-pool.js';
12
+ const DEFAULT_ALLOCATION_OWNER = { owner: 'supervisor allocation' };
13
+ const MAX_ALLOCATION_OWNER_ROWS = 16;
14
+ /**
15
+ * A facet's load the budget did not admit within its bound
16
+ * (SUPERVISOR_LOAD_WAIT_MS): nothing of it was read, and the facet is not
17
+ * started. Resource temporarily unavailable, as the ledger's refusal of a
18
+ * wait no release can satisfy is.
19
+ */
20
+ export class SupervisorLoadWaitError extends Error {
21
+ load;
22
+ bytes;
23
+ waitedMs;
24
+ held;
25
+ code = 'EAGAIN';
26
+ errno = -11;
27
+ constructor(load, bytes, waitedMs, held) {
28
+ super(`Resource temporarily unavailable: ${load} (${bytes.toLocaleString('en-US')} bytes) waited ${waitedMs} ms `
29
+ + `for this isolate's transient allocation budget and was not admitted (${held.current.toLocaleString('en-US')} `
30
+ + `of ${held.capacity.toLocaleString('en-US')} bytes held, ${held.queued} owners queued); `
31
+ + `holders=${JSON.stringify(held.holders)} waiting=${JSON.stringify(held.waiting)}`);
32
+ this.load = load;
33
+ this.bytes = bytes;
34
+ this.waitedMs = waitedMs;
35
+ this.held = held;
36
+ this.name = 'SupervisorLoadWaitError';
37
+ }
38
+ }
12
39
  /**
13
40
  * Reusable contract behind the supervisor singleton. A separate instance is
14
41
  * useful in tests and keeps the invariant independent of Nimbus internals.
@@ -24,24 +51,41 @@ export class SupervisorAllocationBudget {
24
51
  * cache it is filling.
25
52
  */
26
53
  lifecycleHolders = 0;
54
+ holders = new Set();
55
+ waiting = new Set();
27
56
  constructor(capacity, lifecycle = {}, reserve = {}) {
28
57
  this.capacity = capacity;
29
58
  this.lifecycle = lifecycle;
30
59
  this.credits = new WeightedCreditPool(capacity, reserve);
31
60
  }
32
61
  get stats() {
62
+ const now = Date.now();
63
+ const describe = (owner, bytes, since) => ({
64
+ owner: owner.owner.slice(0, 256), bytes, ageMs: Math.max(0, now - since),
65
+ ...(owner.pid === undefined ? {} : { pid: owner.pid }), ...(owner.session === undefined ? {} : { session: owner.session }),
66
+ });
33
67
  return {
34
68
  capacity: this.capacity,
35
69
  ...this.credits.stats,
70
+ holders: [...this.holders].sort((a, b) => b.credit.bytes - a.credit.bytes).slice(0, MAX_ALLOCATION_OWNER_ROWS)
71
+ .map(({ owner, credit, since }) => describe(owner, credit.bytes, since)),
72
+ waiting: [...this.waiting].slice(0, MAX_ALLOCATION_OWNER_ROWS).map(({ owner, bytes, since }) => describe(owner, bytes, since)),
36
73
  };
37
74
  }
75
+ get attributed() {
76
+ const totals = { prefetchBundleBytes: 0, preBundleSliceBytes: 0 };
77
+ for (const { owner, credit } of this.holders)
78
+ if (owner.attribution !== undefined)
79
+ totals[owner.attribution] += credit.bytes;
80
+ return totals;
81
+ }
38
82
  /**
39
83
  * Reserve bytes and, while held, mark the budget active so observers can
40
84
  * free heap headroom. For owners whose payload is what the headroom is for:
41
85
  * installs, clones, pre-bundles, boot payloads, streamed writes.
42
86
  */
43
- acquire(bytes, signal) {
44
- return this._acquire(bytes, signal, true);
87
+ acquire(bytes, signal, owner = DEFAULT_ALLOCATION_OWNER) {
88
+ return this._acquire(bytes, signal, true, owner);
45
89
  }
46
90
  /**
47
91
  * Reserve bytes WITHOUT driving the cache lifecycle, for owners that are
@@ -52,18 +96,116 @@ export class SupervisorAllocationBudget {
52
96
  * never warming. The byte credit is still taken — back-pressure is what
53
97
  * stops a large read overlapping a large write.
54
98
  */
55
- acquireWithoutLifecycle(bytes, signal) {
56
- return this._acquire(bytes, signal, false);
99
+ acquireWithoutLifecycle(bytes, signal, owner = DEFAULT_ALLOCATION_OWNER) {
100
+ return this._acquire(bytes, signal, false, owner);
101
+ }
102
+ /**
103
+ * Reserve what a facet's load holds while the loader takes its module map:
104
+ * `bytes`, or for a load larger than the whole budget the whole budget, so
105
+ * that it holds it alone and every owner after it waits. Granted in the
106
+ * budget's one FIFO order, so no owner queued after a load overtakes it,
107
+ * however small, and refused with SupervisorLoadWaitError when not granted
108
+ * within `waitMs`. Like a copy it holds bytes the session already has, for
109
+ * as long as the load takes, so the disposable VFS cache is not shrunk.
110
+ */
111
+ async acquireLoad(load, bytes, options) {
112
+ options.signal?.throwIfAborted();
113
+ const wanted = Math.min(bytes, this.capacity);
114
+ // Granted at once when nothing is queued and it fits, with no bound to arm.
115
+ const owner = options.owner ?? { owner: load };
116
+ const now = this.tryAcquire(wanted, false, owner);
117
+ if (now)
118
+ return now;
119
+ const started = Date.now();
120
+ const bound = new AbortController();
121
+ // Cleared as the wait settles: a pending timer keeps the hosting object from hibernating.
122
+ const timer = setTimeout(() => bound.abort(), options.waitMs);
123
+ try {
124
+ return await this._acquire(wanted, options.signal ? AbortSignal.any([bound.signal, options.signal]) : bound.signal, false, owner);
125
+ }
126
+ catch (error) {
127
+ if (bound.signal.aborted && options.signal?.aborted !== true)
128
+ throw new SupervisorLoadWaitError(load, bytes, Date.now() - started, this.stats);
129
+ throw error;
130
+ }
131
+ finally {
132
+ clearTimeout(timer);
133
+ }
134
+ }
135
+ /** Reclaimers of parked launches' retained credit, oldest registered first (reclaimable). */
136
+ reclaimers = new Set();
137
+ /**
138
+ * Register `reclaim`, which gives a parked launch's retained credit back
139
+ * before it returns (its map dropped, its lease released, the launch sent
140
+ * back to prepare), for running work to call when nothing else frees what
141
+ * it needs (acquireRunning). Unregistered just before it is called; the
142
+ * returned function unregisters it.
143
+ */
144
+ reclaimable(reclaim) {
145
+ this.reclaimers.add(reclaim);
146
+ // A running ask queued before this launch parked is owed it, once the registration has returned.
147
+ if (this.credits.aheadStarved)
148
+ queueMicrotask(() => this.reclaimForRunning());
149
+ return () => {
150
+ this.reclaimers.delete(reclaim);
151
+ };
152
+ }
153
+ /**
154
+ * Running work's credit, the lock order's one exception
155
+ * (acquireSupervisorLoad): granted at once where it fits, ahead of every
156
+ * queued ask; else, queued ahead of them all, it reclaims parked launches'
157
+ * retained credit, the oldest first, until it is granted; else it waits
158
+ * only for credit other running work holds.
159
+ */
160
+ async acquireRunning(bytes, signal, drivesLifecycle = true, owner = DEFAULT_ALLOCATION_OWNER) {
161
+ const wanted = Math.min(bytes, this.capacity);
162
+ const waiter = { owner: { ...owner }, bytes: wanted, since: Date.now() };
163
+ this.waiting.add(waiter);
164
+ try {
165
+ const lease = this.credits.acquireAhead(wanted, signal);
166
+ this.reclaimForRunning();
167
+ const credit = await lease;
168
+ this.waiting.delete(waiter);
169
+ return this.wrap(credit, drivesLifecycle, waiter.owner);
170
+ }
171
+ finally {
172
+ this.waiting.delete(waiter);
173
+ }
57
174
  }
58
- /** Reserve bytes now or not at all, driving the lifecycle as acquire does. */
59
- tryAcquire(bytes) {
175
+ /** Reclaim parked launches' credit, the oldest parked first, while a running ask waits: what a reclaim frees goes to running asks first. */
176
+ reclaimForRunning() {
177
+ for (const reclaim of this.reclaimers) {
178
+ if (!this.credits.aheadStarved)
179
+ return;
180
+ this.reclaimers.delete(reclaim);
181
+ reclaim();
182
+ }
183
+ }
184
+ /** acquireRunning's credit now, ahead of every queued ask, without reclaiming, or null. */
185
+ tryAcquireRunning(bytes, owner = DEFAULT_ALLOCATION_OWNER) {
186
+ const credit = this.credits.tryAcquireAhead(Math.min(bytes, this.capacity));
187
+ return credit ? this.wrap(credit, true, owner) : null;
188
+ }
189
+ /** Reserve bytes now or not at all, driving the lifecycle as acquire does (or not, `drivesLifecycle` false). */
190
+ tryAcquire(bytes, drivesLifecycle = true, owner = DEFAULT_ALLOCATION_OWNER) {
60
191
  const credit = this.credits.tryAcquire(bytes);
61
- return credit ? this.wrap(credit, true) : null;
192
+ return credit ? this.wrap(credit, drivesLifecycle, owner) : null;
62
193
  }
63
- async _acquire(bytes, signal, drivesLifecycle) {
64
- return this.wrap(await this.credits.acquire(bytes, signal), drivesLifecycle);
194
+ async _acquire(bytes, signal, drivesLifecycle, owner) {
195
+ const waiter = { owner: { ...owner }, bytes, since: Date.now() };
196
+ this.waiting.add(waiter);
197
+ try {
198
+ const credit = await this.credits.acquire(bytes, signal);
199
+ this.waiting.delete(waiter);
200
+ return this.wrap(credit, drivesLifecycle, waiter.owner);
201
+ }
202
+ finally {
203
+ this.waiting.delete(waiter);
204
+ }
65
205
  }
66
- wrap(credit, drivesLifecycle) {
206
+ wrap(credit, drivesLifecycle, owner) {
207
+ const holder = { owner: { ...owner }, credit, since: Date.now() };
208
+ this.holders.add(holder);
67
209
  if (drivesLifecycle) {
68
210
  this.lifecycleHolders++;
69
211
  if (!this.active) {
@@ -79,10 +221,14 @@ export class SupervisorAllocationBudget {
79
221
  shrinkTo: (nextBytes) => {
80
222
  credit.shrinkTo(nextBytes);
81
223
  },
224
+ tryGrowTo: (nextBytes) => credit.tryGrowTo(nextBytes),
225
+ attribute: (attribution) => { if (!released)
226
+ holder.owner = { ...holder.owner, attribution }; },
82
227
  release: () => {
83
228
  if (released)
84
229
  return;
85
230
  released = true;
231
+ this.holders.delete(holder);
86
232
  credit.release();
87
233
  if (!drivesLifecycle)
88
234
  return;
@@ -164,29 +310,102 @@ const supervisorAllocationBudget = new SupervisorAllocationBudget(SUPERVISOR_IN_
164
310
  /**
165
311
  * Reserve an exact number of supervisor-resident bytes.
166
312
  */
167
- export function acquireSupervisorAllocation(bytes, signal) {
168
- return supervisorAllocationBudget.acquire(bytes, signal);
313
+ export function acquireSupervisorAllocation(bytes, signal, owner) {
314
+ return supervisorAllocationBudget.acquire(bytes, signal, owner);
169
315
  }
170
316
  /** Reserve bytes now if they can be granted without waiting, else null. */
171
- export function tryAcquireSupervisorAllocation(bytes) {
172
- return supervisorAllocationBudget.tryAcquire(bytes);
317
+ export function tryAcquireSupervisorAllocation(bytes, owner) {
318
+ return supervisorAllocationBudget.tryAcquire(bytes, true, owner);
319
+ }
320
+ /**
321
+ * Reserve bytes for a running process's filesystem READ (its read RPCs):
322
+ * running work (acquireRunning), which does not shrink the disposable VFS
323
+ * cache, which reads are there to fill.
324
+ */
325
+ export function acquireSupervisorReadAllocation(bytes, signal, owner) {
326
+ return supervisorAllocationBudget.acquireRunning(bytes, signal, false, owner ?? { owner: 'running filesystem read' });
173
327
  }
174
328
  /**
175
- * Reserve bytes for a filesystem READ. Takes the same byte credit as any
176
- * other owner but does not shrink the disposable VFS cache, which reads are
177
- * there to fill.
329
+ * Reserve bytes for a short-lived copy of what the session already holds
330
+ * (a launch's module map made from a staged state), now or not at all, or
331
+ * by waiting (`signal`): the byte credit bounds how many such copies are
332
+ * live at once, but the disposable VFS cache is not shrunk for one, as it
333
+ * is not for a read. Shrinking it for every launch of a program already
334
+ * built cost each one its cache, and the copy is no install.
178
335
  */
179
- export function acquireSupervisorReadAllocation(bytes, signal) {
180
- return supervisorAllocationBudget.acquireWithoutLifecycle(bytes, signal);
336
+ export function tryAcquireSupervisorCopyAllocation(bytes, owner) {
337
+ return supervisorAllocationBudget.tryAcquire(bytes, false, owner ?? { owner: 'supervisor copy' });
338
+ }
339
+ /** {@link tryAcquireSupervisorCopyAllocation}, waiting for room. */
340
+ export function acquireSupervisorCopyAllocation(bytes, signal, owner) {
341
+ return supervisorAllocationBudget.acquireWithoutLifecycle(bytes, signal, owner ?? { owner: 'supervisor copy' });
342
+ }
343
+ /**
344
+ * `bytes` of this isolate for a facet's load (the wasm images read for it;
345
+ * `name` says whose), admitted on the supervisor budget
346
+ * (SupervisorAllocationBudget.acquireLoad): FIFO, the whole budget for one
347
+ * larger than it, refused by name after SUPERVISOR_LOAD_WAIT_MS. `signal`
348
+ * ends the wait.
349
+ *
350
+ * Lock order: supervisor credit, then a Dynamic Worker. Nothing waits for
351
+ * credit (SupervisorAllocationBudget acquire or acquireLoad, or growing a
352
+ * lease) while it holds a worker's fetch hold (beginLoaderFetch,
353
+ * claimAdmission, readmitRefused). While it holds one, it may give credit
354
+ * back, shrink it, or take credit without waiting (tryAcquire). Running work
355
+ * is the one exception, and comes first. Credit a running process needs (its
356
+ * write waves and the session RPCs it makes, through acquireRunning)
357
+ * overtakes every queued ask. When nothing else frees it, it reclaims parked
358
+ * launches' retained maps, oldest parked first: each is dropped, its launch
359
+ * is sent back to prepare, and the map is rebuilt at that launch's turn.
360
+ * Otherwise it waits only for credit other running work holds. A facet's load
361
+ * is not running work.
362
+ */
363
+ export function acquireSupervisorLoad(name, bytes, signal, owner) {
364
+ return supervisorAllocationBudget.acquireLoad(name, bytes, { waitMs: SUPERVISOR_LOAD_WAIT_MS, signal, owner });
365
+ }
366
+ /** acquireSupervisorLoad's credit now, without waiting, or null: all a load may take while it holds a worker. */
367
+ export function tryAcquireSupervisorLoad(bytes, owner = { owner: 'facet load' }) {
368
+ return supervisorAllocationBudget.tryAcquire(Math.min(bytes, supervisorAllocationBudget.capacity), false, owner);
369
+ }
370
+ /**
371
+ * Running work's credit (SupervisorAllocationBudget.acquireRunning): what a
372
+ * running process needs to go on (its write waves, the session RPCs it
373
+ * makes), never held up by a launch that is not running.
374
+ */
375
+ export function acquireSupervisorRunningAllocation(bytes, signal, owner) {
376
+ return supervisorAllocationBudget.acquireRunning(bytes, signal, true, owner ?? { owner: 'running supervisor work' });
377
+ }
378
+ /** acquireSupervisorRunningAllocation's credit now, ahead of every queued ask, without reclaiming, or null. */
379
+ export function tryAcquireSupervisorRunningAllocation(bytes, owner) {
380
+ return supervisorAllocationBudget.tryAcquireRunning(bytes, owner ?? { owner: 'running supervisor work' });
381
+ }
382
+ /** Register a parked launch's reclaimer on the isolate's budget (SupervisorAllocationBudget.reclaimable). */
383
+ export function reclaimableSupervisorAllocation(reclaim) {
384
+ return supervisorAllocationBudget.reclaimable(reclaim);
385
+ }
386
+ /** Run `load` holding acquireSupervisorLoad's credit for `bytes`, given back as it settles; for a load no worker hold waits on. */
387
+ export async function withSupervisorLoadAllocation(name, bytes, signal, load, owner) {
388
+ if (bytes === 0)
389
+ return load();
390
+ const lease = await acquireSupervisorLoad(name, bytes, signal, owner);
391
+ try {
392
+ return await load();
393
+ }
394
+ finally {
395
+ lease.release();
396
+ }
181
397
  }
182
398
  /**
183
399
  * Reserve the full budget for an allocation whose retained size is not known
184
400
  * accurately enough to overlap safely with other heavy work.
185
401
  */
186
- export async function acquireHeavyAlloc(signal) {
187
- const lease = await acquireSupervisorAllocation(SUPERVISOR_IN_FLIGHT_ALLOCATION_BUDGET_BYTES, signal);
402
+ export async function acquireHeavyAlloc(signal, owner = { owner: 'heavy supervisor work' }) {
403
+ const lease = await acquireSupervisorAllocation(SUPERVISOR_IN_FLIGHT_ALLOCATION_BUDGET_BYTES, signal, owner);
188
404
  return lease.release;
189
405
  }
190
406
  export function readSupervisorAllocationBudget() {
191
407
  return supervisorAllocationBudget.stats;
192
408
  }
409
+ export function readSupervisorAllocationAttribution() {
410
+ return supervisorAllocationBudget.attributed;
411
+ }
package/dist/hex.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * hex.ts — bytes as unseparated lowercase hex: the spelling of every content
3
+ * key, digest, object id and token Nimbus writes. It imports nothing, so a
4
+ * compiled guest body or a facet bundle takes it along; a hash is its
5
+ * caller's, as is any width, offset or truncation.
6
+ */
7
+ /**
8
+ * Each byte value's two hex digits: for a reader that spells a window of a
9
+ * larger buffer in place (git's object ids in a pack or a tree), where V8
10
+ * encodes a view natively slower than this table walks it.
11
+ */
12
+ export declare const HEX_BYTE: readonly string[];
13
+ /**
14
+ * Lowercase hex of `bytes`. A listing encodes one key per file, so this is
15
+ * on the enumeration's hot path: the native encoder where the runtime has
16
+ * one, else a table (measured 0.03 and 0.17 µs per 32-byte key, against
17
+ * 0.82 for a toString/padStart loop).
18
+ */
19
+ export declare function bytesToHex(bytes: Uint8Array): string;
20
+ //# sourceMappingURL=hex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hex.d.ts","sourceRoot":"","sources":["../src/hex.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,SAAS,MAAM,EAAiF,CAAC;AAKxH;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAKpD"}
package/dist/hex.js ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * hex.ts — bytes as unseparated lowercase hex: the spelling of every content
3
+ * key, digest, object id and token Nimbus writes. It imports nothing, so a
4
+ * compiled guest body or a facet bundle takes it along; a hash is its
5
+ * caller's, as is any width, offset or truncation.
6
+ */
7
+ /**
8
+ * Each byte value's two hex digits: for a reader that spells a window of a
9
+ * larger buffer in place (git's object ids in a pack or a tree), where V8
10
+ * encodes a view natively slower than this table walks it.
11
+ */
12
+ export const HEX_BYTE = Array.from({ length: 256 }, (_, byte) => byte.toString(16).padStart(2, '0'));
13
+ /** Uint8Array.prototype, with ES2026's toHex where the runtime has it: this TypeScript's library does not declare it. */
14
+ const prototype = Uint8Array.prototype;
15
+ const nativeHex = prototype.toHex;
16
+ /**
17
+ * Lowercase hex of `bytes`. A listing encodes one key per file, so this is
18
+ * on the enumeration's hot path: the native encoder where the runtime has
19
+ * one, else a table (measured 0.03 and 0.17 µs per 32-byte key, against
20
+ * 0.82 for a toString/padStart loop).
21
+ */
22
+ export function bytesToHex(bytes) {
23
+ if (nativeHex !== undefined)
24
+ return nativeHex.call(bytes);
25
+ let out = '';
26
+ for (let i = 0; i < bytes.length; i++)
27
+ out += HEX_BYTE[bytes[i]];
28
+ return out;
29
+ }
@@ -2,21 +2,7 @@
2
2
  * _shared/install-phase.ts — single source of truth for the npm-install
3
3
  * state-machine phase enum.
4
4
  *
5
- * History: CLN-1 (2026-05-11) — consolidated from two diverged copies.
6
- * - `npm/installer.ts:93-95` was the progress-event variant. Included
7
- * 'lock-check' (a real progress event emitted while parsing
8
- * package-lock.json) but lacked 'idle'.
9
- * - `observability/diag-counters.ts:33-35` was the counter-state variant.
10
- * Included 'idle' (the resting state when no install is in flight)
11
- * but lacked 'lock-check'. The diag-counter's `setInstallPhase()`
12
- * was actually called with 'idle' (installer.ts:184,201) — passing
13
- * a value not declared in installer.ts's local type. The type check
14
- * fell through to diag-counters' type because installer.ts imports
15
- * setInstallPhase from there; the local `InstallPhase` definition
16
- * in installer.ts was only used by `InstallProgress.phase`.
17
- *
18
- * Going forward both consumers import from this module; any new phase
19
- * value added here is automatically available everywhere.
5
+ * Every consumer imports it from here, so a phase added here is everyone's.
20
6
  *
21
7
  * Phase semantics (chronological order for a single install run):
22
8
  *
@@ -1 +1 @@
1
- {"version":3,"file":"install-phase.d.ts","sourceRoot":"","sources":["../src/install-phase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,YAAY,GACZ,SAAS,GACT,OAAO,GACP,MAAM,GACN,OAAO,GACP,OAAO,GACP,WAAW,GACX,QAAQ,GACR,MAAM,CAAC"}
1
+ {"version":3,"file":"install-phase.d.ts","sourceRoot":"","sources":["../src/install-phase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,YAAY,GACZ,SAAS,GACT,OAAO,GACP,MAAM,GACN,OAAO,GACP,OAAO,GACP,WAAW,GACX,QAAQ,GACR,MAAM,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The names of `path` once it is resolved lexically, after the names of
3
+ * `base` (taken as they are, not reduced again): empty names and `.`
4
+ * dropped, each `..` taking back the name before it, and a `..` at the root
5
+ * staying at the root, as POSIX resolves `/..`. The one root-clamped lexical
6
+ * reduction; whether the path was absolute or ended in `/` is its caller's to
7
+ * keep. Lexical only: a `..` after a symlink is not the link's parent, so a
8
+ * walk that follows links resolves it as it goes.
9
+ */
10
+ export declare function rootClampedSegments(path: string, base?: readonly string[]): string[];
11
+ //# sourceMappingURL=lexical-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lexical-path.d.ts","sourceRoot":"","sources":["../src/lexical-path.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,SAAS,MAAM,EAAO,GAAG,MAAM,EAAE,CAOxF"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The names of `path` once it is resolved lexically, after the names of
3
+ * `base` (taken as they are, not reduced again): empty names and `.`
4
+ * dropped, each `..` taking back the name before it, and a `..` at the root
5
+ * staying at the root, as POSIX resolves `/..`. The one root-clamped lexical
6
+ * reduction; whether the path was absolute or ended in `/` is its caller's to
7
+ * keep. Lexical only: a `..` after a symlink is not the link's parent, so a
8
+ * walk that follows links resolves it as it goes.
9
+ */
10
+ export function rootClampedSegments(path, base = []) {
11
+ const out = [...base];
12
+ for (const segment of path.split('/')) {
13
+ if (segment === '..')
14
+ out.pop();
15
+ else if (segment !== '' && segment !== '.')
16
+ out.push(segment);
17
+ }
18
+ return out;
19
+ }
package/dist/limits.d.ts CHANGED
@@ -102,7 +102,11 @@ export declare const ONE_SHOT_MODULE_MAP_MAX_BYTES: number;
102
102
  export declare const SUPERVISOR_HEAP_CEILING_BYTES: number;
103
103
  export declare const FACET_OWN_WRITE_MEMORY_BYTES: number;
104
104
  export declare const WASI_RESIDENT_STORE_BYTES: number;
105
+ export declare const RESIDENT_PAGE_BYTES: number;
106
+ export declare const RESIDENT_PAGE_CACHE_BYTES: number;
107
+ export declare const RESIDENT_PAGE_CACHE_FREE_SHARE = 0.25;
105
108
  export declare const SUPERVISOR_IN_FLIGHT_ALLOCATION_BUDGET_BYTES: number;
109
+ export declare const SUPERVISOR_LOAD_WAIT_MS = 60000;
106
110
  export declare const SUPERVISOR_READ_RESERVE_BYTES: number;
107
111
  export declare const MAX_GLOBAL_WRITE_STREAM_CREDIT_BYTES: number;
108
112
  export declare const PRE_BUNDLE_SLICE_CAP_BYTES: number;
@@ -1 +1 @@
1
- {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../src/limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,QAAS,CAAC;AAEjC,eAAO,MAAM,iBAAiB,QAAkB,CAAC;AACjD,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAI5C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,sBAAsB,cAAiB,CAAC;AAMrD,eAAO,MAAM,qBAAqB,QAAS,CAAC;AAE5C;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,QAAa,CAAC;AAErD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,UAAY,CAAC;AAI9C;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAIlD;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,OAAQ,CAAC;AAE3C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,8BAA8B,QAAS,CAAC;AAIrD;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAOhD,eAAO,MAAM,0BAA0B,QAAmB,CAAC;AAmB3D,eAAO,MAAM,6BAA6B,QAAmB,CAAC;AA6B9D,eAAO,MAAM,6BAA6B,QAAmB,CAAC;AAM9D,eAAO,MAAM,4BAA4B,QAAmB,CAAC;AAQ7D,eAAO,MAAM,yBAAyB,QAAmB,CAAC;AAO1D,eAAO,MAAM,4CAA4C,QAAmB,CAAC;AAY7E,eAAO,MAAM,6BAA6B,QAAc,CAAC;AAKzD,eAAO,MAAM,oCAAoC,QAAkB,CAAC;AAQpE,eAAO,MAAM,0BAA0B,QAA6B,CAAC;AACrE,eAAO,MAAM,sBAAsB,IAAI,CAAC"}
1
+ {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../src/limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,QAAS,CAAC;AAEjC,eAAO,MAAM,iBAAiB,QAAkB,CAAC;AACjD,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAI5C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,sBAAsB,cAAiB,CAAC;AAMrD,eAAO,MAAM,qBAAqB,QAAS,CAAC;AAE5C;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,QAAa,CAAC;AAErD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,UAAY,CAAC;AAI9C;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAIlD;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,OAAQ,CAAC;AAE3C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,8BAA8B,QAAS,CAAC;AAIrD;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAOhD,eAAO,MAAM,0BAA0B,QAAmB,CAAC;AAmB3D,eAAO,MAAM,6BAA6B,QAAmB,CAAC;AA6B9D,eAAO,MAAM,6BAA6B,QAAmB,CAAC;AAM9D,eAAO,MAAM,4BAA4B,QAAmB,CAAC;AAQ7D,eAAO,MAAM,yBAAyB,QAAmB,CAAC;AAM1D,eAAO,MAAM,mBAAmB,QAAY,CAAC;AAM7C,eAAO,MAAM,yBAAyB,QAAoB,CAAC;AAQ3D,eAAO,MAAM,8BAA8B,OAAO,CAAC;AAOnD,eAAO,MAAM,4CAA4C,QAAmB,CAAC;AAS7E,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAY9C,eAAO,MAAM,6BAA6B,QAAc,CAAC;AAKzD,eAAO,MAAM,oCAAoC,QAAkB,CAAC;AAQpE,eAAO,MAAM,0BAA0B,QAA6B,CAAC;AACrE,eAAO,MAAM,sBAAsB,IAAI,CAAC"}
package/dist/limits.js CHANGED
@@ -174,12 +174,37 @@ export const FACET_OWN_WRITE_MEMORY_BYTES = 32 * 1024 * 1024;
174
174
  // or a program that reads much, not what a short run holds. Past it the store
175
175
  // holds nothing more and the session answers.
176
176
  export const WASI_RESIDENT_STORE_BYTES = 32 * 1024 * 1024;
177
+ // A file too big to hold whole (over WASI_RESIDENT_FILE_CAP_BYTES: a pack, a
178
+ // deep history's .idx) is read through the resident store a page at a time:
179
+ // git's own unit for a paged pack index, and a sixteenth of its 1 MiB pack
180
+ // window, so one window is one batch read.
181
+ export const RESIDENT_PAGE_BYTES = 64 * 1024;
182
+ // The most a resident store holds of such pages, least recently used out
183
+ // first; in a one-shot's heap, never more than half its budget. Measured on vscode's full history (2.18M objects):
184
+ // a .idx of 57.5 MiB, of which every command touched ~49 MiB, and a .rev of
185
+ // 8.6 MiB, so the bound keeps a deep history's index and its hot pack windows.
186
+ export const RESIDENT_PAGE_CACHE_BYTES = 512 * 1024 * 1024;
187
+ // The pages are a cache in the session's one storage limit (N18), which the
188
+ // user's files share: they never hold more than this share of what they hold
189
+ // plus what the ledger says is still free at the last grant, so a filling
190
+ // session takes room from the cache, not from the user. Evicted pages are
191
+ // reused by the same facet database; its size, which df counts, stays at its
192
+ // high-water mark until the facet's storage is deleted.
193
+ export const RESIDENT_PAGE_CACHE_FREE_SHARE = 0.25;
177
194
  // Shared allowance for transient allocations in the supervisor DO. With the
178
195
  // VFS LRU shrunk to 8 MiB during an active reservation, 40 MiB of admitted
179
196
  // payload plus the 9 MiB bundle baseline stays below the 64 MiB soft ceiling
180
197
  // with 7 MiB left for metadata, structured-clone overhead, and runtime state.
181
198
  // This is 31.25% of the platform's 128 MiB hard isolate ceiling.
182
199
  export const SUPERVISOR_IN_FLIGHT_ALLOCATION_BUDGET_BYTES = 40 * 1024 * 1024;
200
+ // The longest a facet's load waits for that allowance before it is refused
201
+ // (acquireSupervisorLoadAllocation). The wait is FIFO, so a load waits only
202
+ // for the holds ahead of it, each of which ends when its own work does. A
203
+ // load is the one owner that waits while it holds a Dynamic Worker (the
204
+ // loader asks for its code then), so a launch that holds credit while it
205
+ // waits for a worker of the same Durable Object can close a cycle nothing
206
+ // ends: the bound refuses the load, by name, instead of leaving both to hang.
207
+ export const SUPERVISOR_LOAD_WAIT_MS = 60_000;
183
208
  // Reserved slice of that allowance for chunk-sized filesystem reads, so a
184
209
  // read is never queued behind a multi-megabyte owner for a wait that has
185
210
  // nothing to do with its own cost. A read only draws on this when the shared
@@ -1 +1 @@
1
- {"version":3,"file":"module-source.d.ts","sourceRoot":"","sources":["../src/module-source.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAC;CACzD;AAED,4FAA4F;AAC5F,qBAAa,qBAAqB;IAGa,QAAQ,CAAC,KAAK,EAAE,iBAAiB;IAF9E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBACV,KAAK,EAAE,WAAW,GAAG,UAAU,EAAW,KAAK,EAAE,iBAAiB;CAI/E;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,qBAAqB,CAAC;AAC9D,MAAM,MAAM,kBAAkB,GAAG,CAAC,MAAM,GAAG,iBAAiB,CAAC,EAAE,CAAC;AAEhE,gGAAgG;AAChG,qBAAa,YAAY;IAGX,QAAQ,CAAC,KAAK,EAAE,SAAS,gBAAgB,EAAE;IAFvD,OAAO,CAAC,MAAM,CAAqB;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBACP,KAAK,EAAE,SAAS,gBAAgB,EAAE;IAGvD,IAAI,IAAI,IAAI,MAAM,CAEjB;IACD,MAAM,IAAI,kBAAkB;CAG7B;AAED,qGAAqG;AACrG,wBAAgB,YAAY,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,qBAAqB,GAAG,YAAY,CAAC,EAAE,GAAG,YAAY,CAiB5K"}
1
+ {"version":3,"file":"module-source.d.ts","sourceRoot":"","sources":["../src/module-source.ts"],"names":[],"mappings":"AAEA,8EAA8E;AAC9E,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAC;CACzD;AAED,4FAA4F;AAC5F,qBAAa,qBAAqB;IAGa,QAAQ,CAAC,KAAK,EAAE,iBAAiB;IAF9E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBACV,KAAK,EAAE,WAAW,GAAG,UAAU,EAAW,KAAK,EAAE,iBAAiB;CAI/E;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,qBAAqB,CAAC;AAC9D,MAAM,MAAM,kBAAkB,GAAG,CAAC,MAAM,GAAG,iBAAiB,CAAC,EAAE,CAAC;AAEhE,gGAAgG;AAChG,qBAAa,YAAY;IAGX,QAAQ,CAAC,KAAK,EAAE,SAAS,gBAAgB,EAAE;IAFvD,OAAO,CAAC,MAAM,CAAqB;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBACP,KAAK,EAAE,SAAS,gBAAgB,EAAE;IAGvD,IAAI,IAAI,IAAI,MAAM,CAEjB;IACD,MAAM,IAAI,kBAAkB;CAG7B;AAED,qGAAqG;AACrG,wBAAgB,YAAY,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,qBAAqB,GAAG,YAAY,CAAC,EAAE,GAAG,YAAY,CAiB5K"}
@@ -1,3 +1,4 @@
1
+ import { utf8Length } from './utf8.js';
1
2
  /** Source already verified against its deployment pin. Shared across generated programs. */
2
3
  export class ImmutableModuleSource {
3
4
  asset;
@@ -16,7 +17,7 @@ export class ModuleSource {
16
17
  byteLength;
17
18
  constructor(parts) {
18
19
  this.parts = parts;
19
- this.byteLength = parts.reduce((bytes, part) => bytes + (typeof part === 'string' ? new TextEncoder().encode(part).byteLength : part.byteLength), 0);
20
+ this.byteLength = parts.reduce((bytes, part) => bytes + (typeof part === 'string' ? utf8Length(part) : part.byteLength), 0);
20
21
  }
21
22
  get text() {
22
23
  return this.joined ??= this.parts.map((part) => typeof part === 'string' ? part : part.text).join('');
@@ -153,6 +153,10 @@ export type DoCallClass =
153
153
  | 'storage_reset'
154
154
  /** The runtime flagged the error `retryable` itself. */
155
155
  | 'retryable_flag'
156
+ /** The platform failed the call without saying why ("internal error;
157
+ * reference = …", isUnexplainedPlatformError): whether it ran is unknown.
158
+ * Not a transient class: only a callee that converges repeats it. */
159
+ | 'platform_internal'
156
160
  /** The object shed the call under queue pressure. NEVER retried: retrying
157
161
  * an overloaded object is what overloaded it. */
158
162
  | 'overloaded'
@@ -1 +1 @@
1
- {"version":3,"file":"oom-classify.d.ts","sourceRoot":"","sources":["../src/oom-classify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AAEH,QAAA,MAAM,UAAU,kLAYN,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC;AAEjD,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAItD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAmErD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAO1D;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAInD;AAYD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAElE;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEtD;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,WAAW;AACrB,8CAA8C;AAC5C,oBAAoB;AACtB,8CAA8C;GAC5C,iBAAiB;AACnB,uEAAuE;GACrE,eAAe;AACjB,wDAAwD;GACtD,gBAAgB;AAClB;kDACkD;GAChD,YAAY;AACd,kEAAkE;GAChE,WAAW,CAAC;AAEhB;2DAC2D;AAC3D,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAK7D;AAmBD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAsB1D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAiBpD"}
1
+ {"version":3,"file":"oom-classify.d.ts","sourceRoot":"","sources":["../src/oom-classify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AAEH,QAAA,MAAM,UAAU,kLAYN,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC;AAEjD,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAItD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAmErD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAO1D;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAInD;AAYD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAElE;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEtD;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,WAAW;AACrB,8CAA8C;AAC5C,oBAAoB;AACtB,8CAA8C;GAC5C,iBAAiB;AACnB,uEAAuE;GACrE,eAAe;AACjB,wDAAwD;GACtD,gBAAgB;AAClB;;sEAEsE;GACpE,mBAAmB;AACrB;kDACkD;GAChD,YAAY;AACd,kEAAkE;GAChE,WAAW,CAAC;AAEhB;2DAC2D;AAC3D,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAK7D;AAmBD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CA0B1D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAiBpD"}
@@ -294,6 +294,7 @@ export function classifyDoCall(input) {
294
294
  const seen = new Set();
295
295
  const messages = [];
296
296
  let flagged = false;
297
+ let unexplained = false;
297
298
  let link = input;
298
299
  while (link !== null && !seen.has(link)) {
299
300
  seen.add(link);
@@ -303,6 +304,8 @@ export function classifyDoCall(input) {
303
304
  return 'overloaded';
304
305
  if ('retryable' in link && link.retryable === true)
305
306
  flagged = true;
307
+ if (isUnexplainedPlatformError(link))
308
+ unexplained = true;
306
309
  messages.push(link.message ?? '');
307
310
  const cause = link.cause;
308
311
  link = cause instanceof Error ? cause : null;
@@ -314,6 +317,9 @@ export function classifyDoCall(input) {
314
317
  }
315
318
  if (flagged)
316
319
  return 'retryable_flag';
320
+ // Only where nothing in the chain explains it: a wrapper's own words are not the platform's.
321
+ if (unexplained)
322
+ return 'platform_internal';
317
323
  return 'permanent';
318
324
  }
319
325
  /**
@@ -0,0 +1,2 @@
1
+ export declare function realmBuiltin<T>(id: string): T | undefined;
2
+ //# sourceMappingURL=realm-builtin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realm-builtin.d.ts","sourceRoot":"","sources":["../src/realm-builtin.ts"],"names":[],"mappings":"AAYA,wBAAgB,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CASzD"}
@@ -0,0 +1,11 @@
1
+ export function realmBuiltin(id) {
2
+ try {
3
+ const global = globalThis;
4
+ const current = global.process;
5
+ const own = (current && global[Symbol.for('nimbus.fronts')]?.get(current)?.own);
6
+ return (own ?? current)?.getBuiltinModule?.(id);
7
+ }
8
+ catch {
9
+ return undefined;
10
+ }
11
+ }
package/dist/utf8.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /**
2
- * utf8.ts — the UTF-8 length of a string, without encoding it.
2
+ * utf8.ts — the UTF-8 length of a string, and the order of two strings by
3
+ * their UTF-8 bytes, without encoding them.
3
4
  *
4
5
  * Bounds on names and payloads are in bytes, and the hot ones (every path a
5
6
  * W7 wave or a listing page carries) were measured by encoding the string
@@ -7,5 +8,24 @@
7
8
  * TextEncoder would write: one to four per code point, and three for a
8
9
  * lone surrogate, which it writes as U+FFFD.
9
10
  */
11
+ /**
12
+ * From this many UTF-16 units, a string is counted natively (longUtf8Length),
13
+ * into a scratch buffer of SCRATCH_BYTES. The resident store's count on the
14
+ * launch's captures (worker vfs/resident/cell-cost.ts) keeps the same policy,
15
+ * and tests/unit/utf8-length.mjs holds both to TextEncoder.
16
+ */
17
+ export declare const UTF8_LONG_UNITS = 256;
18
+ export declare const UTF8_SCRATCH_BYTES: number;
10
19
  export declare function utf8Length(text: string): number;
20
+ /**
21
+ * `a` against `b` (negative, 0, positive) as their UTF-8 bytes order them,
22
+ * as SQLite's `ORDER BY` of a text column and git's index do: code point
23
+ * order. A string UTF-8 cannot write (a lone surrogate) is ordered as WTF-8
24
+ * writes it, its surrogate a code point of its own: the order is total, as a
25
+ * listing's cursor needs, and decided at the first code point that differs,
26
+ * so a directory's entries follow it together. Units equal in both are
27
+ * passed as they are; two that differ, neither a surrogate, are their own
28
+ * code points; the rest, rare in a path, is surrogatesAt's.
29
+ */
30
+ export declare function compareUtf8(a: string, b: string): number;
11
31
  //# sourceMappingURL=utf8.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utf8.d.ts","sourceRoot":"","sources":["../src/utf8.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAqB/C"}
1
+ {"version":3,"file":"utf8.d.ts","sourceRoot":"","sources":["../src/utf8.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,eAAe,MAAM,CAAC;AACnC,eAAO,MAAM,kBAAkB,QAAa,CAAC;AAK7C,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAsB/C;AA6BD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAUxD"}