@ontrails/testing 1.0.0-beta.12 → 1.0.0-beta.13

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 (43) hide show
  1. package/CHANGELOG.md +58 -27
  2. package/README.md +9 -9
  3. package/dist/context.d.ts +11 -11
  4. package/dist/context.d.ts.map +1 -1
  5. package/dist/context.js +23 -21
  6. package/dist/context.js.map +1 -1
  7. package/dist/contracts.js +8 -8
  8. package/dist/contracts.js.map +1 -1
  9. package/dist/crosses.d.ts +38 -0
  10. package/dist/crosses.d.ts.map +1 -0
  11. package/dist/crosses.js +213 -0
  12. package/dist/crosses.js.map +1 -0
  13. package/dist/examples.d.ts +4 -4
  14. package/dist/examples.js +31 -31
  15. package/dist/examples.js.map +1 -1
  16. package/dist/harness-mcp.d.ts +1 -1
  17. package/dist/harness-mcp.js +2 -2
  18. package/dist/harness-mcp.js.map +1 -1
  19. package/dist/index.d.ts +5 -5
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +3 -3
  22. package/dist/index.js.map +1 -1
  23. package/dist/trail.js +1 -1
  24. package/dist/trail.js.map +1 -1
  25. package/dist/types.d.ts +8 -8
  26. package/dist/types.d.ts.map +1 -1
  27. package/package.json +1 -1
  28. package/src/__tests__/all.test.ts +20 -18
  29. package/src/__tests__/context.test.ts +27 -27
  30. package/src/__tests__/contracts.test.ts +29 -29
  31. package/src/__tests__/{follows.test.ts → crosses.test.ts} +193 -195
  32. package/src/__tests__/detours.test.ts +3 -3
  33. package/src/__tests__/examples.test.ts +145 -144
  34. package/src/__tests__/trail.test.ts +4 -4
  35. package/src/context.ts +36 -32
  36. package/src/contracts.ts +12 -12
  37. package/src/{follows.ts → crosses.ts} +97 -92
  38. package/src/examples.ts +43 -43
  39. package/src/harness-mcp.ts +2 -2
  40. package/src/index.ts +6 -6
  41. package/src/trail.ts +1 -1
  42. package/src/types.ts +9 -9
  43. package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md CHANGED
@@ -1,17 +1,48 @@
1
1
  # @ontrails/testing
2
2
 
3
- ## 1.0.0-beta.12
3
+ ## 1.0.0-beta.13
4
+
5
+ ### Minor Changes
6
+
7
+ - Trail-native vocabulary cutover. Breaking API field renames across all packages:
8
+
9
+ - Trail spec: `run:` → `blaze:`, `follow:` → `crosses:`, `services:` → `provisions:`, `metadata:` → `meta:`, `emits:` → `signals:`
10
+ - Runtime: `ctx.follow()` → `ctx.cross()`, `ctx.emit()` → `ctx.signal()`, `ctx.signal` (abort) → `ctx.abortSignal`
11
+ - Entry points: `blaze(app)` → `trailhead(app)`
12
+ - Package rename: `@ontrails/crumbs` → `@ontrails/tracker`
13
+ - Wrapper types: `Layer` → `Gate`, `layers`/`middleware` → `gates`
14
+ - Transport: `surface` → `trailhead`, `adapter` → `connector`
4
15
 
5
16
  ### Patch Changes
6
17
 
7
- - Complete trifecta for config, permits, and crumbs (formerly tracks)
18
+ - 6944147: Complete trifecta for config, permits, and tracker (formerly tracks)
8
19
 
9
- - **config**: Add `configService`, `config.layer`, `config.trail`, and `config.workspace` trails with full `defineConfig`, `resolve`, `describe`, `explain`, `doctor`, and code generation support
20
+ - **config**: Add `configProvision`, `configGate`, `config.trail`, and `config.workspace` trails with full `defineConfig`, `resolve`, `describe`, `explain`, `doctor`, and code generation support
10
21
  - **permits**: Add `authService` and `auth.verify` trail for runtime authorization checks
11
- - **crumbs**: Rename tracks to crumbs; add `crumbsService` and `crumbs.status` trail for structured event tracking
22
+ - **tracker**: Rename tracks to tracker; add `trackerProvision` and `tracker.status` trail for structured signal tracking
23
+ - **cli**: Fix build flag handling and improve bootstrap scaffolding
24
+ - **testing**: Expand test context helpers and example-based testing utilities
25
+ - **core/mcp/http**: Internal alignment for provision and composition updates
26
+
27
+ - Updated dependencies [6944147]
28
+ - Updated dependencies
29
+ - @ontrails/core@1.0.0-beta.13
30
+ - @ontrails/cli@1.0.0-beta.13
31
+ - @ontrails/mcp@1.0.0-beta.13
32
+ - @ontrails/logging@1.0.0-beta.13
33
+
34
+ ## 1.0.0-beta.12
35
+
36
+ ### Patch Changes
37
+
38
+ - Complete trifecta for config, permits, and tracker (formerly tracks)
39
+
40
+ - **config**: Add `configProvision`, `config.gate`, `config.trail`, and `config.workspace` trails with full `defineConfig`, `resolve`, `describe`, `explain`, `doctor`, and code generation support
41
+ - **permits**: Add `authProvision` and `auth.verify` trail for runtime authorization checks
42
+ - **tracker**: Rename tracks to tracker; add `trackerProvision` and `tracker.status` trail for structured event tracking
12
43
  - **cli**: Fix build flag handling and improve bootstrap scaffolding
13
44
  - **testing**: Expand test context helpers and example-based testing utilities
14
- - **core/mcp/http**: Internal alignment for service and composition updates
45
+ - **core/mcp/http**: Internal alignment for provision and composition updates
15
46
 
16
47
  - Updated dependencies
17
48
  - @ontrails/core@1.0.0-beta.12
@@ -23,19 +54,19 @@
23
54
 
24
55
  ### Minor Changes
25
56
 
26
- - Add services as a first-class primitive.
57
+ - Add provisions as a first-class primitive.
27
58
 
28
- Services make infrastructure dependencies declarative, injectable, and governable. Define a service with `service()`, declare it on a trail with `services: [db]`, and access it with `db.from(ctx)` or `ctx.service()`.
59
+ Provisions make infrastructure dependencies declarative, injectable, and governable. Define a provision with `provision()`, declare it on a trail with `provisions: [db]`, and access it with `db.from(ctx)` or `ctx.provision()`.
29
60
 
30
- **Core:** `service()` factory, `ServiceSpec<T>`, `ServiceContext`, singleton resolution in `executeTrail`, in-flight creation dedup, `isService` guard, `findDuplicateServiceId`, topo service discovery and validation, `services` field on trail specs.
61
+ **Core:** `provision()` factory, `ProvisionSpec<T>`, `ProvisionContext`, singleton resolution in `executeTrail`, in-flight creation dedup, `isProvision` guard, `findDuplicateProvisionId`, topo provision discovery and validation, `provisions` field on trail specs.
31
62
 
32
- **Testing:** Auto-resolution of `mock` factories in `testAll`, `testExamples`, `testContracts`, and `testFollows`. Explicit `services` overrides with correct precedence (`explicit > ctx.extensions > auto-mock`). Service mock propagation through follow graphs.
63
+ **Testing:** Auto-resolution of `mock` factories in `testAll`, `testExamples`, `testContracts`, and `testCrosses`. Explicit `provisions` overrides with correct precedence (`explicit > ctx.extensions > auto-mock`). Provision mock propagation through crossing graphs.
33
64
 
34
- **Warden:** `service-declarations` rule validates `db.from(ctx)` and `ctx.service()` usage matches declared `services: [...]`. `service-exists` rule validates declared service IDs resolve in project context. Scope-aware AST walking skips nested function boundaries.
65
+ **Warden:** `provision-declarations` rule validates `db.from(ctx)` and `ctx.provision()` usage matches declared `provisions: [...]`. `provision-exists` rule validates declared provision IDs resolve in project context. Scope-aware AST walking skips nested function boundaries.
35
66
 
36
- **Surfaces:** Service overrides thread through `dispatch` and `blaze` on CLI, MCP, and HTTP.
67
+ **Trailheads:** Provision overrides thread through `run` and `trailhead` on CLI, MCP, and HTTP.
37
68
 
38
- **Introspection:** Survey and surface map outputs include service graph. Topo exposes `.services`, `.getService()`, `.hasService()`, `.listServices()`, `.serviceIds()`, `.serviceCount`.
69
+ **Introspection:** Survey and trailhead map outputs include provision graph. Topo exposes `.provisions`, `.getProvision()`, `.hasProvision()`, `.listProvisions()`, `.provisionIds()`, `.provisionCount`.
39
70
 
40
71
  **Docs:** ADR-009 accepted. Unified services guide, updated vocabulary, getting-started, architecture, and package READMEs.
41
72
 
@@ -61,9 +92,9 @@
61
92
 
62
93
  ### Minor Changes
63
94
 
64
- - Consolidated improvements across all surface packages.
95
+ - Consolidated improvements across all trailhead packages.
65
96
 
66
- **core**: Add `TrailResult<T>` utility type, `topo.ids()` and `topo.count` accessors, `dispatch()` for headless trail execution, and extract shared `executeTrail` pipeline used by CLI/MCP/HTTP.
97
+ **core**: Add `TrailResult<T>` utility type, `topo.ids()` and `topo.count` accessors, `run()` for headless trail execution, and extract shared `executeTrail` pipeline used by CLI/MCP/HTTP.
67
98
 
68
99
  **http**: Detect route path collisions and return `Result` from `buildHttpRoutes()`, wire request `AbortSignal` through to trail context, and make write → POST mapping explicit in intent-to-method lookup.
69
100
 
@@ -71,7 +102,7 @@
71
102
 
72
103
  **cli**: Verify exception catching via centralized `executeTrail`.
73
104
 
74
- **testing**: Follow context awareness improvements.
105
+ **testing**: Cross-context awareness improvements.
75
106
 
76
107
  **warden**: Refactor rules as composable trails with examples.
77
108
 
@@ -131,15 +162,15 @@
131
162
 
132
163
  **BREAKING CHANGES:**
133
164
 
134
- - `hike()` removed — use `trail()` with optional `follow: [...]` field
135
- - `follows` renamed to `follow` (singular, matching `ctx.follow()`)
165
+ - `hike()` removed — use `trail()` with optional `crosses: [...]` field
166
+ - `follows` renamed to `crosses` (matching `ctx.cross()`)
136
167
  - `topo.hikes` removed — single `topo.trails` map
137
168
  - `kind: 'hike'` removed — everything is `kind: 'trail'`
138
169
  - `readOnly`/`destructive` booleans replaced by `intent: 'read' | 'write' | 'destroy'`
139
170
  - `implementation` field renamed to `run`
140
171
  - `markers` field renamed to `metadata`
141
- - `testHike` renamed to `testFollows`, `HikeScenario` to `FollowScenario`
142
- - `blaze()` now returns the surface handle (`Command` for CLI, `Server` for MCP)
172
+ - `testHike` renamed to `testCrosses`, `HikeScenario` to `CrossScenario`
173
+ - `trailhead()` now returns the trailhead handle (`Command` for CLI, `Server` for MCP)
143
174
 
144
175
  ### Patch Changes
145
176
 
@@ -153,15 +184,15 @@
153
184
 
154
185
  ### Minor Changes
155
186
 
156
- - Bug fixes across all surface packages found via parallel Codex review.
187
+ - Bug fixes across all trailhead packages found via parallel Codex review.
157
188
 
158
189
  **core**: Fix Result.toJson false circular detection on DAGs, deserializeError subclass round-trip, topo cross-kind ID collisions, validateTopo multi-node cycle detection, error example input validation bypass, and deriveFields array type collapse.
159
190
 
160
- **cli**: Switch blaze to parseAsync for proper async error handling, add boolean flag negation (--no-flag), and strict number parsing that rejects partial input.
191
+ **cli**: Switch trailhead to parseAsync for proper async error handling, add boolean flag negation (--no-flag), and strict number parsing that rejects partial input.
161
192
 
162
193
  **mcp**: Align BlobRef with core (including ReadableStream support) and detect tool-name collisions after normalization.
163
194
 
164
- **testing**: Include hikes in testContracts validation, with follow-context awareness.
195
+ **testing**: Include hikes in testContracts validation, with cross-context awareness.
165
196
 
166
197
  **warden**: Collect hike detour targets, validate detour refs in hike specs, and stop implementation-returns-result from walking into nested function bodies.
167
198
 
@@ -205,12 +236,12 @@
205
236
  - Initial v1 beta release of the Trails framework.
206
237
 
207
238
  - **@ontrails/core** — Result type, error taxonomy, trail/hike/event/topo, validateTopo, validateInput/Output, deriveFields, patterns, redaction, branded types, resilience
208
- - **@ontrails/cli** — CLI surface adapter, Commander integration, flag derivation, layers
209
- - **@ontrails/mcp** — MCP surface adapter, tool generation, annotations, progress bridge
210
- - **@ontrails/logging** — Structured logging, sinks, formatters, LogTape adapter
211
- - **@ontrails/testing** — testAll, testExamples, testTrail, testHike, testContracts, testDetours, surface harnesses
239
+ - **@ontrails/cli** — CLI trailhead connector, Commander integration, flag derivation, gates
240
+ - **@ontrails/mcp** — MCP trailhead connector, tool generation, annotations, progress bridge
241
+ - **@ontrails/logging** — Structured logging, sinks, formatters, LogTape connector
242
+ - **@ontrails/testing** — testAll, testExamples, testTrail, testHike, testContracts, testDetours, trailhead harnesses
212
243
  - **@ontrails/warden** — AST-based code convention rules via oxc-parser, drift detection, CI formatters
213
- - **@ontrails/schema** — Surface map generation, hashing, semantic diffing
244
+ - **@ontrails/schema** — Trailhead map generation, hashing, semantic diffing
214
245
 
215
246
  ### Patch Changes
216
247
 
package/README.md CHANGED
@@ -29,10 +29,10 @@ testDetours(app); // Verify detour targets exist
29
29
  | --- | --- |
30
30
  | `testAll(topo, ctx?)` | Single-line governance suite: validation + examples + contracts + detours |
31
31
  | `testExamples(topo, ctx?)` | Run trail examples as `describe`/`test` blocks |
32
- | `testTrail(trail, scenarios)` | Custom scenarios for edge cases, error paths, and follow chains |
32
+ | `testTrail(trail, scenarios)` | Custom scenarios for edge cases, error paths, and cross chains |
33
33
  | `testContracts(topo, ctx?)` | Validate output against declared schemas |
34
34
  | `testDetours(topo)` | Verify every detour target exists in the topo |
35
- | `createFollowContext(options?)` | Mock `FollowFn` for testing composite trails; returns preconfigured `Result` values keyed by trail ID |
35
+ | `createCrossContext(options?)` | Mock `CrossFn` for testing composite trails; returns preconfigured `Result` values keyed by trail ID |
36
36
  | `createTestContext(options?)` | `TrailContext` with sensible test defaults |
37
37
  | `createTestLogger()` | Logger that captures entries in memory for assertions |
38
38
  | `createCliHarness(options)` | Execute CLI commands in-process, capture stdout/stderr |
@@ -55,9 +55,9 @@ testTrail(showTrail, [
55
55
  ]);
56
56
  ```
57
57
 
58
- ## Testing composition (trails with follow)
58
+ ## Testing composition (trails with crosses)
59
59
 
60
- `testTrail` works the same for trails with `follow` -- it exercises the follow graph:
60
+ `testTrail` works the same for trails with `crosses` -- it exercises the crossing graph:
61
61
 
62
62
  ```typescript
63
63
  import { testTrail } from '@ontrails/testing';
@@ -68,25 +68,25 @@ testTrail(onboardTrail, [
68
68
  ]);
69
69
  ```
70
70
 
71
- When you need to isolate a composite trail and stub out its dependencies, use `createFollowContext`:
71
+ When you need to isolate a composite trail and stub out its dependencies, use `createCrossContext`:
72
72
 
73
73
  ```typescript
74
- import { createFollowContext, createTestContext } from '@ontrails/testing';
74
+ import { createCrossContext, createTestContext } from '@ontrails/testing';
75
75
  import { Result } from '@ontrails/core';
76
76
 
77
- const follow = createFollowContext({
77
+ const cross = createCrossContext({
78
78
  responses: {
79
79
  'entity.add': Result.ok({ id: '1', name: 'Delta', type: 'tool' }),
80
80
  'search': Result.ok({ results: [] }),
81
81
  },
82
82
  });
83
- const ctx = { ...createTestContext(), follow };
83
+ const ctx = { ...createTestContext(), cross };
84
84
  const result = await onboardTrail.run({ name: 'Delta', type: 'tool' }, ctx);
85
85
  ```
86
86
 
87
87
  Calls to unregistered trail IDs return `Result.err` with a descriptive message, so missing stubs fail loudly.
88
88
 
89
- ## Surface harnesses
89
+ ## Trailhead harnesses
90
90
 
91
91
  ```typescript
92
92
  import { createCliHarness, createMcpHarness } from '@ontrails/testing';
package/dist/context.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Test context factory for creating TrailContext instances suitable for testing.
3
3
  */
4
- import type { FollowFn, ServiceOverrideMap, Topo, TrailContext } from '@ontrails/core';
4
+ import type { CrossFn, ProvisionOverrideMap, Topo, TrailContext } from '@ontrails/core';
5
5
  import { Result } from '@ontrails/core';
6
6
  import type { TestTrailContextOptions } from './types.js';
7
7
  /**
@@ -9,10 +9,10 @@ import type { TestTrailContextOptions } from './types.js';
9
9
  *
10
10
  * - `requestId`: `"test-request-001"` (deterministic)
11
11
  * - `logger`: a `TestLogger` that captures entries
12
- * - `signal`: a non-aborted AbortController signal
12
+ * - `abortSignal`: a non-aborted AbortController signal
13
13
  */
14
14
  export declare const createTestContext: (overrides?: TestTrailContextOptions) => TrailContext;
15
- export interface CreateFollowContextOptions {
15
+ export interface CreateCrossContextOptions {
16
16
  readonly responses?: Record<string, Result<unknown, Error>> | undefined;
17
17
  }
18
18
  /** Minimal permit shape returned by the mint function. */
@@ -28,7 +28,7 @@ export interface MintableTrail {
28
28
  }
29
29
  export interface TestExecutionOptions {
30
30
  readonly ctx?: Partial<TrailContext> | undefined;
31
- readonly services?: ServiceOverrideMap | undefined;
31
+ readonly provisions?: ProvisionOverrideMap | undefined;
32
32
  /**
33
33
  * When true, disables automatic permit minting. Tests must provide
34
34
  * explicit permits.
@@ -45,31 +45,31 @@ export interface TestExecutionOptions {
45
45
  readonly mintPermit?: (trail: MintableTrail) => MintedPermit | undefined;
46
46
  }
47
47
  /**
48
- * Create a mock `FollowFn` for testing composite trails.
48
+ * Create a mock `CrossFn` for testing composite trails.
49
49
  *
50
50
  * Returns preconfigured `Result` values keyed by trail ID. Calls to
51
51
  * unregistered IDs return `Result.err` with a descriptive message.
52
52
  *
53
53
  * @example
54
54
  * ```ts
55
- * const follow = createFollowContext({
55
+ * const cross = createCrossContext({
56
56
  * responses: { 'entity.add': Result.ok({ id: '1', name: 'Alpha' }) },
57
57
  * });
58
- * const ctx = { ...createTestContext(), follow };
58
+ * const ctx = { ...createTestContext(), cross };
59
59
  * ```
60
60
  */
61
- export declare const createFollowContext: (options?: CreateFollowContextOptions) => FollowFn;
61
+ export declare const createCrossContext: (options?: CreateCrossContextOptions) => CrossFn;
62
62
  /**
63
63
  * Default permit minter — reads `trail.permit.scopes` and produces a
64
64
  * minimal permit object. No dependency on `@ontrails/permits`.
65
65
  */
66
66
  export declare const defaultMintPermit: (trail: MintableTrail) => MintedPermit | undefined;
67
67
  export declare const normalizeTestExecutionOptions: (input?: Partial<TrailContext> | TestExecutionOptions) => TestExecutionOptions;
68
- export declare const mergeServiceOverrides: (autoResolved: ServiceOverrideMap, ctx: Partial<TrailContext> | undefined, explicit: ServiceOverrideMap | undefined) => ServiceOverrideMap;
69
- export declare const resolveMockServices: (app: Topo) => Promise<ServiceOverrideMap>;
68
+ export declare const mergeProvisionOverrides: (autoResolved: ProvisionOverrideMap, ctx: Partial<TrailContext> | undefined, explicit: ProvisionOverrideMap | undefined) => ProvisionOverrideMap;
69
+ export declare const resolveMockProvisions: (app: Topo) => Promise<ProvisionOverrideMap>;
70
70
  /**
71
71
  * Merge a Partial<TrailContext> into a test context.
72
72
  * Used internally when the public API accepts Partial<TrailContext>.
73
73
  */
74
- export declare const mergeTestContext: (ctx?: Partial<TrailContext>, services?: ServiceOverrideMap) => TrailContext;
74
+ export declare const mergeTestContext: (ctx?: Partial<TrailContext>, provisions?: ProvisionOverrideMap) => TrailContext;
75
75
  //# sourceMappingURL=context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,QAAQ,EACR,kBAAkB,EAClB,IAAI,EACJ,YAAY,EACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,MAAM,EAAuB,MAAM,gBAAgB,CAAC;AAG7D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAU1D;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAC5B,YAAY,uBAAuB,KAClC,YAaF,CAAC;AAMF,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC;CACzE;AAED,0DAA0D;AAC1D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,4EAA4E;AAC5E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,CAAC,EACZ;QAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,GACtC,QAAQ,GACR,SAAS,CAAC;CACf;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,QAAQ,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACnD;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7C;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,YAAY,GAAG,SAAS,CAAC;CAC1E;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,GAC9B,UAAU,0BAA0B,KACnC,QAcF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,OAAO,aAAa,KACnB,YAAY,GAAG,SAKjB,CAAC;AAWF,eAAO,MAAM,6BAA6B,GACxC,QAAQ,OAAO,CAAC,YAAY,CAAC,GAAG,oBAAoB,KACnD,oBACqD,CAAC;AAEzD,eAAO,MAAM,qBAAqB,GAChC,cAAc,kBAAkB,EAChC,KAAK,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,EACtC,UAAU,kBAAkB,GAAG,SAAS,KACvC,kBAID,CAAC;AAaH,eAAO,MAAM,mBAAmB,GAC9B,KAAK,IAAI,KACR,OAAO,CAAC,kBAAkB,CAAiC,CAAC;AAE/D;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAC3B,MAAM,OAAO,CAAC,YAAY,CAAC,EAC3B,WAAW,kBAAkB,KAC5B,YAcF,CAAC"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,OAAO,EACP,oBAAoB,EACpB,IAAI,EACJ,YAAY,EACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,MAAM,EAAyB,MAAM,gBAAgB,CAAC;AAG/D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAU1D;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAC5B,YAAY,uBAAuB,KAClC,YAcF,CAAC;AAMF,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC;CACzE;AAED,0DAA0D;AAC1D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,4EAA4E;AAC5E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,CAAC,EACZ;QAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,GACtC,QAAQ,GACR,SAAS,CAAC;CACf;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,UAAU,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACvD;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7C;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,YAAY,GAAG,SAAS,CAAC;CAC1E;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,kBAAkB,GAC7B,UAAU,yBAAyB,KAClC,OAcF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,OAAO,aAAa,KACnB,YAAY,GAAG,SAKjB,CAAC;AAWF,eAAO,MAAM,6BAA6B,GACxC,QAAQ,OAAO,CAAC,YAAY,CAAC,GAAG,oBAAoB,KACnD,oBACqD,CAAC;AAEzD,eAAO,MAAM,uBAAuB,GAClC,cAAc,oBAAoB,EAClC,KAAK,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,EACtC,UAAU,oBAAoB,GAAG,SAAS,KACzC,oBAID,CAAC;AAeH,eAAO,MAAM,qBAAqB,GAChC,KAAK,IAAI,KACR,OAAO,CAAC,oBAAoB,CAAmC,CAAC;AAEnE;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAC3B,MAAM,OAAO,CAAC,YAAY,CAAC,EAC3B,aAAa,oBAAoB,KAChC,YAeF,CAAC"}
package/dist/context.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Test context factory for creating TrailContext instances suitable for testing.
3
3
  */
4
- import { Result, createServiceLookup } from '@ontrails/core';
4
+ import { Result, createProvisionLookup } from '@ontrails/core';
5
5
  import { createTestLogger } from './logger.js';
6
6
  // ---------------------------------------------------------------------------
7
7
  // createTestContext
@@ -11,42 +11,43 @@ import { createTestLogger } from './logger.js';
11
11
  *
12
12
  * - `requestId`: `"test-request-001"` (deterministic)
13
13
  * - `logger`: a `TestLogger` that captures entries
14
- * - `signal`: a non-aborted AbortController signal
14
+ * - `abortSignal`: a non-aborted AbortController signal
15
15
  */
16
16
  export const createTestContext = (overrides) => {
17
17
  const cwd = overrides?.cwd ?? process.cwd();
18
18
  const ctx = {
19
+ abortSignal: overrides?.abortSignal ?? new AbortController().signal,
19
20
  cwd,
20
21
  env: overrides?.env ?? { TRAILS_ENV: 'test' },
21
22
  extensions: undefined,
22
23
  logger: overrides?.logger ?? createTestLogger(),
23
24
  requestId: overrides?.requestId ?? 'test-request-001',
24
- signal: overrides?.signal ?? new AbortController().signal,
25
25
  workspaceRoot: cwd,
26
26
  };
27
- ctx.service = createServiceLookup(() => ctx);
27
+ const lookup = createProvisionLookup(() => ctx);
28
+ ctx.provision = lookup;
28
29
  return ctx;
29
30
  };
30
31
  /**
31
- * Create a mock `FollowFn` for testing composite trails.
32
+ * Create a mock `CrossFn` for testing composite trails.
32
33
  *
33
34
  * Returns preconfigured `Result` values keyed by trail ID. Calls to
34
35
  * unregistered IDs return `Result.err` with a descriptive message.
35
36
  *
36
37
  * @example
37
38
  * ```ts
38
- * const follow = createFollowContext({
39
+ * const cross = createCrossContext({
39
40
  * responses: { 'entity.add': Result.ok({ id: '1', name: 'Alpha' }) },
40
41
  * });
41
- * const ctx = { ...createTestContext(), follow };
42
+ * const ctx = { ...createTestContext(), cross };
42
43
  * ```
43
44
  */
44
- export const createFollowContext = (options) => {
45
+ export const createCrossContext = (options) => {
45
46
  const responses = options?.responses ?? {};
46
47
  return (id, _input) => {
47
48
  const response = responses[id];
48
49
  if (response === undefined) {
49
- return Promise.resolve(Result.err(new Error(`No mock response for follow("${id}")`)));
50
+ return Promise.resolve(Result.err(new Error(`No mock response for cross("${id}")`)));
50
51
  }
51
52
  return Promise.resolve(response);
52
53
  };
@@ -63,43 +64,44 @@ export const defaultMintPermit = (trail) => {
63
64
  };
64
65
  const isTestExecutionOptions = (input) => input !== undefined &&
65
66
  (Object.hasOwn(input, 'ctx') ||
66
- Object.hasOwn(input, 'services') ||
67
+ Object.hasOwn(input, 'provisions') ||
67
68
  Object.hasOwn(input, 'strictPermits') ||
68
69
  Object.hasOwn(input, 'mintPermit'));
69
70
  export const normalizeTestExecutionOptions = (input) => isTestExecutionOptions(input) ? input : { ctx: input };
70
- export const mergeServiceOverrides = (autoResolved, ctx, explicit) => ({
71
+ export const mergeProvisionOverrides = (autoResolved, ctx, explicit) => ({
71
72
  ...autoResolved,
72
73
  ...ctx?.extensions,
73
74
  ...explicit,
74
75
  });
75
- const buildMockServices = async (app) => {
76
- const services = {};
77
- for (const declaredService of app.listServices()) {
78
- if (!declaredService.mock) {
76
+ const buildMockProvisions = async (app) => {
77
+ const provisions = {};
78
+ for (const declaredProvision of app.listProvisions()) {
79
+ if (!declaredProvision.mock) {
79
80
  continue;
80
81
  }
81
- services[declaredService.id] = await declaredService.mock();
82
+ provisions[declaredProvision.id] = await declaredProvision.mock();
82
83
  }
83
- return services;
84
+ return provisions;
84
85
  };
85
- export const resolveMockServices = async (app) => await buildMockServices(app);
86
+ export const resolveMockProvisions = async (app) => await buildMockProvisions(app);
86
87
  /**
87
88
  * Merge a Partial<TrailContext> into a test context.
88
89
  * Used internally when the public API accepts Partial<TrailContext>.
89
90
  */
90
- export const mergeTestContext = (ctx, services) => {
91
+ export const mergeTestContext = (ctx, provisions) => {
91
92
  const base = createTestContext();
92
93
  const extensions = {
93
94
  ...base.extensions,
94
95
  ...ctx?.extensions,
95
- ...services,
96
+ ...provisions,
96
97
  };
97
98
  const merged = {
98
99
  ...base,
99
100
  ...ctx,
100
101
  extensions: Object.keys(extensions).length === 0 ? undefined : extensions,
101
102
  };
102
- merged.service = createServiceLookup(() => merged);
103
+ const lookup = createProvisionLookup(() => merged);
104
+ merged.provision = lookup;
103
105
  return merged;
104
106
  };
105
107
  //# sourceMappingURL=context.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
package/dist/contracts.js CHANGED
@@ -8,17 +8,17 @@
8
8
  import { describe, test } from 'bun:test';
9
9
  import { executeTrail, formatZodIssues, validateInput } from '@ontrails/core';
10
10
  import { expectOk } from './assertions.js';
11
- import { mergeServiceOverrides, mergeTestContext, normalizeTestExecutionOptions, resolveMockServices, } from './context.js';
11
+ import { mergeProvisionOverrides, mergeTestContext, normalizeTestExecutionOptions, resolveMockProvisions, } from './context.js';
12
12
  // ---------------------------------------------------------------------------
13
13
  // Helpers
14
14
  // ---------------------------------------------------------------------------
15
- /** Check if a trail requires follow() but the context doesn't provide it. */
16
- const needsFollowContext = (t, resolveCtx) => {
15
+ /** Check if a trail requires cross() but the context doesn't provide it. */
16
+ const needsCrossContext = (t, resolveCtx) => {
17
17
  const spec = t;
18
- if (!spec.follow || spec.follow.length === 0) {
18
+ if (!spec.crosses || spec.crosses.length === 0) {
19
19
  return false;
20
20
  }
21
- return !normalizeTestExecutionOptions(resolveCtx()).ctx?.follow;
21
+ return !normalizeTestExecutionOptions(resolveCtx()).ctx?.cross;
22
22
  };
23
23
  const validateOutputSchema = (outputSchema, value, trailId, exampleName) => {
24
24
  const parsed = outputSchema.safeParse(value);
@@ -47,20 +47,20 @@ export const testContracts = (app, ctxOrFactory) => {
47
47
  if (t.examples === undefined || t.examples.length === 0) {
48
48
  return;
49
49
  }
50
- if (needsFollowContext(t, resolveInput)) {
50
+ if (needsCrossContext(t, resolveInput)) {
51
51
  return;
52
52
  }
53
53
  const { examples, output: outputSchema } = t;
54
54
  const successExamples = examples.filter((e) => e.error === undefined);
55
55
  test.each(successExamples)('contract: $name', async (example) => {
56
56
  const resolved = normalizeTestExecutionOptions(resolveInput());
57
- const services = mergeServiceOverrides(await resolveMockServices(app), resolved.ctx, resolved.services);
57
+ const provisions = mergeProvisionOverrides(await resolveMockProvisions(app), resolved.ctx, resolved.provisions);
58
58
  const testCtx = mergeTestContext(resolved.ctx);
59
59
  const validated = validateInput(t.input, example.input);
60
60
  expectOk(validated);
61
61
  const result = await executeTrail(t, example.input, {
62
62
  ctx: testCtx,
63
- services,
63
+ provisions,
64
64
  });
65
65
  const resultValue = expectOk(result);
66
66
  validateOutputSchema(outputSchema, resultValue, t.id, example.name);
@@ -1 +1 @@
1
- {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * testCrosses — crossing-aware scenario testing for trails with crossings.
3
+ *
4
+ * Tests the crossing graph: which trails were crossed, in what order,
5
+ * and supports failure injection from crossed trail examples.
6
+ */
7
+ import type { AnyTrail, ProvisionOverrideMap, TrailContext } from '@ontrails/core';
8
+ import type { CrossScenario } from './types.js';
9
+ /** Options for testCrosses that provide trail definitions for injection. */
10
+ export interface TestCrossOptions {
11
+ /** Partial context overrides. */
12
+ readonly ctx?: Partial<TrailContext> | undefined;
13
+ /**
14
+ * Explicit provision overrides merged on top of auto-resolved mocks for every
15
+ * scenario. Values are passed by reference — provide immutable objects, or
16
+ * use `mock()` on the provision definition to get a fresh instance per run.
17
+ */
18
+ readonly provisions?: ProvisionOverrideMap | undefined;
19
+ /** Map of trail ID to trail definition, used for injectFromExample. */
20
+ readonly trails?: ReadonlyMap<string, AnyTrail> | undefined;
21
+ }
22
+ /**
23
+ * Generate a describe block for a trail with crossings with one test per scenario.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * testCrosses(onboardTrail, [
28
+ * {
29
+ * description: "crosses add then relate",
30
+ * input: { name: "Alpha" },
31
+ * expectOk: true,
32
+ * expectCrossed: ["entity.add", "entity.relate"],
33
+ * },
34
+ * ]);
35
+ * ```
36
+ */
37
+ export declare const testCrosses: (trailDef: AnyTrail, scenarios: readonly CrossScenario[], options?: TestCrossOptions) => void;
38
+ //# sourceMappingURL=crosses.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crosses.d.ts","sourceRoot":"","sources":["../src/crosses.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EACV,QAAQ,EAER,oBAAoB,EACpB,YAAY,EACb,MAAM,gBAAgB,CAAC;AAexB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AA0ShD,4EAA4E;AAC5E,MAAM,WAAW,gBAAgB;IAC/B,iCAAiC;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;IACjD;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACvD,uEAAuE;IACvE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,SAAS,CAAC;CAC7D;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW,GACtB,UAAU,QAAQ,EAClB,WAAW,SAAS,aAAa,EAAE,EACnC,UAAU,gBAAgB,KACzB,IAsBF,CAAC"}