@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
package/dist/index.js ADDED
@@ -0,0 +1,232 @@
1
+ import {
2
+ DEFAULT_MAX_FIXTURE_BYTES,
3
+ DEFAULT_MAX_QUERY_BYTES,
4
+ DIRECT_COVERAGE_SCHEMA,
5
+ activateDirectScenario,
6
+ createCoverageCatalog,
7
+ createFixtureEnvelope,
8
+ createScenarioCatalog,
9
+ err,
10
+ isRecord,
11
+ maximumFixtureQueryBytes,
12
+ ok,
13
+ parseCoverageCatalogSnapshot,
14
+ parseDirectQuery,
15
+ parseFixtureEnvelope,
16
+ parseFixtureJson,
17
+ parseJsonValue,
18
+ parseLogicalRuntimeSnapshot,
19
+ renderUnknownReason,
20
+ serializeFixtureJson
21
+ } from "./index-1csg00w4.js";
22
+
23
+ // src/core/definition.ts
24
+ function definitionError(code, message, causes = {}) {
25
+ if (code === "invalid-scenarios" || code === "invalid-default-scenario") {
26
+ const scenarioError = causes.scenarioError;
27
+ if (scenarioError === undefined)
28
+ throw new Error(`${code} requires a scenario error`);
29
+ return Object.freeze({ code, message, scenarioError, coverageError: null });
30
+ }
31
+ if (code === "invalid-coverage") {
32
+ const coverageError = causes.coverageError;
33
+ if (coverageError === undefined)
34
+ throw new Error("invalid-coverage requires a coverage error");
35
+ return Object.freeze({ code, message, scenarioError: null, coverageError });
36
+ }
37
+ return Object.freeze({ code, message, scenarioError: null, coverageError: null });
38
+ }
39
+ function validPositiveLimit(value) {
40
+ return Number.isSafeInteger(value) && value >= 1;
41
+ }
42
+ function activeFromParsed(parsed) {
43
+ if (!parsed.ok)
44
+ return parsed;
45
+ if (parsed.value.kind === "active")
46
+ return ok(parsed.value);
47
+ return err({ code: "invalid-scenario", message: "Direct activation did not select a scenario" });
48
+ }
49
+ function tryDefineDirectUnchecked(input) {
50
+ const parseWorld = input.parseWorld;
51
+ const defaultScenarioInput = input.defaultScenario;
52
+ const scenarioInputs = input.scenarios;
53
+ const coverageInputs = input.coverage;
54
+ const maxFixtureBytes = input.maxFixtureBytes ?? DEFAULT_MAX_FIXTURE_BYTES;
55
+ const maxQueryBytes = input.maxQueryBytes ?? DEFAULT_MAX_QUERY_BYTES;
56
+ if (!validPositiveLimit(maxFixtureBytes) || !validPositiveLimit(maxQueryBytes)) {
57
+ return err(definitionError("invalid-limits", "Direct query and fixture limits must be positive safe integers"));
58
+ }
59
+ const requiredQueryBytes = maximumFixtureQueryBytes(maxFixtureBytes);
60
+ if (!Number.isSafeInteger(requiredQueryBytes) || maxQueryBytes < requiredQueryBytes) {
61
+ return err(definitionError("invalid-limits", `Direct maxQueryBytes must be at least ${String(requiredQueryBytes)} to carry every bounded fixture`));
62
+ }
63
+ const scenarios = createScenarioCatalog(scenarioInputs, parseWorld);
64
+ if (!scenarios.ok) {
65
+ return err(definitionError("invalid-scenarios", scenarios.error.message, {
66
+ scenarioError: scenarios.error
67
+ }));
68
+ }
69
+ const defaultScenario = scenarios.value.resolve(defaultScenarioInput);
70
+ if (!defaultScenario.ok) {
71
+ return err(definitionError("invalid-default-scenario", defaultScenario.error.message, {
72
+ scenarioError: defaultScenario.error
73
+ }));
74
+ }
75
+ const coverage = createCoverageCatalog(coverageInputs, scenarios.value);
76
+ if (!coverage.ok) {
77
+ return err(definitionError("invalid-coverage", coverage.error.message, {
78
+ coverageError: coverage.error
79
+ }));
80
+ }
81
+ const limits = Object.freeze({ maxFixtureBytes, maxQueryBytes });
82
+ const fixtureOptions = Object.freeze({
83
+ scenarios: scenarios.value,
84
+ parseWorld,
85
+ maxBytes: maxFixtureBytes
86
+ });
87
+ const queryOptions = Object.freeze({
88
+ ...fixtureOptions,
89
+ maxQueryBytes
90
+ });
91
+ const activateScenario = (scenario) => activateDirectScenario(scenario, scenarios.value);
92
+ const activate = (source) => {
93
+ const parsed = parseDirectQuery(source, queryOptions);
94
+ if (!parsed.ok || parsed.value.kind === "active")
95
+ return activeFromParsed(parsed);
96
+ return activateScenario(defaultScenario.value.id);
97
+ };
98
+ return ok(Object.freeze({
99
+ defaultScenario: defaultScenario.value,
100
+ scenarios: scenarios.value,
101
+ coverage: coverage.value,
102
+ parseWorld,
103
+ limits,
104
+ activate,
105
+ activateScenario,
106
+ parseFixture: (fixture) => parseFixtureEnvelope(fixture, fixtureOptions),
107
+ parseFixtureJson: (source) => parseFixtureJson(source, fixtureOptions),
108
+ createFixture: (fixture) => createFixtureEnvelope(fixture, fixtureOptions),
109
+ serializeFixture: (fixture) => serializeFixtureJson(fixture, fixtureOptions)
110
+ }));
111
+ }
112
+ function tryDefineDirect(input) {
113
+ try {
114
+ return tryDefineDirectUnchecked(input);
115
+ } catch (reason) {
116
+ return err(definitionError("invalid-options", renderUnknownReason(reason, "Direct definition options could not be inspected")));
117
+ }
118
+ }
119
+ var DEFINITION_INPUT_KEYS = new Set([
120
+ "coverage",
121
+ "defaultScenario",
122
+ "maxFixtureBytes",
123
+ "maxQueryBytes",
124
+ "parseWorld",
125
+ "scenarios"
126
+ ]);
127
+ var SCENARIO_INPUT_KEYS = new Set([
128
+ "description",
129
+ "id",
130
+ "route",
131
+ "runtime",
132
+ "title",
133
+ "world"
134
+ ]);
135
+ function parseDirectDefinition(input) {
136
+ try {
137
+ if (!isRecord(input))
138
+ throw new Error("Direct definition must be an object");
139
+ for (const key of Object.keys(input)) {
140
+ if (!DEFINITION_INPUT_KEYS.has(key))
141
+ throw new Error(`Unknown Direct definition key: ${key}`);
142
+ }
143
+ const rawParser = input.parseWorld;
144
+ if (typeof rawParser !== "function")
145
+ throw new Error("Direct parseWorld must be a function");
146
+ const parseWorld = (candidate) => {
147
+ const parsedCandidate = Reflect.apply(rawParser, undefined, [candidate]);
148
+ const parsedJson = parseJsonValue(parsedCandidate);
149
+ if (!parsedJson.ok)
150
+ throw new Error(parsedJson.error.message);
151
+ return parsedJson.value;
152
+ };
153
+ if (typeof input.defaultScenario !== "string") {
154
+ throw new Error("Direct defaultScenario must be a string");
155
+ }
156
+ if (!Array.isArray(input.scenarios))
157
+ throw new Error("Direct scenarios must be an array");
158
+ const scenarios = [];
159
+ for (const [index, candidate] of input.scenarios.entries()) {
160
+ if (!isRecord(candidate))
161
+ throw new Error(`Direct scenario ${String(index)} must be an object`);
162
+ for (const key of Object.keys(candidate)) {
163
+ if (!SCENARIO_INPUT_KEYS.has(key)) {
164
+ throw new Error(`Unknown Direct scenario key at ${String(index)}: ${key}`);
165
+ }
166
+ }
167
+ if (typeof candidate.id !== "string" || typeof candidate.title !== "string" || typeof candidate.route !== "string" || candidate.description !== undefined && typeof candidate.description !== "string") {
168
+ throw new Error(`Direct scenario ${String(index)} has an invalid shape`);
169
+ }
170
+ const world = parseJsonValue(candidate.world);
171
+ if (!world.ok)
172
+ throw new Error(`Direct scenario ${String(index)} world is invalid: ${world.error.message}`);
173
+ const runtime = candidate.runtime === undefined ? undefined : parseLogicalRuntimeSnapshot(candidate.runtime);
174
+ if (runtime !== undefined && !runtime.ok) {
175
+ throw new Error(`Direct scenario ${String(index)} runtime is invalid: ${runtime.error.message}`);
176
+ }
177
+ scenarios.push({
178
+ id: candidate.id,
179
+ title: candidate.title,
180
+ ...candidate.description === undefined ? {} : { description: candidate.description },
181
+ route: candidate.route,
182
+ world: world.value,
183
+ ...runtime === undefined ? {} : { runtime: runtime.value }
184
+ });
185
+ }
186
+ const coverage = parseCoverageCatalogSnapshot({
187
+ schema: DIRECT_COVERAGE_SCHEMA,
188
+ entries: input.coverage
189
+ });
190
+ if (!coverage.ok) {
191
+ return err(definitionError("invalid-coverage", coverage.error.message, {
192
+ coverageError: coverage.error
193
+ }));
194
+ }
195
+ const maxFixtureBytes = input.maxFixtureBytes;
196
+ const maxQueryBytes = input.maxQueryBytes;
197
+ if (maxFixtureBytes !== undefined && typeof maxFixtureBytes !== "number") {
198
+ throw new Error("Direct maxFixtureBytes must be a number");
199
+ }
200
+ if (maxQueryBytes !== undefined && typeof maxQueryBytes !== "number") {
201
+ throw new Error("Direct maxQueryBytes must be a number");
202
+ }
203
+ return tryDefineDirectUnchecked({
204
+ parseWorld,
205
+ defaultScenario: input.defaultScenario,
206
+ scenarios,
207
+ coverage: coverage.value.entries,
208
+ ...maxFixtureBytes === undefined ? {} : { maxFixtureBytes },
209
+ ...maxQueryBytes === undefined ? {} : { maxQueryBytes }
210
+ });
211
+ } catch (reason) {
212
+ return err(definitionError("invalid-options", renderUnknownReason(reason, "Direct definition options could not be inspected")));
213
+ }
214
+ }
215
+ function defineDirect(input) {
216
+ const defined = tryDefineDirect(input);
217
+ if (!defined.ok) {
218
+ throw new Error(defined.error.message, { cause: defined.error });
219
+ }
220
+ return defined.value;
221
+ }
222
+
223
+ // src/index.ts
224
+ var FIXTURE_QUERY_KEY = "__direct_fixture";
225
+ var SCENARIO_QUERY_KEY = "__direct_scenario";
226
+ export {
227
+ tryDefineDirect,
228
+ parseDirectDefinition,
229
+ defineDirect,
230
+ SCENARIO_QUERY_KEY,
231
+ FIXTURE_QUERY_KEY
232
+ };
package/dist/react.js ADDED
@@ -0,0 +1,32 @@
1
+ // src/react.ts
2
+ import {
3
+ createContext,
4
+ createElement,
5
+ useContext,
6
+ useSyncExternalStore
7
+ } from "react";
8
+ function createDirectReactBindings() {
9
+ const StoreContext = createContext(null);
10
+ const useStore = () => {
11
+ const store = useContext(StoreContext);
12
+ if (store === null) {
13
+ throw new Error("Direct hooks require their matching Direct Provider");
14
+ }
15
+ return store;
16
+ };
17
+ const useSnapshot = () => {
18
+ const store = useStore();
19
+ return useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
20
+ };
21
+ const bindings = {
22
+ Context: StoreContext,
23
+ Provider: ({ store, children }) => createElement(StoreContext.Provider, { value: store }, children),
24
+ useStore,
25
+ useSnapshot,
26
+ useWorld: () => useSnapshot().world
27
+ };
28
+ return Object.freeze(bindings);
29
+ }
30
+ export {
31
+ createDirectReactBindings
32
+ };