cursedbelt-core 2.13.2 → 2.13.3

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 (75) hide show
  1. package/dist/core/analytics/range.d.ts +2 -2
  2. package/dist/core/analytics/range.js +2 -2
  3. package/dist/core/analytics/schedule.d.ts +1 -1
  4. package/dist/core/analytics/schedule.js +3 -3
  5. package/dist/core/duplicates/index.d.ts +2 -2
  6. package/dist/core/duplicates/index.js +1 -1
  7. package/dist/core/file-tree/fileTreeModel.d.ts +3 -3
  8. package/dist/core/file-tree/fileTreeModel.js +2 -2
  9. package/dist/core/folder-tree/actions.d.ts +1 -1
  10. package/dist/core/folder-tree/actions.js +1 -1
  11. package/dist/core/master-lock/kdf.js +1 -1
  12. package/dist/core/master-lock/presence.d.ts +1 -1
  13. package/dist/core/master-lock/presence.js +1 -1
  14. package/dist/core/master-lock/wire.d.ts +1 -1
  15. package/dist/core/media/mediaItem.js +1 -1
  16. package/dist/core/media/types.d.ts +4 -4
  17. package/dist/core/media/videoCuts.d.ts +1 -1
  18. package/dist/core/media/videoCuts.js +2 -2
  19. package/dist/core/navigation/index.js +1 -1
  20. package/dist/core/navigation/navigationModel.d.ts +1 -1
  21. package/dist/core/navigation/navigationModel.js +1 -1
  22. package/dist/core/navigation/navigationSelectors.d.ts +2 -2
  23. package/dist/core/navigation/navigationSelectors.js +2 -2
  24. package/dist/core/navigation/searchCatalogue.d.ts +2 -2
  25. package/dist/core/navigation/searchCatalogue.js +4 -4
  26. package/dist/core/palette/fuzzyRank.d.ts +1 -1
  27. package/dist/core/palette/fuzzyRank.js +3 -3
  28. package/dist/core/tokens/registry.d.ts +1 -1
  29. package/dist/core/tokens/registry.js +1 -1
  30. package/dist/core/wire/__fixtures__/rowsMarshalWorker.js +2 -2
  31. package/dist/core/wire/index.d.ts +1 -1
  32. package/dist/core/wire/index.js +1 -1
  33. package/dist/core/wire/ingress.d.ts +4 -4
  34. package/dist/core/wire/ingress.js +12 -12
  35. package/dist/core/wire/marshalWorker.d.ts +1 -1
  36. package/dist/core/wire/marshalWorker.js +15 -15
  37. package/dist/core/wire/marshalling.d.ts +16 -16
  38. package/dist/core/wire/marshalling.js +13 -13
  39. package/dist/ctgrClient/convertRequest.js +2 -2
  40. package/dist/testing/bytes.d.ts +1 -1
  41. package/dist/testing/bytes.js +1 -1
  42. package/package.json +1 -1
  43. package/src/core/analytics/range.spec.ts +1 -1
  44. package/src/core/analytics/range.ts +2 -2
  45. package/src/core/analytics/schedule.spec.ts +3 -3
  46. package/src/core/analytics/schedule.ts +3 -3
  47. package/src/core/duplicates/index.ts +2 -2
  48. package/src/core/file-tree/fileTreeModel.ts +4 -4
  49. package/src/core/folder-tree/actions.ts +1 -1
  50. package/src/core/master-lock/kdf.ts +1 -1
  51. package/src/core/master-lock/presence.ts +1 -1
  52. package/src/core/master-lock/wire.ts +1 -1
  53. package/src/core/media/mediaItem.ts +1 -1
  54. package/src/core/media/types.ts +4 -4
  55. package/src/core/media/videoCuts.ts +2 -2
  56. package/src/core/navigation/index.ts +1 -1
  57. package/src/core/navigation/navigation.spec.ts +3 -3
  58. package/src/core/navigation/navigationModel.ts +2 -2
  59. package/src/core/navigation/navigationSelectors.ts +3 -3
  60. package/src/core/navigation/searchCatalogue.ts +4 -4
  61. package/src/core/palette/fuzzyRank.ts +3 -3
  62. package/src/core/tokens/registry.ts +2 -2
  63. package/src/core/wire/__fixtures__/rowsMarshalWorker.ts +2 -2
  64. package/src/core/wire/index.ts +1 -1
  65. package/src/core/wire/ingress.spec.ts +12 -12
  66. package/src/core/wire/ingress.ts +15 -15
  67. package/src/core/wire/marshalWorker.spec.ts +7 -7
  68. package/src/core/wire/marshalWorker.ts +15 -15
  69. package/src/core/wire/marshalling.spec.ts +3 -3
  70. package/src/core/wire/marshalling.ts +25 -25
  71. package/src/ctgrClient/convertRequest.ts +2 -2
  72. package/src/namedSubpathsResolve.spec.ts +1 -1
  73. package/src/publishShape.spec.ts +1 -1
  74. package/src/shippedFilesAreTracked.spec.ts +2 -2
  75. package/src/testing/bytes.ts +1 -1
@@ -1,5 +1,5 @@
1
1
  // Pure matcher + grouper for the instant client-side "pages" search layer. Ranks a
2
- // derived catalogue ({@link deriveSearchCatalogue}) against a query and buckets the
2
+ // derived catalog ({@link deriveSearchCatalogue}) against a query and buckets the
3
3
  // hits by their owning domain. Kept pure + framework-free so it's unit-testable and
4
4
  // shared by HeaderSearch and (task 14) the command palette. The palette upgrades the
5
5
  // *ranking* to uFuzzy; this is the dependency-free baseline both can fall back to.
@@ -49,8 +49,8 @@ function scoreEntry(entry: SearchCatalogueEntry, q: string): number {
49
49
  }
50
50
 
51
51
  /**
52
- * Filter + rank a catalogue by `query`. Empty/blank query → `[]` (the instant layer
53
- * shows nothing until the user types). Stable: equal scores keep catalogue order.
52
+ * Filter + rank a catalog by `query`. Empty/blank query → `[]` (the instant layer
53
+ * shows nothing until the user types). Stable: equal scores keep catalog order.
54
54
  */
55
55
  export function rankCatalogue(catalogue: SearchCatalogueEntry[], query: string): CatalogueHit[] {
56
56
  const q = norm(query);
@@ -61,7 +61,7 @@ export function rankCatalogue(catalogue: SearchCatalogueEntry[], query: string):
61
61
  if (score > 0) scored.push({ ...entry, score });
62
62
  }
63
63
  // Stable sort by score desc — Array.prototype.sort is stable in modern engines, so
64
- // equal scores retain catalogue (authoring) order.
64
+ // equal scores retain catalog (authoring) order.
65
65
  return scored.sort((a, b) => b.score - a.score);
66
66
  }
67
67
 
@@ -1,4 +1,4 @@
1
- // The command-palette ranking layer — uFuzzy over the nav catalogue. This is the
1
+ // The command-palette ranking layer — uFuzzy over the nav catalog. This is the
2
2
  // *upgrade* HeaderSearch's `rankCatalogue` (a substring scorer) cannot match: uFuzzy
3
3
  // scores by contiguous-match proximity, so abbreviated/typeahead input ranks the
4
4
  // right page first. Pure + synchronous + React-free (uFuzzy is regex-based, no DOM),
@@ -48,7 +48,7 @@ function haystackFor(item: NavItem): string {
48
48
 
49
49
  /**
50
50
  * The SECOND tier: what a destination holds rather than what it is called — its description,
51
- * and the group and place it sits under when the entry carries them (catalogue entries do).
51
+ * and the group and place it sits under when the entry carries them (catalog entries do).
52
52
  * Owner, 2026-10-09: *"I may not know where to go but typing something like 'api' brings up the
53
53
  * relevant page links quickly"* — a page found only by its exact name is not found by someone
54
54
  * who does not know the name.
@@ -70,7 +70,7 @@ function rankedIndexes(haystack: string[], q: string): number[] {
70
70
 
71
71
  /**
72
72
  * Rank `items` against `query`, best match first; non-matches dropped. Generic over the
73
- * item type (so callers can pass plain {@link NavItem}s *or* richer catalogue entries
73
+ * item type (so callers can pass plain {@link NavItem}s *or* richer catalog entries
74
74
  * that carry domain/group tags for grouping — the extra fields ride straight through).
75
75
  * An empty/blank query returns `[]` (the palette shows its cold state instead).
76
76
  *
@@ -40,7 +40,7 @@ export interface TokenDef<S extends z.ZodType = z.ZodType> {
40
40
  subtypeOf?: string;
41
41
  /** Canonical payload injected by the V7.4 wire smoke probe. Must satisfy `schema`. */
42
42
  sample: z.infer<S>;
43
- /** True when this token receives third-party traffic — triggers the V3 marshaller gates. */
43
+ /** True when this token receives third-party traffic — triggers the V3 marshaler gates. */
44
44
  external?: boolean;
45
45
  deprecated?: TokenDeprecation;
46
46
  description: string;
@@ -493,7 +493,7 @@ export const BASE_TOKENS: readonly TokenDef[] = [
493
493
  id: 'knowledge:records',
494
494
  mode: 'value',
495
495
  external: true,
496
- description: 'Imported record rows (CSV/sheet/webhook) — external traffic, marshaller-gated (02 §7.1).',
496
+ description: 'Imported record rows (CSV/sheet/webhook) — external traffic, marshaler-gated (02 §7.1).',
497
497
  schema: z.object({ rows: z.array(z.record(z.string(), z.unknown())) }),
498
498
  sample: { rows: [{ id: '1' }] },
499
499
  },
@@ -1,9 +1,9 @@
1
1
  /**
2
- * A REAL marshalling worker entry, used by `marshalWorker.spec.ts` to prove the
2
+ * A REAL marshaling worker entry, used by `marshalWorker.spec.ts` to prove the
3
3
  * round-trip over an actual OS thread rather than over an injected fake.
4
4
  *
5
5
  * This is also the shape every production entry has, so it doubles as the
6
- * reference an app author copies: construct the marshaller, hand it to
6
+ * reference an app author copies: construct the marshaler, hand it to
7
7
  * `serveMarshalWorker`, done. The host never imports this file — it names it,
8
8
  * and the worker imports it.
9
9
  */
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * This entry exists because of Law #1, for the same reason `client/index.ts`
5
5
  * gives that reason for `createWireHub`: an ingress route has to be able to
6
- * IMPORT the marshalling seam, and a worker entry has to be able to import
6
+ * IMPORT the marshaling seam, and a worker entry has to be able to import
7
7
  * `serveMarshalWorker`. Until the Worker commit (05 §B1) neither symbol had any
8
8
  * export path at all — `marshalInbound` was reachable only from inside this
9
9
  * package, which is most of why it went three arcs with zero callers.
@@ -35,7 +35,7 @@ const registryWith = (marshaller: CCWireMarshaller) => {
35
35
  };
36
36
 
37
37
  describe('createMarshalledIngress', () => {
38
- it('marshals a payload through the token’s registered marshaller', async () => {
38
+ it('marshals a payload through the token’s registered marshaler', async () => {
39
39
  const ingress = createMarshalledIngress({ registry: registryWith(rowsMarshaller()) });
40
40
  await expect(ingress.ingest('knowledge:records', { rows: [{ id: 'a' }] })).resolves.toEqual({
41
41
  rows: [{ id: 'a' }],
@@ -45,7 +45,7 @@ describe('createMarshalledIngress', () => {
45
45
 
46
46
  it('is a 404 for an unregistered token, not a 400', async () => {
47
47
  const ingress = createMarshalledIngress({ registry: createMarshallerRegistry() });
48
- // From outside, "no marshaller" and "no such token" are the same fact.
48
+ // From outside, "no marshaler" and "no such token" are the same fact.
49
49
  // Distinguishing them would make an ingress an enumeration oracle for the
50
50
  // app's whole wire surface.
51
51
  await expect(ingress.ingest('nope', {})).rejects.toMatchObject({
@@ -55,20 +55,20 @@ describe('createMarshalledIngress', () => {
55
55
  await ingress.dispose();
56
56
  });
57
57
 
58
- it('carries the marshaller’s own typed refusals through unchanged', async () => {
58
+ it('carries the marshaler’s own typed refusals through unchanged', async () => {
59
59
  const ingress = createMarshalledIngress({
60
60
  registry: registryWith(rowsMarshaller({ maxPayloadBytes: 8 })),
61
61
  });
62
- // 413, from the marshaller's declared ceiling — the ingress adds no policy
63
- // of its own about size, because the marshaller is where that is declared.
62
+ // 413, from the marshaler's declared ceiling — the ingress adds no policy
63
+ // of its own about size, because the marshaler is where that is declared.
64
64
  await expect(ingress.ingest('knowledge:records', { rows: [{ id: 'a-very-long-id' }] })).rejects.toMatchObject({
65
65
  status: 413,
66
66
  });
67
67
  await ingress.dispose();
68
68
  });
69
69
 
70
- it('preserves the marshalling tier’s status codes rather than flattening them', async () => {
71
- // These codes are the marshalling tier's, unchanged, and the distinction is
70
+ it('preserves the marshaling tier’s status codes rather than flattening them', async () => {
71
+ // These codes are the marshaling tier's, unchanged, and the distinction is
72
72
  // load-bearing: a payload `validate` refuses is the CALLER's wrong shape
73
73
  // (400), while a transform whose OUTPUT violates the token schema means an
74
74
  // upstream provider changed shape under us (502 — not our error budget, and
@@ -114,10 +114,10 @@ describe('createMarshalledIngress', () => {
114
114
  * The reason this module exists at all. `createMarshalWorkerClient` spawns a
115
115
  * thread PER CALL, so a route handler that called it per request would leak one
116
116
  * OS thread per webhook — a server that gets slower for a week and then dies,
117
- * with nothing in the marshalling API to warn you. Caching per entry is not an
117
+ * with nothing in the marshaling API to warn you. Caching per entry is not an
118
118
  * optimization here; it is the whole point of having one owner.
119
119
  */
120
- it('reuses ONE thread for a marshaller that offloads, and disposes it once', async () => {
120
+ it('reuses ONE thread for a marshaler that offloads, and disposes it once', async () => {
121
121
  const disposed: string[] = [];
122
122
  const ingress = createMarshalledIngress({
123
123
  registry: registryWith(
@@ -156,7 +156,7 @@ describe('createMarshalledIngress', () => {
156
156
 
157
157
  /* --------------------------------------------------------- request bodies */
158
158
 
159
- it('parses a JSON body and hands the marshaller a VALUE', async () => {
159
+ it('parses a JSON body and hands the marshaler a VALUE', async () => {
160
160
  const ingress = createMarshalledIngress({ registry: registryWith(rowsMarshaller()) });
161
161
  const request = new Request('http://x/hook', {
162
162
  method: 'POST',
@@ -235,7 +235,7 @@ describe('adding an ingress later is a ROUTE, not a refactor (E16/D8)', () => {
235
235
  expect(ok.status).toBe(202);
236
236
  expect(accepted).toEqual([{ rows: [{ id: 'from-the-wire' }] }]);
237
237
 
238
- // And a CSV import is the SAME route with a different marshaller and a
238
+ // And a CSV import is the SAME route with a different marshaler and a
239
239
  // different service call — which is the claim the owner's condition asked
240
240
  // to be able to rely on.
241
241
  await ingress.dispose();
@@ -253,7 +253,7 @@ describe('adding an ingress later is a ROUTE, not a refactor (E16/D8)', () => {
253
253
  } catch (error) {
254
254
  // A real mount uses the app's error middleware; the point asserted here
255
255
  // is that the ingress hands up an error that already KNOWS its status,
256
- // so a route never has to map marshalling failures itself.
256
+ // so a route never has to map marshaling failures itself.
257
257
  return c.json({ success: false }, (error as { status?: number }).status as 413);
258
258
  }
259
259
  });
@@ -13,25 +13,25 @@
13
13
  * webhook endpoint that no product asked for would create a new orphan seam of
14
14
  * exactly the kind Law #1 exists to prevent, and it would guess wrong about the
15
15
  * part that actually differs between a webhook and an import (authentication,
16
- * routing, what the marshalled value is handed to). What does NOT differ — and
16
+ * routing, what the marshaled value is handed to). What does NOT differ — and
17
17
  * what every ingress would otherwise re-derive, differently — is this:
18
18
  *
19
19
  * 1. reading the body as bytes without buffering a stream into RAM twice;
20
- * 2. finding the marshaller for the token being fed;
20
+ * 2. finding the marshaler for the token being fed;
21
21
  * 3. owning a worker per `workerEntry` — a live OS thread, so exactly one
22
22
  * thing must own disposing of it — and resolving it lazily and cached;
23
23
  * 4. handing those failures up as errors that already KNOW their HTTP status,
24
- * so no route re-derives the mapping. The marshalling tier's codes are
24
+ * so no route re-derives the mapping. The marshaling tier's codes are
25
25
  * unchanged and deliberately distinct: 413 over the declared ceiling, 400
26
26
  * for a payload `validate` refuses (the caller's shape is wrong), 502 when
27
27
  * the TRANSFORM OUTPUT violates the token's canonical schema (an upstream
28
28
  * provider changed shape under us — not our error budget), 503 for a
29
- * payload that needs offload from a marshaller with no worker.
29
+ * payload that needs offload from a marshaler with no worker.
30
30
  *
31
31
  * Step 3 is the one that would go wrong. `createMarshalWorkerClient` spawns a
32
32
  * thread per call; a route handler that called it per request would leak one
33
33
  * OS thread per webhook, and the symptom would be a server that gets slower for
34
- * a week and then dies. Nothing about that is discoverable from the marshalling
34
+ * a week and then dies. Nothing about that is discoverable from the marshaling
35
35
  * API, which is precisely why it belongs here once instead of in each ingress.
36
36
  *
37
37
  * ## Adding an ingress later
@@ -47,7 +47,7 @@
47
47
  * });
48
48
  * ```
49
49
  *
50
- * A CSV import is the same three lines with a different marshaller and a
50
+ * A CSV import is the same three lines with a different marshaler and a
51
51
  * different service call. Neither needs to know that a worker exists.
52
52
  */
53
53
  import { AppError } from '../../shared/errors.js';
@@ -59,14 +59,14 @@ import {
59
59
  type MarshalWorker,
60
60
  } from './marshalling.js';
61
61
 
62
- /** No marshaller is registered for the token an ingress was asked to feed. */
62
+ /** No marshaler is registered for the token an ingress was asked to feed. */
63
63
  export const INGRESS_TOKEN_UNKNOWN = 'INGRESS_TOKEN_UNKNOWN';
64
64
 
65
65
  export interface MarshalledIngressOptions {
66
66
  /** The registry the app's wire tokens were registered on. */
67
67
  readonly registry: MarshallerRegistry;
68
68
  /**
69
- * Per-payload worker ceiling. A marshalling worker that hangs would otherwise
69
+ * Per-payload worker ceiling. A marshaling worker that hangs would otherwise
70
70
  * hold the request open for as long as the client is willing to wait.
71
71
  */
72
72
  readonly workerTimeoutMs?: number;
@@ -83,12 +83,12 @@ export interface MarshalledIngress {
83
83
  *
84
84
  * @throws {AppError} `INGRESS_TOKEN_UNKNOWN` (404) when nothing is registered;
85
85
  * `MARSHALLER_PAYLOAD_TOO_LARGE` (413/503), `MARSHALLER_VALIDATION_FAILED`
86
- * (400) or `MARSHALLER_SCHEMA_VIOLATION` (502) from the marshaller itself.
86
+ * (400) or `MARSHALLER_SCHEMA_VIOLATION` (502) from the marshaler itself.
87
87
  */
88
88
  ingest<Out = unknown>(tokenId: string, payload: unknown): Promise<Out>;
89
89
  /**
90
90
  * Read a `Request` body and marshal it for `tokenId`. JSON bodies are parsed;
91
- * anything else is handed to the marshaller as bytes, because a marshaller for
91
+ * anything else is handed to the marshaler as bytes, because a marshaler for
92
92
  * a CSV or a binary feed wants the bytes and re-encoding them would be lossy.
93
93
  */
94
94
  ingestRequest<Out = unknown>(tokenId: string, request: Request): Promise<Out>;
@@ -113,7 +113,7 @@ export const createMarshalledIngress = (options: MarshalledIngressOptions): Mars
113
113
  const entry = marshaller.workerEntry;
114
114
  if (entry === undefined) return undefined;
115
115
  if (disposed)
116
- throw new AppError('This ingress has been disposed and cannot spawn a marshalling worker.', {
116
+ throw new AppError('This ingress has been disposed and cannot spawn a marshaling worker.', {
117
117
  code: 'INGRESS_DISPOSED',
118
118
  status: 503,
119
119
  isOperational: false,
@@ -133,10 +133,10 @@ export const createMarshalledIngress = (options: MarshalledIngressOptions): Mars
133
133
  const marshallerFor = (tokenId: string): CCWireMarshaller => {
134
134
  const marshaller = options.registry.forToken(tokenId);
135
135
  if (!marshaller)
136
- // 404, not 400: from outside, a token with no marshaller and a token that
136
+ // 404, not 400: from outside, a token with no marshaler and a token that
137
137
  // does not exist are the same fact, and distinguishing them would make
138
138
  // this endpoint an enumeration oracle for the app's wire surface.
139
- throw new AppError(`No marshaller is registered for wire token '${tokenId}'.`, {
139
+ throw new AppError(`No marshaler is registered for wire token '${tokenId}'.`, {
140
140
  code: INGRESS_TOKEN_UNKNOWN,
141
141
  status: 404,
142
142
  context: { tokenId },
@@ -153,8 +153,8 @@ export const createMarshalledIngress = (options: MarshalledIngressOptions): Mars
153
153
 
154
154
  async ingestRequest<Out>(tokenId: string, request: Request): Promise<Out> {
155
155
  const contentType = request.headers.get('content-type') ?? '';
156
- // JSON is parsed here so the marshaller sees a value rather than a string
157
- // it would have to parse itself (and parse DIFFERENTLY per marshaller).
156
+ // JSON is parsed here so the marshaler sees a value rather than a string
157
+ // it would have to parse itself (and parse DIFFERENTLY per marshaler).
158
158
  // A malformed body is the CALLER's error — 400 — and must not read as a
159
159
  // validation failure of a payload we never managed to decode.
160
160
  const payload = contentType.includes('application/json')
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The marshalling Worker (05 §B1) — proven over a REAL thread.
2
+ * The marshaling Worker (05 §B1) — proven over a REAL thread.
3
3
  *
4
4
  * The seam has had an injectable `MarshalWorker` since it was written, and the
5
5
  * old suite exercised that seam with a fake. What it could never show is the
@@ -33,7 +33,7 @@ const marshaller = (over: Partial<CCWireMarshaller<unknown, z.infer<typeof schem
33
33
  ...over,
34
34
  }) as CCWireMarshaller<unknown, z.infer<typeof schema>>;
35
35
 
36
- describe('a real marshalling worker', () => {
36
+ describe('a real marshaling worker', () => {
37
37
  it('runs validate + transform off-thread and returns the result', async () => {
38
38
  const client = createMarshalWorkerClient({ entry: WORKER_ENTRY, timeoutMs: 20_000 });
39
39
  try {
@@ -87,7 +87,7 @@ describe('a real marshalling worker', () => {
87
87
  }
88
88
  }, 30_000);
89
89
 
90
- it('is the DEFAULT path: marshalInbound resolves the marshaller’s own workerEntry', async () => {
90
+ it('is the DEFAULT path: marshalInbound resolves the marshaler’s own workerEntry', async () => {
91
91
  const client = createMarshalWorkerClient({ entry: WORKER_ENTRY, timeoutMs: 20_000 });
92
92
  try {
93
93
  let ranOnMainThread = false;
@@ -100,7 +100,7 @@ describe('a real marshalling worker', () => {
100
100
  }),
101
101
  { rows: [{ id: 'x' }] },
102
102
  // No `worker:` — the point of the commit is that an ingress route wires
103
- // nothing per-marshaller; it supplies one resolver and offload happens.
103
+ // nothing per-marshaler; it supplies one resolver and offload happens.
104
104
  { offloadThresholdBytes: 4, resolveWorker: () => client },
105
105
  );
106
106
  expect(result).toEqual({ rows: [{ id: 'worker:x' }] });
@@ -162,17 +162,17 @@ describe('marshal worker lifecycle', () => {
162
162
  });
163
163
 
164
164
  describe('requiresWorkerOffload — a derived fact, not a declared one', () => {
165
- it('is false for a marshaller that can never exceed the main-thread limit', () => {
165
+ it('is false for a marshaler that can never exceed the main-thread limit', () => {
166
166
  // 256KB ceiling: no payload it accepts can reach the 512KB boundary, so
167
167
  // demanding a worker of it would be noise.
168
168
  expect(requiresWorkerOffload({ maxPayloadBytes: 256 * 1024 })).toBe(false);
169
169
  });
170
170
 
171
- it('is true for a marshaller whose ceiling is above it', () => {
171
+ it('is true for a marshaler whose ceiling is above it', () => {
172
172
  expect(requiresWorkerOffload({ maxPayloadBytes: 2 * 1024 * 1024 })).toBe(true);
173
173
  });
174
174
 
175
- it('names the missing artifact when an offload-needing marshaller has no entry', async () => {
175
+ it('names the missing artifact when an offload-needing marshaler has no entry', async () => {
176
176
  // The 503 that D1 was about. It is still reachable in code — V3 is what makes
177
177
  // it unreachable in a verified app — and when it fires it must say what to
178
178
  // build, not merely that something is missing.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The marshalling Worker (05 §B1, second half) — `validate` + `transform` for a
2
+ * The marshaling Worker (05 §B1, second half) — `validate` + `transform` for a
3
3
  * large inbound payload, off the thread that has to answer requests.
4
4
  *
5
5
  * `marshalling.ts` has always had the SIZE BOUNDARY and the injection seam; what
@@ -8,19 +8,19 @@
8
8
  * the missing half: a real, long-lived worker with a request/response protocol,
9
9
  * on both runtimes cursedbelt ships to.
10
10
  *
11
- * ## Why the marshaller names its own worker entry
11
+ * ## Why the marshaler names its own worker entry
12
12
  *
13
- * A marshaller is mostly FUNCTIONS (`validate`, `transform`, a Zod schema), and
13
+ * A marshaler is mostly FUNCTIONS (`validate`, `transform`, a Zod schema), and
14
14
  * functions do not survive structured clone — a worker cannot be handed one, it
15
15
  * has to `import` it. The obvious design (one shared worker that resolves any
16
- * marshaller by id from a registry module) needs the host to declare, register
17
- * and keep in sync a second module listing every marshaller, and it gives that
16
+ * marshaler by id from a registry module) needs the host to declare, register
17
+ * and keep in sync a second module listing every marshaler, and it gives that
18
18
  * one worker the authority to run all of them.
19
19
  *
20
- * Instead each marshaller declares `workerEntry`: the module that constructs
21
- * exactly that marshaller and calls {@link serveMarshalWorker}. The worker can
22
- * therefore only ever run the one marshaller it was built for, the host wires
23
- * nothing, and — the part that matters for the gate — "can this marshaller
20
+ * Instead each marshaler declares `workerEntry`: the module that constructs
21
+ * exactly that marshaler and calls {@link serveMarshalWorker}. The worker can
22
+ * therefore only ever run the one marshaler it was built for, the host wires
23
+ * nothing, and — the part that matters for the gate — "can this marshaler
24
24
  * offload?" stops being a boolean somebody remembered to set and becomes a
25
25
  * question about an artifact that either exists or does not. V3 checks it
26
26
  * statically (`marshaller-worker-offload-missing`), so the 503 path below is
@@ -133,7 +133,7 @@ export async function serveMarshalWorker<Inbound, Out>(
133
133
  id: request.id,
134
134
  ok: false,
135
135
  code: MARSHALLER_VALIDATION_FAILED,
136
- message: `Inbound payload rejected by marshaller '${marshaller.id}'.`,
136
+ message: `Inbound payload rejected by marshaler '${marshaller.id}'.`,
137
137
  } satisfies MarshalWorkerResponse);
138
138
  return;
139
139
  }
@@ -249,7 +249,7 @@ function spawnHostWorker(entry: string | URL): HostWorker {
249
249
  }
250
250
 
251
251
  /**
252
- * A long-lived worker for ONE marshaller, multiplexing concurrent payloads.
252
+ * A long-lived worker for ONE marshaler, multiplexing concurrent payloads.
253
253
  *
254
254
  * Long-lived rather than one-worker-per-payload deliberately: thread startup
255
255
  * plus module load is tens of milliseconds, which on a burst of imports would
@@ -304,7 +304,7 @@ export function createMarshalWorkerClient(options: MarshalWorkerClientOptions):
304
304
  for (const id of [...pending.keys()])
305
305
  settle(id, (p) =>
306
306
  p.reject(
307
- new AppError(`Marshalling worker failed: ${message}`, {
307
+ new AppError(`Marshaling worker failed: ${message}`, {
308
308
  code: MARSHALLER_WORKER_FAILED,
309
309
  status: 500,
310
310
  context: { worker: String(options.entry) },
@@ -317,7 +317,7 @@ export function createMarshalWorkerClient(options: MarshalWorkerClientOptions):
317
317
  run<Inbound, Out>(_marshallerId: string, payload: Inbound): Promise<Out> {
318
318
  if (disposed)
319
319
  return Promise.reject(
320
- new AppError('Marshalling worker has been disposed.', {
320
+ new AppError('Marshaling worker has been disposed.', {
321
321
  code: MARSHALLER_WORKER_FAILED,
322
322
  status: 500,
323
323
  context: { worker: String(options.entry) },
@@ -328,7 +328,7 @@ export function createMarshalWorkerClient(options: MarshalWorkerClientOptions):
328
328
  const timer = setTimeout(() => {
329
329
  pending.delete(id);
330
330
  reject(
331
- new AppError(`Marshalling worker did not answer within ${timeoutMs}ms.`, {
331
+ new AppError(`Marshaling worker did not answer within ${timeoutMs}ms.`, {
332
332
  code: MARSHALLER_WORKER_TIMEOUT,
333
333
  status: 504,
334
334
  context: { worker: String(options.entry), timeoutMs },
@@ -345,7 +345,7 @@ export function createMarshalWorkerClient(options: MarshalWorkerClientOptions):
345
345
  for (const id of [...pending.keys()])
346
346
  settle(id, (p) =>
347
347
  p.reject(
348
- new AppError('Marshalling worker was disposed while a payload was in flight.', {
348
+ new AppError('Marshaling worker was disposed while a payload was in flight.', {
349
349
  code: MARSHALLER_WORKER_FAILED,
350
350
  status: 503,
351
351
  context: { worker: String(options.entry) },
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Port marshalling + the 512KB worker gate (02 §7.1).
2
+ * Port marshaling + the 512KB worker gate (02 §7.1).
3
3
  */
4
4
  import { describe, expect, it } from 'bun:test';
5
5
  import { z } from 'zod';
@@ -44,7 +44,7 @@ describe('marshalInbound', () => {
44
44
  expect(result).toEqual({ rows: [{ id: '1' }] });
45
45
  });
46
46
 
47
- it('rejects a payload over the marshaller’s own limit before scheduling any work', async () => {
47
+ it('rejects a payload over the marshaler’s own limit before scheduling any work', async () => {
48
48
  let transformed = false;
49
49
  await expect(
50
50
  marshalInbound(
@@ -122,7 +122,7 @@ describe('marshalInbound', () => {
122
122
  });
123
123
 
124
124
  describe('createMarshallerRegistry', () => {
125
- it('refuses a marshaller with no declared payload ceiling', () => {
125
+ it('refuses a marshaler with no declared payload ceiling', () => {
126
126
  const registry = createMarshallerRegistry();
127
127
  expect(() => registry.register('knowledge:records', marshaller({ maxPayloadBytes: 0 }))).toThrow(
128
128
  /maxPayloadBytes/,
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Port marshalling + the 512KB worker gate (02 §7.1).
2
+ * Port marshaling + the 512KB worker gate (02 §7.1).
3
3
  *
4
4
  * External payloads — webhooks, third-party feeds, spreadsheet imports — never
5
- * touch component code. A marshaller registered on the token is the only entry,
5
+ * touch component code. A marshaler registered on the token is the only entry,
6
6
  * and its `transform` output is checked against the token's canonical Zod schema
7
7
  * (V3 asserts this statically; here it is enforced at runtime too, because a
8
8
  * provider can change its shape without anyone recompiling).
@@ -21,7 +21,7 @@ import { AppError } from '../../shared/errors.js';
21
21
  export const MARSHALLER_WORKER_OFFLOAD_BYTES = 512 * 1024;
22
22
 
23
23
  /**
24
- * The ONE marshaller contract (05 §B1, unified 2026-07-26).
24
+ * The ONE marshaler contract (05 §B1, unified 2026-07-26).
25
25
  *
26
26
  * There were TWO interfaces of this name in this package: this one, and a
27
27
  * divergent copy in `core/tokens/registry.ts` that additionally required
@@ -35,24 +35,24 @@ export const MARSHALLER_WORKER_OFFLOAD_BYTES = 512 * 1024;
35
35
  */
36
36
  export interface CCWireMarshaller<Inbound = unknown, Out = unknown> {
37
37
  id: string;
38
- /** The wire token this marshaller feeds — V3 resolves it against the registry. */
38
+ /** The wire token this marshaler feeds — V3 resolves it against the registry. */
39
39
  tokenId: string;
40
40
  /** REQUIRED — V3 `marshaller-payload-unbounded` when absent or non-positive. */
41
41
  maxPayloadBytes: number;
42
42
  /**
43
- * The module that runs this marshaller's `validate`+`transform` off the main
43
+ * The module that runs this marshaler's `validate`+`transform` off the main
44
44
  * thread — an entry calling `serveMarshalWorker` (`core/wire/marshalWorker.ts`).
45
45
  *
46
46
  * **This replaced a `workerOffload: boolean` in the Worker commit (05 §B1).**
47
47
  * That flag was authored by hand and asserted a capability the codebase did
48
- * not have: every marshaller in the repo set it `true` while no worker
48
+ * not have: every marshaler in the repo set it `true` while no worker
49
49
  * existed anywhere, so the V3 gate it fed was checking that someone had
50
- * remembered to type `true`. Whether a marshaller can offload is now a
50
+ * remembered to type `true`. Whether a marshaler can offload is now a
51
51
  * question about an ARTIFACT — this entry either exists or it does not — and
52
52
  * whether it NEEDS to is {@link requiresWorkerOffload}, derived from
53
53
  * `maxPayloadBytes`. Neither is a promise anyone can make by hand.
54
54
  *
55
- * Optional because a marshaller whose `maxPayloadBytes` sits under the
55
+ * Optional because a marshaler whose `maxPayloadBytes` sits under the
56
56
  * main-thread limit can never reach the offload path; V3 requires it of
57
57
  * exactly those that can.
58
58
  */
@@ -64,9 +64,9 @@ export interface CCWireMarshaller<Inbound = unknown, Out = unknown> {
64
64
  }
65
65
 
66
66
  /**
67
- * Can this marshaller ever reach the offload path? A DERIVED fact (05 §B1).
67
+ * Can this marshaler ever reach the offload path? A DERIVED fact (05 §B1).
68
68
  *
69
- * A marshaller that refuses anything over 256KB can never produce a payload
69
+ * A marshaler that refuses anything over 256KB can never produce a payload
70
70
  * above the 512KB main-thread limit, so it needs no worker and demanding one
71
71
  * would be noise. One whose ceiling is 2MB certainly can, and without a
72
72
  * `workerEntry` its large payloads are a guaranteed 503 — which is why V3
@@ -111,13 +111,13 @@ export interface MarshalWorker {
111
111
 
112
112
  export interface MarshalOptions {
113
113
  /**
114
- * Use THIS worker instead of the one the marshaller's `workerEntry` names.
114
+ * Use THIS worker instead of the one the marshaler's `workerEntry` names.
115
115
  * Left unset in production: offload is the default path, resolved from the
116
- * marshaller itself, so an ingress route needs no worker wiring of its own.
116
+ * marshaler itself, so an ingress route needs no worker wiring of its own.
117
117
  */
118
118
  worker?: MarshalWorker;
119
119
  /**
120
- * Resolves a worker for a marshaller that declares a `workerEntry`. The host
120
+ * Resolves a worker for a marshaler that declares a `workerEntry`. The host
121
121
  * supplies this once (`createMarshalWorkerClient`, cached per entry) — it is a
122
122
  * parameter rather than a module-level singleton because a worker is a live
123
123
  * OS thread, and something has to own disposing of it.
@@ -128,9 +128,9 @@ export interface MarshalOptions {
128
128
  }
129
129
 
130
130
  /**
131
- * Run a payload through its marshaller, offloading past the size gate.
131
+ * Run a payload through its marshaler, offloading past the size gate.
132
132
  *
133
- * Order matters: the marshaller's OWN `maxPayloadBytes` is checked first, so an
133
+ * Order matters: the marshaler's OWN `maxPayloadBytes` is checked first, so an
134
134
  * oversized payload is refused with a typed diagnostic before any work — worker
135
135
  * or otherwise — is scheduled for it.
136
136
  */
@@ -143,7 +143,7 @@ export async function marshalInbound<Inbound, Out>(
143
143
 
144
144
  if (bytes > marshaller.maxPayloadBytes)
145
145
  throw new AppError(
146
- `Payload of ${bytes} bytes exceeds marshaller '${marshaller.id}' limit of ${marshaller.maxPayloadBytes}.`,
146
+ `Payload of ${bytes} bytes exceeds marshaler '${marshaller.id}' limit of ${marshaller.maxPayloadBytes}.`,
147
147
  {
148
148
  code: MARSHALLER_PAYLOAD_TOO_LARGE,
149
149
  status: 413,
@@ -155,15 +155,15 @@ export async function marshalInbound<Inbound, Out>(
155
155
 
156
156
  if (bytes > threshold) {
157
157
  // Offload is the DEFAULT path (05 §B1): an explicitly injected worker wins,
158
- // otherwise the marshaller's own `workerEntry` is resolved through the host's
159
- // resolver. Neither present means this marshaller has no offload path at all
158
+ // otherwise the marshaler's own `workerEntry` is resolved through the host's
159
+ // resolver. Neither present means this marshaler has no offload path at all
160
160
  // — which V3 refuses to verify, so a verified app never reaches this throw.
161
161
  const worker =
162
162
  options.worker ??
163
163
  (marshaller.workerEntry ? options.resolveWorker?.(marshaller as CCWireMarshaller<never, never>) : undefined);
164
164
  if (!worker)
165
165
  throw new AppError(
166
- `Payload of ${bytes} bytes exceeds the ${threshold}-byte main-thread limit and marshaller '${marshaller.id}' has no marshalling worker.`,
166
+ `Payload of ${bytes} bytes exceeds the ${threshold}-byte main-thread limit and marshaler '${marshaller.id}' has no marshaling worker.`,
167
167
  {
168
168
  code: MARSHALLER_PAYLOAD_TOO_LARGE,
169
169
  status: 503,
@@ -173,8 +173,8 @@ export async function marshalInbound<Inbound, Out>(
173
173
  threshold,
174
174
  workerEntry: marshaller.workerEntry ?? null,
175
175
  hint: marshaller.workerEntry
176
- ? 'The marshaller declares a workerEntry but no resolveWorker was supplied — pass createMarshalWorkerClient through MarshalOptions.resolveWorker.'
177
- : 'Give the marshaller a workerEntry (a module calling serveMarshalWorker), or lower maxPayloadBytes below the main-thread limit.',
176
+ ? 'The marshaler declares a workerEntry but no resolveWorker was supplied — pass createMarshalWorkerClient through MarshalOptions.resolveWorker.'
177
+ : 'Give the marshaler a workerEntry (a module calling serveMarshalWorker), or lower maxPayloadBytes below the main-thread limit.',
178
178
  },
179
179
  },
180
180
  );
@@ -185,7 +185,7 @@ export async function marshalInbound<Inbound, Out>(
185
185
  }
186
186
 
187
187
  if (!marshaller.validate(payload))
188
- throw new AppError(`Inbound payload rejected by marshaller '${marshaller.id}'.`, {
188
+ throw new AppError(`Inbound payload rejected by marshaler '${marshaller.id}'.`, {
189
189
  code: MARSHALLER_VALIDATION_FAILED,
190
190
  status: 400,
191
191
  context: { marshaller: marshaller.id },
@@ -202,7 +202,7 @@ export async function marshalInbound<Inbound, Out>(
202
202
  function assertSchema<Inbound, Out>(marshaller: CCWireMarshaller<Inbound, Out>, value: Out): Out {
203
203
  const parsed = marshaller.targetZodSchema.safeParse(value);
204
204
  if (!parsed.success)
205
- throw new AppError(`Marshaller '${marshaller.id}' produced output that violates its token's schema.`, {
205
+ throw new AppError(`Marshaler '${marshaller.id}' produced output that violates its token's schema.`, {
206
206
  code: MARSHALLER_SCHEMA_VIOLATION,
207
207
  status: 502,
208
208
  context: {
@@ -213,7 +213,7 @@ function assertSchema<Inbound, Out>(marshaller: CCWireMarshaller<Inbound, Out>,
213
213
  return parsed.data;
214
214
  }
215
215
 
216
- /** The registry of marshallers, keyed by token id (02 §7.1: registered ON the token). */
216
+ /** The registry of marshalers, keyed by token id (02 §7.1: registered ON the token). */
217
217
  export interface MarshallerRegistry {
218
218
  register(tokenId: string, marshaller: CCWireMarshaller): void;
219
219
  forToken(tokenId: string): CCWireMarshaller | undefined;
@@ -225,7 +225,7 @@ export function createMarshallerRegistry(): MarshallerRegistry {
225
225
  return {
226
226
  register(tokenId, marshaller) {
227
227
  if (marshaller.maxPayloadBytes === undefined || marshaller.maxPayloadBytes <= 0)
228
- throw new AppError(`Marshaller '${marshaller.id}' must declare a positive maxPayloadBytes.`, {
228
+ throw new AppError(`Marshaler '${marshaller.id}' must declare a positive maxPayloadBytes.`, {
229
229
  code: 'marshaller-payload-unbounded',
230
230
  status: 500,
231
231
  context: { marshaller: marshaller.id, tokenId },
@@ -93,7 +93,7 @@ async function formDataToBody(formData: FormData): Promise<Record<string, unknow
93
93
  * The request body as a JS value: a JSON string is parsed, a plain string rides as itself.
94
94
  *
95
95
  * 🔴 Anything else is REFUSED. The tunnel carries a JSON value or a form's files; a `File`, a
96
- * `Blob`, bytes, a stream or `URLSearchParams` handed through here was JSON-serialised as `{}` —
96
+ * `Blob`, bytes, a stream or `URLSearchParams` handed through here was JSON-serialized as `{}` —
97
97
  * desk's import preview posted a 3.4 MB workbook and the server described "a JSON file" with `{}`
98
98
  * as its sample (forge task 3443). A loud error at the call is the bug; a silent `{}` is data loss.
99
99
  * Send an upload as `FormData`, which is carried whole.
@@ -101,7 +101,7 @@ async function formDataToBody(formData: FormData): Promise<Record<string, unknow
101
101
  function bodyFromInit(body: BodyInit | null | undefined, method: string, url: string): unknown {
102
102
  if (body === null || body === undefined) return undefined;
103
103
  if (typeof body !== 'string') {
104
- // A plain object or array a caller cast to `BodyInit` serialises as itself — carried as before.
104
+ // A plain object or array a caller cast to `BodyInit` serializes as itself — carried as before.
105
105
  const proto = Object.getPrototypeOf(body);
106
106
  if (Array.isArray(body) || proto === Object.prototype || proto === null) return body;
107
107
  const shape = Object.prototype.toString.call(body).slice(8, -1);
@@ -103,7 +103,7 @@ describe('subpaths named in this repo resolve', () => {
103
103
  });
104
104
 
105
105
  it('knows what the manifest exports', () => {
106
- // If `exports` is ever read wrong, every offence below silently becomes one.
106
+ // If `exports` is ever read wrong, every offense below silently becomes one.
107
107
  expect(exported.has('')).toBe(true); // the "." root entry
108
108
  expect(exported.has('/master-lock')).toBe(true);
109
109
  expect(exported.has('/react')).toBe(false); // the react tier stayed in `cursedbelt` at the 2026-09-15 split