@hraness/direct 0.7.5

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 (56) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +436 -0
  3. package/dist/core/index.js +162 -0
  4. package/dist/index-1csg00w4.js +1167 -0
  5. package/dist/index-6mdfd2ey.js +464 -0
  6. package/dist/index-7n1h75n6.js +616 -0
  7. package/dist/index.js +232 -0
  8. package/dist/react.js +32 -0
  9. package/dist/testing/index.js +1069 -0
  10. package/dist/tooling/bombadil.js +2117 -0
  11. package/dist/tooling/browser-verification-entry.js +1499 -0
  12. package/dist/tooling/bundle-boundary.js +119 -0
  13. package/dist/web.js +605 -0
  14. package/package.json +179 -0
  15. package/skills/direct/AGENTS.md +13 -0
  16. package/skills/direct/SKILL.md +49 -0
  17. package/skills/direct/agents/openai.yaml +4 -0
  18. package/skills/direct/references/adoption.md +131 -0
  19. package/skills/direct/references/install.md +91 -0
  20. package/skills/direct/references/verification.md +247 -0
  21. package/src/core/coverage.ts +336 -0
  22. package/src/core/definition.ts +378 -0
  23. package/src/core/effects.ts +88 -0
  24. package/src/core/fixture.ts +185 -0
  25. package/src/core/ids.ts +77 -0
  26. package/src/core/index.ts +13 -0
  27. package/src/core/json-value.ts +7 -0
  28. package/src/core/json.ts +593 -0
  29. package/src/core/query.ts +230 -0
  30. package/src/core/reason.ts +16 -0
  31. package/src/core/resource.ts +10 -0
  32. package/src/core/result.ts +19 -0
  33. package/src/core/runtime.ts +229 -0
  34. package/src/core/scenario.ts +149 -0
  35. package/src/core/store.ts +784 -0
  36. package/src/index.ts +51 -0
  37. package/src/react.ts +54 -0
  38. package/src/testing/activity.ts +228 -0
  39. package/src/testing/coverage-binding.ts +99 -0
  40. package/src/testing/evidence.ts +59 -0
  41. package/src/testing/index.ts +22 -0
  42. package/src/testing/manifest.ts +559 -0
  43. package/src/testing/probe.ts +446 -0
  44. package/src/testing/scripted-transport.ts +775 -0
  45. package/src/testing/session.ts +525 -0
  46. package/src/tooling/bombadil-campaign.ts +288 -0
  47. package/src/tooling/bombadil-internal.d.ts +46 -0
  48. package/src/tooling/bombadil-runner.ts +1424 -0
  49. package/src/tooling/bombadil.ts +27 -0
  50. package/src/tooling/browser-verification-entry.ts +32 -0
  51. package/src/tooling/browser-verification.ts +916 -0
  52. package/src/tooling/bundle-boundary.ts +159 -0
  53. package/src/web/browser-bridge.ts +296 -0
  54. package/src/web/browser.ts +277 -0
  55. package/src/web/fetch-firewall.ts +251 -0
  56. package/src/web.ts +27 -0
@@ -0,0 +1,464 @@
1
+ import {
2
+ DEFAULT_JSON_LIMITS,
3
+ cloneJson,
4
+ err,
5
+ ok,
6
+ parseAndCloneWorld,
7
+ parseOperationId,
8
+ renderUnknownReason,
9
+ utf8ByteLength
10
+ } from "./index-1csg00w4.js";
11
+
12
+ // src/core/store.ts
13
+ var DIRECT_STORE_MAX_REPLACEMENTS = 32;
14
+ var DIRECT_STORE_MAX_REPLACEMENT_PATH_DEPTH = 32;
15
+ function storeError(code, message, operation = null) {
16
+ return { code, message, operation };
17
+ }
18
+ function replacementFailure(message) {
19
+ throw new TypeError(message);
20
+ }
21
+ function standardRecord(input) {
22
+ const prototype = Object.getPrototypeOf(input);
23
+ return prototype === Object.prototype || prototype === null;
24
+ }
25
+ function isJsonArray(input) {
26
+ return Array.isArray(input);
27
+ }
28
+ function ownEnumerableDataValue(input, key) {
29
+ const descriptor = Object.getOwnPropertyDescriptor(input, key);
30
+ if (descriptor === undefined || descriptor.enumerable !== true || !("value" in descriptor)) {
31
+ replacementFailure(`Replacement property ${JSON.stringify(key)} must be an own enumerable data property.`);
32
+ }
33
+ return descriptor.value;
34
+ }
35
+ function exactEnumerableKeys(input, expected, label) {
36
+ if (Object.getOwnPropertySymbols(input).length > 0) {
37
+ replacementFailure(`${label} cannot contain symbol properties.`);
38
+ }
39
+ const keys = Object.keys(input);
40
+ const ownKeys = Reflect.ownKeys(input);
41
+ if (keys.length !== expected.length || ownKeys.length !== expected.length || expected.some((key) => !Object.hasOwn(input, key))) {
42
+ replacementFailure(`${label} must contain exactly ${expected.join(", ")}.`);
43
+ }
44
+ for (const key of expected)
45
+ ownEnumerableDataValue(input, key);
46
+ }
47
+ function denseStandardArrayValues(input, label, maximumLength) {
48
+ if (!Array.isArray(input) || Object.getPrototypeOf(input) !== Array.prototype) {
49
+ replacementFailure(`${label} must be a standard array.`);
50
+ }
51
+ const lengthDescriptor = Object.getOwnPropertyDescriptor(input, "length");
52
+ if (lengthDescriptor === undefined || !("value" in lengthDescriptor)) {
53
+ replacementFailure(`${label} must have a data length from 0 through ${String(maximumLength)}.`);
54
+ }
55
+ const lengthValue = lengthDescriptor.value;
56
+ if (typeof lengthValue !== "number" || !Number.isSafeInteger(lengthValue) || lengthValue < 0 || lengthValue > maximumLength) {
57
+ replacementFailure(`${label} must have a data length from 0 through ${String(maximumLength)}.`);
58
+ }
59
+ const length = lengthValue;
60
+ const ownKeys = Reflect.ownKeys(input);
61
+ if (ownKeys.length !== length + 1 || ownKeys.at(-1) !== "length") {
62
+ replacementFailure(`${label} must be dense and cannot contain extra properties.`);
63
+ }
64
+ return Array.from({ length }, (_, index) => {
65
+ const key = String(index);
66
+ if (ownKeys[index] !== key) {
67
+ replacementFailure(`${label} must contain every index exactly once.`);
68
+ }
69
+ return ownEnumerableDataValue(input, key);
70
+ });
71
+ }
72
+ function consumeReplacementString(value, label, budget, budgetKey) {
73
+ budget[budgetKey] += utf8ByteLength(value);
74
+ if (budget[budgetKey] > DEFAULT_JSON_LIMITS.maxStringBytes) {
75
+ replacementFailure(`${label} exceeds the replacement string byte limit.`);
76
+ }
77
+ return value;
78
+ }
79
+ function replacementPrimitive(input, label, budget, budgetKey) {
80
+ if (input === null || typeof input === "boolean")
81
+ return input;
82
+ if (typeof input === "number") {
83
+ if (!Number.isFinite(input) || Object.is(input, -0)) {
84
+ replacementFailure(`${label} must be a finite normalized JSON number.`);
85
+ }
86
+ return input;
87
+ }
88
+ if (typeof input === "string") {
89
+ return consumeReplacementString(input, label, budget, budgetKey);
90
+ }
91
+ return replacementFailure(`${label} must be a JSON primitive.`);
92
+ }
93
+ function replacementPath(input, index, budget) {
94
+ const values = denseStandardArrayValues(input, `Replacement ${String(index)} path`, DIRECT_STORE_MAX_REPLACEMENT_PATH_DEPTH);
95
+ if (values.length === 0) {
96
+ replacementFailure(`Replacement ${String(index)} path must contain 1 through ${String(DIRECT_STORE_MAX_REPLACEMENT_PATH_DEPTH)} segments.`);
97
+ }
98
+ return Object.freeze(values.map((segment, segmentIndex) => {
99
+ if (typeof segment === "string") {
100
+ return consumeReplacementString(segment, `Replacement ${String(index)} path segment ${String(segmentIndex)}`, budget, "pathStringBytes");
101
+ }
102
+ if (typeof segment === "number" && Number.isSafeInteger(segment) && segment >= 0 && !Object.is(segment, -0)) {
103
+ return segment;
104
+ }
105
+ return replacementFailure(`Replacement ${String(index)} path segment ${String(segmentIndex)} must be a string or non-negative safe integer.`);
106
+ }));
107
+ }
108
+ function parsePrimitiveReplacements(input) {
109
+ const values = denseStandardArrayValues(input, "Replacements", DIRECT_STORE_MAX_REPLACEMENTS);
110
+ if (values.length === 0) {
111
+ replacementFailure(`A replacement transaction must contain 1 through ${String(DIRECT_STORE_MAX_REPLACEMENTS)} entries.`);
112
+ }
113
+ const budget = {
114
+ expectedStringBytes: 0,
115
+ pathStringBytes: 0,
116
+ valueStringBytes: 0
117
+ };
118
+ return Object.freeze(values.map((value, index) => {
119
+ if (typeof value !== "object" || value === null || Array.isArray(value) || !standardRecord(value)) {
120
+ replacementFailure(`Replacement ${String(index)} must be a standard or null-prototype object.`);
121
+ }
122
+ exactEnumerableKeys(value, ["expected", "path", "value"], `Replacement ${String(index)}`);
123
+ return Object.freeze({
124
+ expected: replacementPrimitive(ownEnumerableDataValue(value, "expected"), `Replacement ${String(index)} expected value`, budget, "expectedStringBytes"),
125
+ path: replacementPath(ownEnumerableDataValue(value, "path"), index, budget),
126
+ value: replacementPrimitive(ownEnumerableDataValue(value, "value"), `Replacement ${String(index)} value`, budget, "valueStringBytes")
127
+ });
128
+ }));
129
+ }
130
+ function replacementTrie(replacements) {
131
+ const root = { children: new Map, replacement: null };
132
+ for (const replacement of replacements) {
133
+ let node = root;
134
+ for (const segment of replacement.path) {
135
+ if (node.replacement !== null) {
136
+ replacementFailure("Replacement paths cannot overlap.");
137
+ }
138
+ let child = node.children.get(segment);
139
+ if (child === undefined) {
140
+ child = { children: new Map, replacement: null };
141
+ node.children.set(segment, child);
142
+ }
143
+ node = child;
144
+ }
145
+ if (node.replacement !== null) {
146
+ replacementFailure("Replacement paths cannot be duplicated.");
147
+ }
148
+ if (node.children.size > 0) {
149
+ replacementFailure("Replacement paths cannot overlap.");
150
+ }
151
+ node.replacement = replacement;
152
+ }
153
+ return root;
154
+ }
155
+ function samePrimitive(left, right) {
156
+ return left === right;
157
+ }
158
+ function primitiveShapeMatches(current, replacement) {
159
+ return current === null ? replacement === null : replacement !== null && typeof current === typeof replacement;
160
+ }
161
+ function replacedJsonValue(current, node, path) {
162
+ if (node.replacement !== null) {
163
+ if (current !== null && typeof current === "object") {
164
+ return replacementFailure(`${path} is a container, not a primitive leaf.`);
165
+ }
166
+ if (!samePrimitive(current, node.replacement.expected)) {
167
+ return replacementFailure(`${path} no longer matches its expected value.`);
168
+ }
169
+ if (!primitiveShapeMatches(current, node.replacement.value)) {
170
+ return replacementFailure(`${path} replacement would change the JSON shape.`);
171
+ }
172
+ return node.replacement.value;
173
+ }
174
+ if (current === null || typeof current !== "object") {
175
+ return replacementFailure(`${path} is a primitive and cannot contain a replacement path.`);
176
+ }
177
+ if (isJsonArray(current)) {
178
+ const next2 = [...current];
179
+ for (const [segment, child] of node.children) {
180
+ if (typeof segment !== "number" || !Number.isSafeInteger(segment) || segment < 0 || segment >= current.length) {
181
+ return replacementFailure(`${path} requires an existing numeric array index.`);
182
+ }
183
+ const currentValue = current[segment];
184
+ if (currentValue === undefined) {
185
+ return replacementFailure(`${path} requires an existing numeric array index.`);
186
+ }
187
+ next2[segment] = replacedJsonValue(currentValue, child, `${path}[${String(segment)}]`);
188
+ }
189
+ return Object.freeze(next2);
190
+ }
191
+ const prototype = Object.getPrototypeOf(current);
192
+ if (prototype !== Object.prototype && prototype !== null) {
193
+ return replacementFailure(`${path} is not a standard JSON object.`);
194
+ }
195
+ const record = current;
196
+ const next = prototype === null ? Object.create(null) : {};
197
+ for (const key of Object.keys(record)) {
198
+ const child = node.children.get(key);
199
+ const currentValue = record[key];
200
+ if (currentValue === undefined) {
201
+ return replacementFailure(`${path} requires an existing string-keyed property.`);
202
+ }
203
+ Object.defineProperty(next, key, {
204
+ configurable: true,
205
+ enumerable: true,
206
+ value: child === undefined ? currentValue : replacedJsonValue(currentValue, child, `${path}.${key}`),
207
+ writable: true
208
+ });
209
+ }
210
+ for (const segment of node.children.keys()) {
211
+ if (typeof segment !== "string" || !Object.hasOwn(record, segment)) {
212
+ return replacementFailure(`${path} requires an existing string-keyed property.`);
213
+ }
214
+ }
215
+ return Object.freeze(next);
216
+ }
217
+ function applyPrimitiveReplacements(world, replacements) {
218
+ const trie = replacementTrie(replacements);
219
+ const stringByteDelta = replacements.reduce((delta, replacement) => delta + (typeof replacement.value === "string" ? utf8ByteLength(replacement.value) : 0) - (typeof replacement.expected === "string" ? utf8ByteLength(replacement.expected) : 0), 0);
220
+ if (stringByteDelta > 0) {
221
+ replacementFailure("Primitive replacements cannot increase aggregate raw UTF-8 string bytes.");
222
+ }
223
+ return replacedJsonValue(world, trie, "$");
224
+ }
225
+ function generation(value) {
226
+ return value;
227
+ }
228
+ function activity(active, started, settled) {
229
+ return Object.freeze({ active, started, settled });
230
+ }
231
+ function storeSnapshot(currentGeneration, revision, world, currentActivity) {
232
+ return Object.freeze({ generation: currentGeneration, revision, world, activity: currentActivity });
233
+ }
234
+ function isPromiseLike(value) {
235
+ return (typeof value === "object" && value !== null || typeof value === "function") && typeof Reflect.get(value, "then") === "function";
236
+ }
237
+ function createDirectStore(initialWorld, parseWorld, options = {}) {
238
+ const initial = parseAndCloneWorld(initialWorld, parseWorld);
239
+ if (!initial.ok) {
240
+ return err(storeError("invalid-world", initial.error.message));
241
+ }
242
+ let currentGeneration = generation(1);
243
+ let revision = 0;
244
+ let currentActivity = activity(0, 0, 0);
245
+ let snapshot = storeSnapshot(currentGeneration, revision, initial.value, currentActivity);
246
+ const listeners = new Set;
247
+ const activeOperations = new Set;
248
+ let onListenerError;
249
+ let validateReplacements;
250
+ try {
251
+ onListenerError = options.onListenerError;
252
+ validateReplacements = options.validateReplacements;
253
+ } catch (reason) {
254
+ return err(storeError("invalid-world", renderUnknownReason(reason, "Direct store options could not be inspected")));
255
+ }
256
+ if (onListenerError !== undefined && typeof onListenerError !== "function") {
257
+ return err(storeError("invalid-world", "Direct listener error reporting must be callable."));
258
+ }
259
+ if (validateReplacements !== undefined && typeof validateReplacements !== "function") {
260
+ return err(storeError("invalid-world", "Direct replacement validation must be callable."));
261
+ }
262
+ const reportListenerError = (reason) => {
263
+ if (onListenerError === undefined)
264
+ return;
265
+ try {
266
+ const returned = onListenerError(reason);
267
+ if (isPromiseLike(returned)) {
268
+ Promise.resolve(returned).catch(() => {
269
+ return;
270
+ });
271
+ }
272
+ } catch {}
273
+ };
274
+ const publish = (world = snapshot.world) => {
275
+ revision += 1;
276
+ const committed = storeSnapshot(currentGeneration, revision, world, currentActivity);
277
+ snapshot = committed;
278
+ for (const listener of [...listeners]) {
279
+ try {
280
+ const returned = listener();
281
+ if (isPromiseLike(returned)) {
282
+ Promise.resolve(returned).catch(reportListenerError);
283
+ }
284
+ } catch (reason) {
285
+ reportListenerError(reason);
286
+ }
287
+ }
288
+ return committed;
289
+ };
290
+ const stale = (expected, operation = null) => expected === currentGeneration ? null : storeError("stale-generation", `Generation ${String(expected)} is stale; current generation is ${String(currentGeneration)}`, operation);
291
+ const validateOperation = (candidate) => {
292
+ const parsed = parseOperationId(candidate);
293
+ return parsed.ok ? ok(parsed.value) : err(storeError("invalid-operation", parsed.error.message));
294
+ };
295
+ const settleActivity = (expected, candidate) => {
296
+ const operation = validateOperation(candidate);
297
+ if (!operation.ok) {
298
+ return operation;
299
+ }
300
+ const staleError = stale(expected, operation.value);
301
+ if (staleError !== null) {
302
+ return err(staleError);
303
+ }
304
+ if (!activeOperations.delete(operation.value)) {
305
+ return err(storeError("activity-not-found", `Activity is not active: ${operation.value}`, operation.value));
306
+ }
307
+ currentActivity = activity(currentActivity.active - 1, currentActivity.started, currentActivity.settled + 1);
308
+ return ok(publish());
309
+ };
310
+ const store = {
311
+ getSnapshot: () => snapshot,
312
+ subscribe: (listener) => {
313
+ listeners.add(listener);
314
+ return () => {
315
+ listeners.delete(listener);
316
+ };
317
+ },
318
+ transact: (expected, candidate, update) => {
319
+ const operation = validateOperation(candidate);
320
+ if (!operation.ok) {
321
+ return operation;
322
+ }
323
+ const staleError = stale(expected, operation.value);
324
+ if (staleError !== null) {
325
+ return err(staleError);
326
+ }
327
+ const baseSnapshot = snapshot;
328
+ const cloned = cloneJson(snapshot.world);
329
+ if (!cloned.ok) {
330
+ return err(storeError("invalid-world", cloned.error.message, operation.value));
331
+ }
332
+ let candidateWorld;
333
+ try {
334
+ const draft = cloned.value;
335
+ const returned = update(draft);
336
+ candidateWorld = returned === undefined ? draft : returned;
337
+ } catch (reason) {
338
+ return err(storeError("transaction-failed", renderUnknownReason(reason), operation.value));
339
+ }
340
+ const validated = parseAndCloneWorld(candidateWorld, parseWorld);
341
+ if (!validated.ok) {
342
+ return err(storeError("invalid-world", validated.error.message, operation.value));
343
+ }
344
+ const nextStaleError = stale(expected, operation.value);
345
+ if (nextStaleError !== null) {
346
+ return err(nextStaleError);
347
+ }
348
+ if (snapshot !== baseSnapshot) {
349
+ return err(storeError("transaction-conflict", `Store revision changed during transaction ${operation.value}`, operation.value));
350
+ }
351
+ return ok(publish(validated.value));
352
+ },
353
+ transactReplacements: (expected, candidate, input) => {
354
+ const operation = validateOperation(candidate);
355
+ if (!operation.ok) {
356
+ return operation;
357
+ }
358
+ const staleError = stale(expected, operation.value);
359
+ if (staleError !== null) {
360
+ return err(staleError);
361
+ }
362
+ if (validateReplacements === undefined) {
363
+ return err(storeError("invalid-world", "This Direct store does not define a primitive replacement validator.", operation.value));
364
+ }
365
+ const baseSnapshot = snapshot;
366
+ let replacements;
367
+ let candidateWorld;
368
+ try {
369
+ replacements = parsePrimitiveReplacements(input);
370
+ candidateWorld = applyPrimitiveReplacements(baseSnapshot.world, replacements);
371
+ const returned = validateReplacements(Object.freeze({
372
+ baseWorld: baseSnapshot.world,
373
+ candidateWorld,
374
+ generation: expected,
375
+ operation: operation.value,
376
+ replacements
377
+ }));
378
+ if (returned !== undefined) {
379
+ if (isPromiseLike(returned)) {
380
+ Promise.resolve(returned).catch(() => {
381
+ return;
382
+ });
383
+ }
384
+ throw new TypeError("Direct replacement validation must complete synchronously and return undefined.");
385
+ }
386
+ } catch (reason) {
387
+ return err(storeError("invalid-world", renderUnknownReason(reason, "Direct primitive replacements are invalid"), operation.value));
388
+ }
389
+ const nextStaleError = stale(expected, operation.value);
390
+ if (nextStaleError !== null) {
391
+ return err(nextStaleError);
392
+ }
393
+ if (snapshot !== baseSnapshot) {
394
+ return err(storeError("transaction-conflict", `Store revision changed during transaction ${operation.value}`, operation.value));
395
+ }
396
+ return ok(publish(candidateWorld));
397
+ },
398
+ reset: (world) => {
399
+ const validated = parseAndCloneWorld(world, parseWorld);
400
+ if (!validated.ok) {
401
+ return err(storeError("invalid-world", validated.error.message));
402
+ }
403
+ const nextGeneration = Number(currentGeneration) + 1;
404
+ if (!Number.isSafeInteger(nextGeneration)) {
405
+ return err(storeError("generation-overflow", "Store generation exceeds the safe integer range"));
406
+ }
407
+ currentGeneration = generation(nextGeneration);
408
+ activeOperations.clear();
409
+ currentActivity = activity(0, 0, 0);
410
+ return ok(publish(validated.value));
411
+ },
412
+ beginActivity: (expected, candidate) => {
413
+ const operation = validateOperation(candidate);
414
+ if (!operation.ok) {
415
+ return operation;
416
+ }
417
+ const staleError = stale(expected, operation.value);
418
+ if (staleError !== null) {
419
+ return err(staleError);
420
+ }
421
+ if (activeOperations.has(operation.value)) {
422
+ return err(storeError("duplicate-activity", `Activity is already active: ${operation.value}`, operation.value));
423
+ }
424
+ activeOperations.add(operation.value);
425
+ currentActivity = activity(currentActivity.active + 1, currentActivity.started + 1, currentActivity.settled);
426
+ publish();
427
+ const lease = Object.freeze({
428
+ generation: expected,
429
+ operation: operation.value,
430
+ settle: () => settleActivity(expected, operation.value)
431
+ });
432
+ return ok(lease);
433
+ },
434
+ settleActivity,
435
+ isQuiescent: (expected) => {
436
+ const staleError = stale(expected);
437
+ return staleError === null ? ok(currentActivity.active === 0) : err(staleError);
438
+ },
439
+ whenQuiescent: (expected) => {
440
+ const staleError = stale(expected);
441
+ if (staleError !== null) {
442
+ return Promise.resolve(err(staleError));
443
+ }
444
+ if (currentActivity.active === 0) {
445
+ return Promise.resolve(ok(snapshot));
446
+ }
447
+ return new Promise((resolve) => {
448
+ const unsubscribe = store.subscribe(() => {
449
+ const nextStaleError = stale(expected);
450
+ if (nextStaleError !== null) {
451
+ unsubscribe();
452
+ resolve(err(nextStaleError));
453
+ } else if (currentActivity.active === 0) {
454
+ unsubscribe();
455
+ resolve(ok(snapshot));
456
+ }
457
+ });
458
+ });
459
+ }
460
+ };
461
+ return ok(Object.freeze(store));
462
+ }
463
+
464
+ export { DIRECT_STORE_MAX_REPLACEMENTS, DIRECT_STORE_MAX_REPLACEMENT_PATH_DEPTH, createDirectStore };