@workglow/test-contract 0.6.1

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 (149) hide show
  1. package/README.md +232 -0
  2. package/dist/ai-provider/assertions/capabilityHonesty.d.ts +7 -0
  3. package/dist/ai-provider/assertions/dispose.d.ts +7 -0
  4. package/dist/ai-provider/assertions/inferAdvertisesRegistered.d.ts +15 -0
  5. package/dist/ai-provider/assertions/inferServesInferred.d.ts +20 -0
  6. package/dist/ai-provider/assertions/pricingMatchesModality.d.ts +36 -0
  7. package/dist/ai-provider/assertions/registryCoverage.d.ts +13 -0
  8. package/dist/ai-provider/assertions/sessionReuse.d.ts +7 -0
  9. package/dist/ai-provider/assertions/signalHonoring.d.ts +7 -0
  10. package/dist/ai-provider/assertions/structuredGeneration.d.ts +7 -0
  11. package/dist/ai-provider/assertions/textGenerationSmoke.d.ts +7 -0
  12. package/dist/ai-provider/assertions/toolCallAccumulator.d.ts +7 -0
  13. package/dist/ai-provider/assertions/toolCallMultiTurn.d.ts +7 -0
  14. package/dist/ai-provider/assertions/usageNormalization.d.ts +61 -0
  15. package/dist/ai-provider/fixtures.d.ts +8 -0
  16. package/dist/ai-provider/runAiProviderConformance.d.ts +7 -0
  17. package/dist/ai-provider/types.d.ts +75 -0
  18. package/dist/ai-provider.d.ts +25 -0
  19. package/dist/ai-provider.js +876 -0
  20. package/dist/ai-provider.js.map +26 -0
  21. package/dist/browser-context/ConformanceMockContext.d.ts +54 -0
  22. package/dist/browser-context/assertions/ariaRoundTrip.d.ts +7 -0
  23. package/dist/browser-context/assertions/capabilityHonesty.d.ts +7 -0
  24. package/dist/browser-context/assertions/itExpectFail.d.ts +8 -0
  25. package/dist/browser-context/assertions/networkIntrospection.d.ts +7 -0
  26. package/dist/browser-context/assertions/tabsLifecycle.d.ts +7 -0
  27. package/dist/browser-context/fixtures.d.ts +8 -0
  28. package/dist/browser-context/runIBrowserContextConformance.d.ts +7 -0
  29. package/dist/browser-context/types.d.ts +48 -0
  30. package/dist/browser-context.d.ts +18 -0
  31. package/dist/browser-context.js +567 -0
  32. package/dist/browser-context.js.map +17 -0
  33. package/dist/creditExhaustedSkip.d.ts +39 -0
  34. package/dist/creditExhaustedSkip.js +163 -0
  35. package/dist/creditExhaustedSkip.js.map +10 -0
  36. package/dist/entitlement-profile/assertions/denialShape.d.ts +13 -0
  37. package/dist/entitlement-profile/assertions/dispose.d.ts +16 -0
  38. package/dist/entitlement-profile/assertions/hierarchyHonoring.d.ts +11 -0
  39. package/dist/entitlement-profile/assertions/optionalNeverDenied.d.ts +11 -0
  40. package/dist/entitlement-profile/assertions/requestEntitlementShape.d.ts +12 -0
  41. package/dist/entitlement-profile/assertions/resourceScoping.d.ts +16 -0
  42. package/dist/entitlement-profile/assertions/subscribeGrant.d.ts +11 -0
  43. package/dist/entitlement-profile/assertions/subscribeReload.d.ts +11 -0
  44. package/dist/entitlement-profile/assertions/subscribeRevocation.d.ts +12 -0
  45. package/dist/entitlement-profile/assertions/surfaceCoverage.d.ts +7 -0
  46. package/dist/entitlement-profile/assertions/unsubscribeIdempotent.d.ts +7 -0
  47. package/dist/entitlement-profile/fixtures.d.ts +21 -0
  48. package/dist/entitlement-profile/runEntitlementProfileConformance.d.ts +7 -0
  49. package/dist/entitlement-profile/types.d.ts +45 -0
  50. package/dist/entitlement-profile.d.ts +23 -0
  51. package/dist/entitlement-profile.js +436 -0
  52. package/dist/entitlement-profile.js.map +22 -0
  53. package/dist/human-connector/MockHumanConnector.d.ts +29 -0
  54. package/dist/human-connector/assertions/abort.d.ts +7 -0
  55. package/dist/human-connector/assertions/capabilityHonesty.d.ts +7 -0
  56. package/dist/human-connector/assertions/concurrentIsolation.d.ts +7 -0
  57. package/dist/human-connector/assertions/multiTurnFollowUp.d.ts +7 -0
  58. package/dist/human-connector/assertions/notifyDisplayFastResolve.d.ts +7 -0
  59. package/dist/human-connector/assertions/roundtrip.d.ts +7 -0
  60. package/dist/human-connector/fixtures.d.ts +8 -0
  61. package/dist/human-connector/runHumanConnectorConformance.d.ts +9 -0
  62. package/dist/human-connector/types.d.ts +91 -0
  63. package/dist/human-connector.d.ts +19 -0
  64. package/dist/human-connector.js +843 -0
  65. package/dist/human-connector.js.map +20 -0
  66. package/dist/itExpectFail.d.ts +15 -0
  67. package/dist/itExpectFail.js +180 -0
  68. package/dist/itExpectFail.js.map +11 -0
  69. package/dist/storage-migrations/assertions/appliesAndRecords.d.ts +7 -0
  70. package/dist/storage-migrations/assertions/concurrentRunsSerialize.d.ts +18 -0
  71. package/dist/storage-migrations/assertions/ensureBookkeepingIdempotent.d.ts +7 -0
  72. package/dist/storage-migrations/assertions/failedMigrationLeavesNoPartialSchema.d.ts +14 -0
  73. package/dist/storage-migrations/assertions/failedMigrationNotRecorded.d.ts +7 -0
  74. package/dist/storage-migrations/assertions/idempotentRun.d.ts +7 -0
  75. package/dist/storage-migrations/assertions/incrementalApplication.d.ts +7 -0
  76. package/dist/storage-migrations/runMigrationRunnerContract.d.ts +9 -0
  77. package/dist/storage-migrations/types.d.ts +78 -0
  78. package/dist/storage-migrations.d.ts +18 -0
  79. package/dist/storage-migrations.js +473 -0
  80. package/dist/storage-migrations.js.map +20 -0
  81. package/dist/tabular-migrations/assertions/addAndDropIndex.d.ts +7 -0
  82. package/dist/tabular-migrations/assertions/addColumn.d.ts +7 -0
  83. package/dist/tabular-migrations/assertions/backfill.d.ts +7 -0
  84. package/dist/tabular-migrations/assertions/dropColumn.d.ts +7 -0
  85. package/dist/tabular-migrations/assertions/failedMigrationNotRecorded.d.ts +7 -0
  86. package/dist/tabular-migrations/assertions/freshDbFastPath.d.ts +7 -0
  87. package/dist/tabular-migrations/assertions/incrementalApplication.d.ts +7 -0
  88. package/dist/tabular-migrations/assertions/renameColumn.d.ts +7 -0
  89. package/dist/tabular-migrations/runTabularMigrationContract.d.ts +8 -0
  90. package/dist/tabular-migrations/types.d.ts +28 -0
  91. package/dist/tabular-migrations.d.ts +19 -0
  92. package/dist/tabular-migrations.js +257 -0
  93. package/dist/tabular-migrations.js.map +18 -0
  94. package/dist/tabular-storage/assertions/countMatchesQuery.d.ts +7 -0
  95. package/dist/tabular-storage/assertions/guardParity.d.ts +25 -0
  96. package/dist/tabular-storage/assertions/inListCriterion.d.ts +14 -0
  97. package/dist/tabular-storage/assertions/joinBoundedLeftRead.d.ts +29 -0
  98. package/dist/tabular-storage/assertions/joinPushdown.d.ts +13 -0
  99. package/dist/tabular-storage/assertions/notInListCriterion.d.ts +15 -0
  100. package/dist/tabular-storage/assertions/strategyParity.d.ts +31 -0
  101. package/dist/tabular-storage/assertions/subscribeToChanges.d.ts +21 -0
  102. package/dist/tabular-storage/assertions/vectorColumnFormat.d.ts +7 -0
  103. package/dist/tabular-storage/assertions/withConnectionTransaction.d.ts +7 -0
  104. package/dist/tabular-storage/assertions/withTransactionRollback.d.ts +7 -0
  105. package/dist/tabular-storage/fixtures.d.ts +33 -0
  106. package/dist/tabular-storage/joinFixtures.d.ts +66 -0
  107. package/dist/tabular-storage/runTabularJoinContract.d.ts +24 -0
  108. package/dist/tabular-storage/runTabularStorageContract.d.ts +9 -0
  109. package/dist/tabular-storage/types.d.ts +102 -0
  110. package/dist/tabular-storage.d.ts +25 -0
  111. package/dist/tabular-storage.js +1477 -0
  112. package/dist/tabular-storage.js.map +27 -0
  113. package/dist/vector-storage/assertions/dimensionValidation.d.ts +17 -0
  114. package/dist/vector-storage/assertions/legacyEncoding.d.ts +16 -0
  115. package/dist/vector-storage/assertions/metadataFilter.d.ts +16 -0
  116. package/dist/vector-storage/assertions/searchOptions.d.ts +16 -0
  117. package/dist/vector-storage/assertions/shared.d.ts +23 -0
  118. package/dist/vector-storage/assertions/similarityRanking.d.ts +18 -0
  119. package/dist/vector-storage/assertions/similaritySearchEvent.d.ts +16 -0
  120. package/dist/vector-storage/assertions/vectorRoundTrip.d.ts +17 -0
  121. package/dist/vector-storage/runVectorStorageContract.d.ts +20 -0
  122. package/dist/vector-storage/types.d.ts +87 -0
  123. package/dist/vector-storage.d.ts +19 -0
  124. package/dist/vector-storage.js +412 -0
  125. package/dist/vector-storage.js.map +21 -0
  126. package/dist/web-search/assertions/capabilityAgreement.d.ts +23 -0
  127. package/dist/web-search/assertions/credentialNaming.d.ts +21 -0
  128. package/dist/web-search/assertions/dateFiltering.d.ts +22 -0
  129. package/dist/web-search/assertions/domainNormalization.d.ts +24 -0
  130. package/dist/web-search/assertions/maxResultsCeiling.d.ts +22 -0
  131. package/dist/web-search/assertions/reportedQuery.d.ts +18 -0
  132. package/dist/web-search/assertions/signalThreading.d.ts +20 -0
  133. package/dist/web-search/fixtures.d.ts +40 -0
  134. package/dist/web-search/runWebSearchProviderConformance.d.ts +24 -0
  135. package/dist/web-search/types.d.ts +79 -0
  136. package/dist/web-search.d.ts +19 -0
  137. package/dist/web-search.js +560 -0
  138. package/dist/web-search.js.map +18 -0
  139. package/dist/worker-proxy/assertions/backlogOrdering.d.ts +7 -0
  140. package/dist/worker-proxy/assertions/disposeTerminatesWorker.d.ts +8 -0
  141. package/dist/worker-proxy/assertions/errorPropagation.d.ts +7 -0
  142. package/dist/worker-proxy/assertions/providerCallHelpers.d.ts +23 -0
  143. package/dist/worker-proxy/browserOnlyStub.d.ts +7 -0
  144. package/dist/worker-proxy/runWorkerProxyBoundary.d.ts +7 -0
  145. package/dist/worker-proxy/types.d.ts +47 -0
  146. package/dist/worker-proxy.d.ts +16 -0
  147. package/dist/worker-proxy.js +389 -0
  148. package/dist/worker-proxy.js.map +17 -0
  149. package/package.json +120 -0
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { WebSearchProviderConformanceOpts } from "../types";
7
+ /**
8
+ * A credential is named for a provider, never for the request.
9
+ *
10
+ * `credential_keys` maps provider name to credential-store key, and the key
11
+ * sent is the one named for the provider that RAN — so a key issued for one
12
+ * vendor cannot leave with a request to another. That is not a tidiness rule:
13
+ * a search API key is a bearer credential against a metered account, and one
14
+ * forwarded to the wrong vendor has been disclosed to them.
15
+ *
16
+ * The bare `credential_key` port survives for a pinned provider, where the
17
+ * vendor is unambiguous, and is refused under `"auto"` for the same reason:
18
+ * routing picks the vendor at run time, so an unnamed key goes wherever it
19
+ * lands.
20
+ */
21
+ export declare function credentialNamingBlock(opts: WebSearchProviderConformanceOpts): void;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { WebSearchProviderConformanceOpts } from "../types";
7
+ /**
8
+ * Date filtering is never emulated, and never half-sent.
9
+ *
10
+ * Post-filtering by `publishedDate` breaks `maxResults` and drops every result
11
+ * whose date the provider omitted, so a provider that cannot filter server-side
12
+ * declares `dateFilter: false` and such a request is refused rather than
13
+ * approximated. That is the half most people expect.
14
+ *
15
+ * The other half is what a provider declaring `true` then owes: something for
16
+ * EVERY range this task accepts. The real APIs take closed intervals — Brave's
17
+ * `freshness`, Gemini's `timeRangeFilter` — so a half-open range has to be
18
+ * filled at the open end. Dropping it instead reports a bound as honored on a
19
+ * search that ran unfiltered, which is the failure the refusal above exists to
20
+ * avoid, arrived at by a different road.
21
+ */
22
+ export declare function dateFilteringBlock(opts: WebSearchProviderConformanceOpts): void;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { WebSearchProviderConformanceOpts } from "../types";
7
+ /**
8
+ * A domain entry means the same thing whichever route carries it.
9
+ *
10
+ * There are two routes — a native domain list, and a `site:` clause spliced
11
+ * into the query — and the same entry has to reduce identically on both. It did
12
+ * not once: reducing only on the way into an operator left `"https://arxiv.org/"`
13
+ * restricting one route and reaching a vendor API scheme-first on the other,
14
+ * where it matches nothing. Under `"auto"` the caller cannot even tell which
15
+ * route ran, so the search comes back successful, reports the provider, and
16
+ * silently searched the whole web.
17
+ *
18
+ * An unusable entry is refused for the same reason, and for EVERY provider
19
+ * rather than only the ones translating to `site:`. Dropping it is the same
20
+ * trade one step worse: the translation emits no clause for an empty list and
21
+ * the task clears the list afterwards, so one bad entry in a one-entry list
22
+ * removes the restriction from both paths at once.
23
+ */
24
+ export declare function domainNormalizationBlock(opts: WebSearchProviderConformanceOpts): void;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { WebSearchProviderConformanceOpts } from "../types";
7
+ /**
8
+ * `maxResults` is a ceiling, and it means the same thing on every route.
9
+ *
10
+ * It is the one option `unhonorableOptions` deliberately never reports: asking
11
+ * for more results than a provider's cap is not a requirement the way a domain
12
+ * restriction is, so an over-large value is clamped rather than refused. That
13
+ * asymmetry is what makes the rest of it worth asserting — a provider is free
14
+ * to return fewer, and never free to return more, and neither half is visible
15
+ * to a caller who gets a plausible-looking list back.
16
+ *
17
+ * Three providers needed a fix for exactly this in one window, each found by
18
+ * hand on its own route: an API with no result parameter has to apply the bound
19
+ * itself after the fact, and every one that forgot returned whatever the vendor
20
+ * felt like.
21
+ */
22
+ export declare function maxResultsCeilingBlock(opts: WebSearchProviderConformanceOpts): void;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { WebSearchProviderConformanceOpts } from "../types";
7
+ /**
8
+ * The `query` output port is the query that ran, and `provider` is who ran it.
9
+ *
10
+ * Both exist because the task rewrites one and chooses the other. A
11
+ * `query-operator` provider has its domain restriction spliced into the query
12
+ * as `site:` clauses, so the string that ran is not the string the caller
13
+ * passed — and an adapter that echoes the input instead is reporting a search
14
+ * that did not happen. Under `"auto"` the caller did not pick the vendor
15
+ * either, so `provider` is the only record of which quota was spent and which
16
+ * engine's ranking produced the list.
17
+ */
18
+ export declare function reportedQueryBlock(opts: WebSearchProviderConformanceOpts): void;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { WebSearchProviderConformanceOpts } from "../types";
7
+ /**
8
+ * The run's signal reaches the call, not just a check in front of it.
9
+ *
10
+ * A `throwIfAborted()` before the request answers the easy half — a run already
11
+ * cancelled does not start one — and leaves the expensive half alone: a
12
+ * cancelled run whose request is already in flight keeps it in flight, and a
13
+ * grounded turn nobody is waiting for is still billed for every token it
14
+ * generates. The signal has to be handed to the transport itself.
15
+ *
16
+ * Asserted on what the adapter passed outward rather than on how fast the
17
+ * promise rejects. A rejection proves the task stopped waiting; only the signal
18
+ * on the call proves the call stopped running.
19
+ */
20
+ export declare function signalThreadingBlock(opts: WebSearchProviderConformanceOpts): void;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { IWebSearchProvider, WebSearchRequest } from "@workglow/web-search";
7
+ import type { WebSearchConformanceHarness } from "./types";
8
+ /** The query every assertion searches for, so a rewrite of it is visible. */
9
+ export declare const PROBE_QUERY = "transformer architecture";
10
+ /**
11
+ * A provider registered beside the one under test, so `"auto"` has somewhere
12
+ * else to land and a credential can be named for a vendor that is not this one.
13
+ *
14
+ * It declares everything, which is what makes it a useful foil: routing prefers
15
+ * a provider a key is named for, so a decoy that could serve the request is the
16
+ * only way to catch a key reaching the wrong vendor.
17
+ */
18
+ export declare function decoyProvider(name: string, onSearch?: (r: WebSearchRequest) => void): IWebSearchProvider;
19
+ /** Registers the provider under test alone, the state most assertions want. */
20
+ export declare function registerOnly(harness: WebSearchConformanceHarness): void;
21
+ /**
22
+ * Whether a domain restriction reaches this provider as a list or as `site:`
23
+ * operators spliced into the query. The exclude direction defaults to the
24
+ * include direction, exactly as the task reads it.
25
+ */
26
+ export declare function domainRoutes(provider: IWebSearchProvider): {
27
+ readonly include: "native" | "query-operator" | false;
28
+ readonly exclude: "native" | "query-operator" | false;
29
+ };
30
+ /**
31
+ * Everything one search sent, as a single string to look for a substring in.
32
+ *
33
+ * The decoded rendering is appended rather than substituted, so a value matches
34
+ * whichever way this provider carried it. One sends `site:example.com` in a
35
+ * JSON body and the next sends `site%3Aexample.com` in a query string; both are
36
+ * the same restriction, and a suite that reads only the raw bytes would report
37
+ * the second as a restriction that never left. Appending keeps the equality
38
+ * assertions exact — two sends are equal here only if their raw forms were.
39
+ */
40
+ export declare function sentText(harness: WebSearchConformanceHarness): string;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { WebSearchProviderConformanceOpts } from "./types";
7
+ /**
8
+ * Everything an `IWebSearchProvider` owes a caller, over every adapter.
9
+ *
10
+ * Seven ship — three that own an HTTP fetch, four that reach a vendor SDK for
11
+ * model-grounded search — and they had no shared assertions at all. What that
12
+ * cost is legible in the package's own history: three of its twelve fixes in
13
+ * one window were "make property P true on every route", each found by hand,
14
+ * one route at a time, after the route that already had it was shipped. A
15
+ * property that has to hold on every route is what a parameterized suite is
16
+ * for.
17
+ *
18
+ * So the assertions are derived from `WebSearchCapabilities` rather than
19
+ * written per provider. The record already declares what each adapter can do;
20
+ * reading it and asserting the matching behaviour is what makes the suite still
21
+ * true after a provider changes what it supports — which is the event worth
22
+ * catching, and the one a hand-written expectation silently outlives.
23
+ */
24
+ export declare function runWebSearchProviderConformance(opts: WebSearchProviderConformanceOpts): void;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { IWebSearchProvider, WebSearchRequest, WebSearchResponse } from "@workglow/web-search";
7
+ /**
8
+ * One provider, wired to a transport that answers it instead of a vendor.
9
+ *
10
+ * The transport is the adapter's own boundary, not a network stub: an HTTP
11
+ * provider is intercepted at the `FetchUrlTask` it owns, an SDK-backed one at
12
+ * the client handed to its constructor. Both report what went out as text,
13
+ * which is what lets one suite assert "the option reached the wire" across two
14
+ * transports that share no shape.
15
+ */
16
+ export interface WebSearchConformanceHarness {
17
+ readonly provider: IWebSearchProvider;
18
+ /**
19
+ * Everything the adapter sent outward, one entry per call, flattened to text
20
+ * — a URL with its query string and body, or the JSON of the SDK arguments.
21
+ *
22
+ * Flattened rather than structured because every assertion over it is
23
+ * differential: the same search with and without one option has to send
24
+ * something different. That question has an answer for every provider, where
25
+ * "which field carries the date bound" has a different one for each.
26
+ */
27
+ readonly sent: () => readonly string[];
28
+ /** The abort signal each outbound call was given, in call order. */
29
+ readonly signals: () => ReadonlyArray<AbortSignal | undefined>;
30
+ /** Runs the provider directly against this transport, under `signal`. */
31
+ readonly search: (request: WebSearchRequest, signal: AbortSignal) => Promise<WebSearchResponse>;
32
+ /** Removes the interception. Called after every test. */
33
+ readonly dispose: () => void;
34
+ }
35
+ export interface WebSearchHarnessRequest {
36
+ /** How many results the canned answer carries. */
37
+ readonly resultCount: number;
38
+ }
39
+ export interface WebSearchProviderConformanceOpts {
40
+ readonly name: string;
41
+ readonly skip?: boolean;
42
+ readonly timeout?: number;
43
+ /**
44
+ * A fresh provider and transport per test. Nothing is shared between tests: a
45
+ * registry is process-wide, and a provider that cached a client in one test
46
+ * would answer the next one's assertions about what it sent.
47
+ */
48
+ readonly createHarness: (request: WebSearchHarnessRequest) => Promise<WebSearchConformanceHarness>;
49
+ /**
50
+ * Whether the run's `AbortSignal` is handed to the outbound call itself.
51
+ *
52
+ * True for an adapter reaching a vendor SDK, where nothing else would stop a
53
+ * grounded turn that is still being billed. False for one whose fetch this
54
+ * package owns: cancellation reaches it through the `FetchUrlTask` it owns
55
+ * and that task's own scope, so the adapter passes no signal of its own and
56
+ * there is nothing at this boundary to observe. A flag rather than a silent
57
+ * skip, because "this adapter drops the signal" and "this adapter never held
58
+ * one" are the two answers that must not look alike.
59
+ */
60
+ readonly signalReachesTransport: boolean;
61
+ /**
62
+ * Whether this provider's date parameter is a CLOSED interval, so a half-open
63
+ * range has its missing end filled rather than sent half.
64
+ *
65
+ * Brave's `freshness` and Gemini's `timeRangeFilter` are closed and fill;
66
+ * Tavily sets `start_date` and `end_date` independently and correctly sends
67
+ * only the bound it was given. A flag rather than something the suite infers,
68
+ * because the two are indistinguishable from outside — and the failure it
69
+ * guards is a provider that drops the open end and reports the bound as
70
+ * honored on a search that ran unfiltered at that end. Meaningless, and
71
+ * ignored, when `dateFilter` is false.
72
+ */
73
+ readonly fillsOpenDateBounds: boolean;
74
+ /**
75
+ * A domain this provider's canned results sit on, used where a request has to
76
+ * name a real-looking host. Defaults to `example.com`.
77
+ */
78
+ readonly sampleDomain?: string;
79
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ /**
7
+ * Conformance suite for `IWebSearchProvider` — what a provider declares in its
8
+ * capability record is what it refuses, what it attempts, and what it sends.
9
+ */
10
+ export * from "./web-search/assertions/capabilityAgreement";
11
+ export * from "./web-search/assertions/credentialNaming";
12
+ export * from "./web-search/assertions/dateFiltering";
13
+ export * from "./web-search/assertions/domainNormalization";
14
+ export * from "./web-search/assertions/maxResultsCeiling";
15
+ export * from "./web-search/assertions/reportedQuery";
16
+ export * from "./web-search/assertions/signalThreading";
17
+ export * from "./web-search/fixtures";
18
+ export * from "./web-search/runWebSearchProviderConformance";
19
+ export * from "./web-search/types";