@ontrails/core 1.0.0-beta.2 → 1.0.0-beta.22

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 (245) hide show
  1. package/CHANGELOG.md +285 -5
  2. package/README.md +113 -33
  3. package/package.json +11 -1
  4. package/src/activation-provenance.ts +111 -0
  5. package/src/activation-source-compatibility.ts +430 -0
  6. package/src/activation-source-projection.ts +221 -0
  7. package/src/activation-source.ts +91 -0
  8. package/src/blob-ref.ts +51 -0
  9. package/src/branded.ts +1 -1
  10. package/src/compose-batch.ts +69 -0
  11. package/src/compose-schema.ts +36 -0
  12. package/src/context.ts +44 -10
  13. package/src/contour.ts +346 -0
  14. package/src/derive.ts +59 -18
  15. package/src/detours.ts +8 -0
  16. package/src/draft.ts +342 -0
  17. package/src/error-projection.ts +51 -0
  18. package/src/errors.ts +309 -48
  19. package/src/execute.ts +1577 -0
  20. package/src/fire.ts +1169 -0
  21. package/src/index.ts +477 -32
  22. package/src/internal/fork-ctx.ts +69 -0
  23. package/src/layer-projection.ts +193 -0
  24. package/src/layer.ts +43 -6
  25. package/src/observe.ts +361 -0
  26. package/src/path-security.ts +1 -1
  27. package/src/permits.ts +12 -0
  28. package/src/redaction/patterns.ts +6 -3
  29. package/src/resilience.ts +11 -11
  30. package/src/resource-config.ts +792 -0
  31. package/src/resource.ts +194 -0
  32. package/src/result.ts +36 -4
  33. package/src/run.ts +76 -0
  34. package/src/schedule-runtime.ts +689 -0
  35. package/src/schedule.ts +326 -0
  36. package/src/serialization.ts +119 -39
  37. package/src/signal-diagnostics.ts +633 -0
  38. package/src/signal-ref.ts +87 -0
  39. package/src/signal.ts +104 -0
  40. package/src/store/accessor-protocol.ts +56 -0
  41. package/src/store/index.ts +4 -0
  42. package/src/structured-examples.ts +248 -0
  43. package/src/surface-derivation.ts +91 -0
  44. package/src/surface-filter.ts +176 -0
  45. package/src/surface-versioning.ts +42 -0
  46. package/src/topo.ts +769 -57
  47. package/src/tracing.ts +345 -0
  48. package/src/trail.ts +1161 -29
  49. package/src/trails/derive-trail.ts +842 -0
  50. package/src/trails/index.ts +9 -0
  51. package/src/trails/ingest.ts +139 -0
  52. package/src/trails-db.ts +208 -0
  53. package/src/transport-error-map.ts +174 -0
  54. package/src/type-utils.ts +87 -0
  55. package/src/types.ts +254 -12
  56. package/src/validate-established-topo.ts +69 -0
  57. package/src/validate-topo.ts +442 -35
  58. package/src/validation.ts +152 -4
  59. package/src/version-marker.ts +716 -0
  60. package/src/version-resolution.ts +308 -0
  61. package/src/version-runtime.ts +120 -0
  62. package/src/webhook.ts +278 -0
  63. package/src/workspace.ts +1 -1
  64. package/src/zod-wrappers.ts +72 -0
  65. package/.turbo/turbo-build.log +0 -1
  66. package/.turbo/turbo-lint.log +0 -3
  67. package/.turbo/turbo-typecheck.log +0 -1
  68. package/dist/adapters.d.ts +0 -39
  69. package/dist/adapters.d.ts.map +0 -1
  70. package/dist/adapters.js +0 -2
  71. package/dist/adapters.js.map +0 -1
  72. package/dist/blob-ref.d.ts +0 -20
  73. package/dist/blob-ref.d.ts.map +0 -1
  74. package/dist/blob-ref.js +0 -22
  75. package/dist/blob-ref.js.map +0 -1
  76. package/dist/branded.d.ts +0 -36
  77. package/dist/branded.d.ts.map +0 -1
  78. package/dist/branded.js +0 -89
  79. package/dist/branded.js.map +0 -1
  80. package/dist/collections.d.ts +0 -31
  81. package/dist/collections.d.ts.map +0 -1
  82. package/dist/collections.js +0 -60
  83. package/dist/collections.js.map +0 -1
  84. package/dist/context.d.ts +0 -10
  85. package/dist/context.d.ts.map +0 -1
  86. package/dist/context.js +0 -15
  87. package/dist/context.js.map +0 -1
  88. package/dist/derive.d.ts +0 -33
  89. package/dist/derive.d.ts.map +0 -1
  90. package/dist/derive.js +0 -122
  91. package/dist/derive.js.map +0 -1
  92. package/dist/errors.d.ts +0 -83
  93. package/dist/errors.d.ts.map +0 -1
  94. package/dist/errors.js +0 -142
  95. package/dist/errors.js.map +0 -1
  96. package/dist/event.d.ts +0 -45
  97. package/dist/event.d.ts.map +0 -1
  98. package/dist/event.js +0 -17
  99. package/dist/event.js.map +0 -1
  100. package/dist/fetch.d.ts +0 -15
  101. package/dist/fetch.d.ts.map +0 -1
  102. package/dist/fetch.js +0 -102
  103. package/dist/fetch.js.map +0 -1
  104. package/dist/guards.d.ts +0 -17
  105. package/dist/guards.d.ts.map +0 -1
  106. package/dist/guards.js +0 -25
  107. package/dist/guards.js.map +0 -1
  108. package/dist/health.d.ts +0 -18
  109. package/dist/health.d.ts.map +0 -1
  110. package/dist/health.js +0 -5
  111. package/dist/health.js.map +0 -1
  112. package/dist/hike.d.ts +0 -36
  113. package/dist/hike.d.ts.map +0 -1
  114. package/dist/hike.js +0 -20
  115. package/dist/hike.js.map +0 -1
  116. package/dist/index.d.ts +0 -34
  117. package/dist/index.d.ts.map +0 -1
  118. package/dist/index.js +0 -38
  119. package/dist/index.js.map +0 -1
  120. package/dist/job.d.ts +0 -24
  121. package/dist/job.d.ts.map +0 -1
  122. package/dist/job.js +0 -17
  123. package/dist/job.js.map +0 -1
  124. package/dist/layer.d.ts +0 -17
  125. package/dist/layer.d.ts.map +0 -1
  126. package/dist/layer.js +0 -21
  127. package/dist/layer.js.map +0 -1
  128. package/dist/path-security.d.ts +0 -28
  129. package/dist/path-security.d.ts.map +0 -1
  130. package/dist/path-security.js +0 -63
  131. package/dist/path-security.js.map +0 -1
  132. package/dist/patterns/bulk.d.ts +0 -15
  133. package/dist/patterns/bulk.d.ts.map +0 -1
  134. package/dist/patterns/bulk.js +0 -14
  135. package/dist/patterns/bulk.js.map +0 -1
  136. package/dist/patterns/change.d.ts +0 -10
  137. package/dist/patterns/change.d.ts.map +0 -1
  138. package/dist/patterns/change.js +0 -10
  139. package/dist/patterns/change.js.map +0 -1
  140. package/dist/patterns/date-range.d.ts +0 -10
  141. package/dist/patterns/date-range.d.ts.map +0 -1
  142. package/dist/patterns/date-range.js +0 -10
  143. package/dist/patterns/date-range.js.map +0 -1
  144. package/dist/patterns/index.d.ts +0 -9
  145. package/dist/patterns/index.d.ts.map +0 -1
  146. package/dist/patterns/index.js +0 -9
  147. package/dist/patterns/index.js.map +0 -1
  148. package/dist/patterns/pagination.d.ts +0 -18
  149. package/dist/patterns/pagination.d.ts.map +0 -1
  150. package/dist/patterns/pagination.js +0 -18
  151. package/dist/patterns/pagination.js.map +0 -1
  152. package/dist/patterns/progress.d.ts +0 -11
  153. package/dist/patterns/progress.d.ts.map +0 -1
  154. package/dist/patterns/progress.js +0 -11
  155. package/dist/patterns/progress.js.map +0 -1
  156. package/dist/patterns/sorting.d.ts +0 -13
  157. package/dist/patterns/sorting.d.ts.map +0 -1
  158. package/dist/patterns/sorting.js +0 -10
  159. package/dist/patterns/sorting.js.map +0 -1
  160. package/dist/patterns/status.d.ts +0 -15
  161. package/dist/patterns/status.d.ts.map +0 -1
  162. package/dist/patterns/status.js +0 -9
  163. package/dist/patterns/status.js.map +0 -1
  164. package/dist/patterns/timestamps.d.ts +0 -10
  165. package/dist/patterns/timestamps.d.ts.map +0 -1
  166. package/dist/patterns/timestamps.js +0 -10
  167. package/dist/patterns/timestamps.js.map +0 -1
  168. package/dist/redaction/index.d.ts +0 -4
  169. package/dist/redaction/index.d.ts.map +0 -1
  170. package/dist/redaction/index.js +0 -3
  171. package/dist/redaction/index.js.map +0 -1
  172. package/dist/redaction/patterns.d.ts +0 -9
  173. package/dist/redaction/patterns.d.ts.map +0 -1
  174. package/dist/redaction/patterns.js +0 -39
  175. package/dist/redaction/patterns.js.map +0 -1
  176. package/dist/redaction/redactor.d.ts +0 -27
  177. package/dist/redaction/redactor.d.ts.map +0 -1
  178. package/dist/redaction/redactor.js +0 -89
  179. package/dist/redaction/redactor.js.map +0 -1
  180. package/dist/resilience.d.ts +0 -34
  181. package/dist/resilience.d.ts.map +0 -1
  182. package/dist/resilience.js +0 -164
  183. package/dist/resilience.js.map +0 -1
  184. package/dist/result.d.ts +0 -57
  185. package/dist/result.d.ts.map +0 -1
  186. package/dist/result.js +0 -145
  187. package/dist/result.js.map +0 -1
  188. package/dist/serialization.d.ts +0 -27
  189. package/dist/serialization.d.ts.map +0 -1
  190. package/dist/serialization.js +0 -115
  191. package/dist/serialization.js.map +0 -1
  192. package/dist/topo.d.ts +0 -18
  193. package/dist/topo.d.ts.map +0 -1
  194. package/dist/topo.js +0 -74
  195. package/dist/topo.js.map +0 -1
  196. package/dist/trail.d.ts +0 -83
  197. package/dist/trail.d.ts.map +0 -1
  198. package/dist/trail.js +0 -16
  199. package/dist/trail.js.map +0 -1
  200. package/dist/types.d.ts +0 -46
  201. package/dist/types.d.ts.map +0 -1
  202. package/dist/types.js +0 -2
  203. package/dist/types.js.map +0 -1
  204. package/dist/validate-topo.d.ts +0 -24
  205. package/dist/validate-topo.d.ts.map +0 -1
  206. package/dist/validate-topo.js +0 -108
  207. package/dist/validate-topo.js.map +0 -1
  208. package/dist/validation.d.ts +0 -27
  209. package/dist/validation.d.ts.map +0 -1
  210. package/dist/validation.js +0 -134
  211. package/dist/validation.js.map +0 -1
  212. package/dist/workspace.d.ts +0 -25
  213. package/dist/workspace.d.ts.map +0 -1
  214. package/dist/workspace.js +0 -57
  215. package/dist/workspace.js.map +0 -1
  216. package/src/__tests__/blob-ref.test.ts +0 -103
  217. package/src/__tests__/branded.test.ts +0 -148
  218. package/src/__tests__/collections.test.ts +0 -126
  219. package/src/__tests__/context.test.ts +0 -66
  220. package/src/__tests__/derive.test.ts +0 -159
  221. package/src/__tests__/errors.test.ts +0 -309
  222. package/src/__tests__/event.test.ts +0 -82
  223. package/src/__tests__/fetch.test.ts +0 -217
  224. package/src/__tests__/guards.test.ts +0 -102
  225. package/src/__tests__/hike.test.ts +0 -117
  226. package/src/__tests__/job.test.ts +0 -98
  227. package/src/__tests__/layer.test.ts +0 -224
  228. package/src/__tests__/path-security.test.ts +0 -114
  229. package/src/__tests__/patterns.test.ts +0 -273
  230. package/src/__tests__/redaction.test.ts +0 -244
  231. package/src/__tests__/resilience.test.ts +0 -246
  232. package/src/__tests__/result.test.ts +0 -155
  233. package/src/__tests__/serialization.test.ts +0 -236
  234. package/src/__tests__/topo.test.ts +0 -184
  235. package/src/__tests__/trail.test.ts +0 -179
  236. package/src/__tests__/validate-topo.test.ts +0 -201
  237. package/src/__tests__/validation.test.ts +0 -283
  238. package/src/__tests__/workspace.test.ts +0 -183
  239. package/src/adapters.ts +0 -68
  240. package/src/event.ts +0 -77
  241. package/src/health.ts +0 -23
  242. package/src/hike.ts +0 -77
  243. package/src/job.ts +0 -20
  244. package/tsconfig.json +0 -9
  245. package/tsconfig.tsbuildinfo +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,285 @@
1
1
  # @ontrails/core
2
2
 
3
+ ## 1.0.0-beta.22
4
+
5
+ ## 1.0.0-beta.21
6
+
7
+ ### Patch Changes
8
+
9
+ - 99523f2: Clean up resource context naming in shipped source and examples so resource
10
+ factories consistently use resource vocabulary.
11
+
12
+ ## 1.0.0-beta.20
13
+
14
+ ### Patch Changes
15
+
16
+ - 851a2a3: Derive trail caller and blaze input types from the authored input schema while keeping one public input contract.
17
+
18
+ ## 1.0.0-beta.19
19
+
20
+ ### Major Changes
21
+
22
+ - 1eb5bdc: Rename first-class trail composition from the `cross` API family to the `compose` family across core contracts, testing helpers, topo projections, Warden rules, CLI scaffolds, and docs. `composes`, `ctx.compose`, `composeInput`, and `Compose*` type names are now the public authoring vocabulary; topo persistence migrates legacy composition rows and graph keys forward.
23
+
24
+ ### Patch Changes
25
+
26
+ - e41c382: Document beta-channel install guidance in package and adapter README install snippets so consumers use explicit `@beta` (or pinned `1.0.0-beta.N`) tags instead of accidental `latest` resolution during the prerelease line. Adds the policy doc at `docs/releases/beta-channel-policy.md`, prints both `latest` and `beta` dist-tags in `bun run publish:registry-check`, and aligns plugin/skill install snippets.
27
+ - f8d80b9: Refresh current-facing compose vocabulary in package documentation after the composition cutover.
28
+ - 846a597: Reject versioned trail marker schemas that use Zod validation checks or object
29
+ catchall policies outside the bounded marker subset.
30
+ - 223aaad: Fix `ctx.compose(trail, input)` inference for trails that do not define a
31
+ `composeInput` schema while preserving authored compose-input requirements.
32
+ - 3125f4d: Add pure revision transpose validation and execution helpers for trail versions.
33
+ - 2494dc6: Infer `resource()` create-context config types from resource config schemas.
34
+ - 2d53717: Add trail-only `version` / `versions` authoring types and TopoGraph projection.
35
+ - 16cb740: Run examples and contract checks across live trail version entries, and project version-entry example coverage into topo and survey reports.
36
+ - 8894ecb: Project content-addressed trail version markers and marker-prefix resolution.
37
+ - fdf7ec9: Resolve trail versions during execution, including live revisions, forks, marker references, and unsupported-version errors.
38
+ - d76be13: Require deprecated trail version entries to carry successor, migration, or note guidance and expose typed lifecycle helpers.
39
+ - 84f56a5: Project live trail-version metadata on CLI, HTTP, and MCP surfaces and thread explicit surface version selection into shared trail execution.
40
+ - 431b04c: Expose archived trail version lifecycle helpers and validate archived status reason metadata.
41
+ - 5d88104: Polish Trails blaze terminology across package docs and Warden guidance.
42
+ - f04a9ef: Tighten trail-versioning API polish by keeping executor cross-validation internals out of public options and improving absent marker diagnostics.
43
+
44
+ ## 1.0.0-beta.18
45
+
46
+ ## 1.0.0-beta.17
47
+
48
+ ### Patch Changes
49
+
50
+ - 3dc8254: Fix README TypeScript snippets so the expanded documentation snippet gate can verify them.
51
+
52
+ ## 1.0.0-beta.16
53
+
54
+ ### Major Changes
55
+
56
+ - 331e3a9: Relocate the topo-store public API from `@ontrails/core` to `@ontrails/topographer` per ADR-0042. Generic `trails-db` helpers (`openReadTrailsDb`, `openWriteTrailsDb`, `ensureSubsystemSchema`, `deriveTrailsDbPath`, `deriveTrailsDir`) stay in core because tracing and other subsystems share them.
57
+
58
+ Breaking pre-1.0 beta change. Update consumer imports:
59
+
60
+ ```diff
61
+ - import { topoStore, createTopoStore, createMockTopoStore, createTopoSnapshot, listTopoSnapshots, pinTopoSnapshot, unpinTopoSnapshot, createStoredTopoSnapshot, getStoredTopoExport, countTopoSnapshots, countPinnedSnapshots, countPrunableSnapshots, pruneUnpinnedSnapshots } from '@ontrails/core';
62
+ + import { topoStore, createTopoStore, createMockTopoStore, createTopoSnapshot, listTopoSnapshots, pinTopoSnapshot, unpinTopoSnapshot } from '@ontrails/topographer';
63
+ + import { createStoredTopoSnapshot, getStoredTopoExport, countTopoSnapshots, countPinnedSnapshots, countPrunableSnapshots, pruneUnpinnedSnapshots } from '@ontrails/topographer/backend-support';
64
+ ```
65
+
66
+ The same root move applies to types `ReadOnlyTopoStore`, `MockTopoStoreSeed`, `TopoSnapshot`, `TopoStoreRef`, `TopoStoreExportRecord`, `TopoStoreResourceRecord`, `TopoStoreTrailRecord`, `TopoStoreTrailDetailRecord`, `CreateTopoSnapshotInput`, and `ListTopoSnapshotsOptions`. The direct DB helper type `StoredTopoExport` moves to `@ontrails/topographer/backend-support`.
67
+
68
+ Core newly exports `activationSourceKey`, `projectActivationSourceDeclaration`, `activationSourceDeclarationSignature`, and the `ActivationSourceProjection` type — these were already used internally and are now part of the public surface so `@ontrails/topographer` (the only consumer that needs them) can import them through normal package channels.
69
+
70
+ - 10eae9a: Migrate the Trails workspace to the documented `.trails/` layout: committed `.lock` files at the workspace root, ignored `cache/` for rebuildable derived data, ignored `state/` for mutable runtime state, and `.trails/config.local.{ts,js}` for local overrides. The default SQLite path is now `.trails/state/trails.db`. Workspace bootstrap creates only `cache/` and `state/` — the legacy `dev/` and `generated/` subdirectories are no longer created. Dev reset cleans both the new `.trails/state/` paths and legacy `.trails/trails.db*` and `.trails/dev/tracing.db*` paths for one cycle. Scaffold and workspace gitignores reflect the new layout.
71
+
72
+ Workspace bootstrap is now owned by a single canonical source in `@ontrails/core`. The package exposes `ensureTrailsWorkspace()`, `WORKSPACE_GITIGNORE_CONTENT`, and `WORKSPACE_GITIGNORE_LINES`. `@ontrails/config` no longer exports its own `ensureWorkspace` (consumers should import from `@ontrails/core`). `trails create` now writes `.trails/.gitignore` during scaffolding so a fresh-scaffolded project's initial commit includes the workspace gitignore (resolves TRL-703).
73
+
74
+ ### Minor Changes
75
+
76
+ - bcdc484: Add an explicit `unmockable: { reason }` resource marker and have testing auto-mock resolution skip intentionally unmockable resources.
77
+ - 4b8d13b: **BREAKING:** Complete the `trailhead` to `surface` public API cutover in core.
78
+
79
+ - `TraceRecord.trailhead` is now `TraceRecord.surface`.
80
+ - `SURFACE_KEY` now uses the `__trails_surface` extension key value, and the deprecated `TRAILHEAD_KEY` alias is removed.
81
+ - Deprecated `transport*` surface-error aliases are removed; import the existing `surface*` names instead.
82
+ - `isVisibleToTrailheads` is renamed to `isVisibleToSurfaces`.
83
+
84
+ See `docs/migration/trailhead-to-surface.md` for the full migration map.
85
+
86
+ - 112b9f2: Add `dryRun` to `TrailContext` and wire `--dry-run`. `TrailContext` gains an optional `dryRun?: boolean` field, defaulted to `false` in `createTrailContext`. `ExecuteTrailOptions` carries `dryRun?: boolean` through `applyContextOverrides` so `executeTrail(t, input, { dryRun: true })` produces `ctx.dryRun === true`. The CLI's existing `dryRunPreset` (auto-derived for `intent: 'write' | 'destroy'` trails) now flows through `META_FLAG_CANDIDATES` and reaches the executor via `runTrailOnce`, so `trails run booking.cancel … --dry-run` lands `ctx.dryRun === true` on the trail's blaze. Trails that don't read the field are unchanged. Read-intent trails don't get `--dry-run` exposed.
87
+ - 893025e: Add `--permit '<json>'` to inject an inline permit on `trails run`. New `permitPreset()` exposes a `--permit` string flag that the CLI build parses and validates against the `BasePermit` shape (`{ id: string, scopes: string[] }`) using a small Zod schema. Valid permits flow through `ExecuteTrailOptions.permit` → `applyContextOverrides` → `ctx.permit` so existing `enforcePermitRequirement` behavior just sees a populated permit. Invalid JSON or schema mismatch surface as `Result.err(ValidationError)` (exit code 1) before the trail runs, avoiding spurious `PermitError` results from malformed input. The flag is global, never routed into trail input (added to `META_FLAG_CANDIDATES`), and overlays only when defined.
88
+
89
+ Topographer now projects permit requirements into surface-map entries and classifies permit-tightening diffs as breaking when new scopes are required.
90
+
91
+ - eec5e9d: Default `ctx.logger` to a structured stdout console sink when `topo()` is called without an `observe:` option. Apps now get observability for free with zero configuration, per ADR-0041. Explicit `observe:` values (including `combine()` with no sinks, an explicit `Logger`, or an explicit `{ log }` config) are preserved untouched — the default is only injected when no `observe:` is supplied.
92
+ - ebd4434: Phase 7 starts: typed layers with optional object-shaped surface input. `Layer` gains an optional `input?: LayerInputSchema` field for surface projection (TRL-473/474 will project it onto CLI/MCP/HTTP). `executeTrail({ layers })` remains the canonical per-call wrapper option. Layers without `input` schemas stay surface-invisible and cover runtime-only concerns such as tenant guards, rate limiting, circuit breaking, and custom audit logging.
93
+ - 863d473: Add three attachment scopes for typed layers — trail, surface, topo — with composition order **topo → surface → trail → blaze**. `TrailSpec` and `Trail` gain `layers?: readonly Layer[]` (default `[]`). `topo()` accepts `{ layers: [...] }` as the third options argument; the topo carries those layers and they reach the executor via `ExecuteTrailOptions.topoLayers`. The CLI's `surface()`/`createProgram()`/`deriveCliCommands` already supports a `layers` option; that now flows through `runTrailOnce` as `surfaceLayers`. The executor builds the layer chain `[...topoLayers, ...surfaceLayers, ...trail.layers, ...options.layers]` so topo wraps surface wraps trail wraps blaze (verified by composition-order tests at every level). Survey's `TrailDetailReport` adds `composedLayers: { topo, surface, trail }` so agents can introspect the layer chain per trail. Backward-compatible: every new field is optional with a non-undefined default; existing call sites are unchanged.
94
+ - 344f2f7: Project typed-layer `input` schemas onto CLI flags. Each effective layer (topo + surface + trail composition order) with a non-undefined `input` schema gets its fields auto-derived into `--flag` options on every command it attaches to. Parsed values route to the layer at runtime via `ctx.extensions[LAYER_INPUTS_KEY][layer.name]` — `Layer.wrap` is unchanged. Collision rule: if a layer field name collides with a trail input field, another layer's projected name, or a CLI meta flag, the layer's flag is renamed to `--<layer-name>-<original-flag-name>` and a one-line warning emits to stderr (`[trails] ...`). Renames are deterministic across builds. New `LAYER_INPUTS_KEY` (exported from `@ontrails/core`) reserves the `ctx.extensions` slot.
95
+ - 26f9ffd: Project typed-layer `input` schemas onto MCP and HTTP surfaces. Closes Phase 7. Lifts `collectAttachedTypedLayers` and `projectLayerFieldName` (collision-rename rule) into `@ontrails/core/internal/layer-projection` so all three surfaces share one source of truth. The CLI surface refactors to consume the lifted helpers (no behavior change). MCP merges layer fields into each tool's `inputSchema` and partitions inbound args at invocation time. HTTP merges layer fields into the route's request schema (query for reads, body for writes) and exposes new optional `HttpRouteDefinition.inputSchema` + `layerInputProjections` for surface adapters / OpenAPI generators. Collision rule matches TRL-473's: deterministic rename to a layer-prefixed camelCase name with the original captured in the routing table. Side fix: MCP and HTTP handlers now forward `topoLayers: graph.layers` + `surfaceLayers: layers` so topo-scope layers actually compose at runtime (previously the handlers used the deprecated `layers` alias and never read `graph.layers`).
96
+ - 22c6c06: Accept ADR-0041 Unified Observability and ship the first activation and
97
+ observability primitives it depends on: activation trace records, topo-level
98
+ observe configuration, webhook activation materialization, signal/webhook
99
+ warden coaching, the `@ontrails/observe` package, sink composition, and
100
+ zero-dependency observe sinks.
101
+
102
+ ### Patch Changes
103
+
104
+ - 73622ae: Thread `ResourceSpec.config` through the built-in auth resource. Resource config schemas that accept `undefined` now receive their parsed default when config values are omitted, and `authResource` can materialize the no-op or JWT adapter from typed config while preserving existing mock and override paths.
105
+ - 6300f70: Refresh source comments and test labels for retired connector terminology as adapter guardrails become strict.
106
+ - d172013: Preserve specialized TrailsError identity and retry-exhaustion metadata when
107
+ serializing and deserializing framework errors.
108
+ - c3fc5c3: Move previously root-exported helper contracts out of `src/internal/*` to stable core module homes, document their public boundary, and guard the public barrel against future internal re-exports.
109
+ - 20d7a5c: Enforce the shared safe error projection policy for public error bodies, diagnostics, serialized payloads, and CLI stderr.
110
+ - be5fb46: Publish registry-driven error taxonomy documentation and checks from the core error registry.
111
+ - e898cc4: Add repo-level Knip dead-code detection and remove stale internal exports and unused package dependencies surfaced by the new check.
112
+ - 3395234: Move store adapter-binding helpers to `@ontrails/store/adapter-support` and topographer direct database/admin helpers to `@ontrails/topographer/backend-support`, keeping root exports focused on contract-level APIs.
113
+ - 4399fdb: Renamed `@ontrails/schema` to `@ontrails/topographer`. Mechanical rename only — no API changes. Update import sites from `@ontrails/schema` to `@ontrails/topographer`. See ADR-0042 for the durable graph substrate doctrine.
114
+
115
+ ## 1.0.0-beta.15
116
+
117
+ ### Minor Changes
118
+
119
+ - 4ad6b25: Lexicon rename cleanup (ADR-0023). Breaking for `@ontrails/core`, `@ontrails/cli`, and `@ontrails/tracing` at the boundary; internal-only churn for `@ontrails/warden`.
120
+
121
+ - **core**: the topo store schema renames `topo_provisions` / `topo_trail_provisions` → `topo_resources` / `topo_trail_resources` and `provision_count` → `resource_count`. Schema version bumped v4→v5. Stores still carrying the legacy schema are detected on open, dropped, and recreated from the new DDL — previous topo saves are cleared. Stored-data helpers `listTopoStoreProvisions` / `getTopoStoreProvision` / `readProvisionUsage` / `mapProvisionRow` renamed to their `resource` counterparts. TS row types `TopoTrailProvisionRow` / `TopoProvisionRow` renamed to `TopoTrailResourceRow` / `TopoResourceRow`.
122
+ - **cli**: CLI output mode env vars are now derived from the topo name per ADR-0023. Legacy globals `TRAILS_JSON` / `TRAILS_JSONL` are no longer honored — a topo named `stash` reads `STASH_JSON` / `STASH_JSONL`. `ActionResultContext` gains a `topoName: string` field; `resolveOutputMode(flags, topoName)` takes a topo name argument.
123
+ - **tracing**: legacy `.trails/dev/tracker.db` migration path removed. Any user still running a pre-rename beta build with a `tracker.db` should delete it or migrate before upgrading.
124
+ - **warden**: internal-only rename of `provisionDeclarations` / `provisionExists` rules and their trails to `resourceDeclarations` / `resourceExists`. No behavior change.
125
+
126
+ ## 1.0.0-beta.14
127
+
128
+ ### Minor Changes
129
+
130
+ - 69057e9: Add hierarchical CLI command trees and structured input, enforce established-only topo exports across trailheads, move developer topo and tracker state onto shared `trails.db` with pins and maintenance flows, and ship schema-derived stores through `@ontrails/store` and its Drizzle runtime.
131
+
132
+ ## 1.0.0-beta.13
133
+
134
+ ### Minor Changes
135
+
136
+ - Trail-native vocabulary cutover. Breaking API field renames across all packages:
137
+
138
+ - Trail spec: `run:` → `blaze:`, `follow:` → `crosses:`, `services:` → `provisions:`, `metadata:` → `meta:`, `emits:` → `signals:`
139
+ - Runtime: `ctx.follow()` → `ctx.cross()`, `ctx.emit()` → `ctx.signal()`, `ctx.signal` (abort) → `ctx.abortSignal`
140
+ - Entry points: `blaze(app)` → `trailhead(app)`
141
+ - Package rename: `@ontrails/crumbs` → `@ontrails/tracker`
142
+ - Wrapper types: `Layer` → `Gate`, `layers`/`middleware` → `gates`
143
+ - Transport: `surface` → `trailhead`, `adapter` → `connector`
144
+
145
+ ### Patch Changes
146
+
147
+ - 6944147: Complete trifecta for config, permits, and tracker (formerly tracks)
148
+
149
+ - **config**: Add `configProvision`, `configGate`, `config.trail`, and `config.workspace` trails with full `defineConfig`, `resolve`, `describe`, `explain`, `doctor`, and code generation support
150
+ - **permits**: Add `authService` and `auth.verify` trail for runtime authorization checks
151
+ - **tracker**: Rename tracks to tracker; add `trackerProvision` and `tracker.status` trail for structured signal tracking
152
+ - **cli**: Fix build flag handling and improve bootstrap scaffolding
153
+ - **testing**: Expand test context helpers and example-based testing utilities
154
+ - **core/mcp/http**: Internal alignment for provision and composition updates
155
+
156
+ ## 1.0.0-beta.12
157
+
158
+ ### Patch Changes
159
+
160
+ - Complete trifecta for config, permits, and tracker (formerly tracks)
161
+
162
+ - **config**: Add `configProvision`, `config.gate`, `config.trail`, and `config.workspace` trails with full `defineConfig`, `resolve`, `describe`, `explain`, `doctor`, and code generation support
163
+ - **permits**: Add `authProvision` and `auth.verify` trail for runtime authorization checks
164
+ - **tracker**: Rename tracks to tracker; add `trackerProvision` and `tracker.status` trail for structured event tracking
165
+ - **cli**: Fix build flag handling and improve bootstrap scaffolding
166
+ - **testing**: Expand test context helpers and example-based testing utilities
167
+ - **core/mcp/http**: Internal alignment for provision and composition updates
168
+
169
+ ## 1.0.0-beta.11
170
+
171
+ ### Minor Changes
172
+
173
+ - Add provisions as a first-class primitive.
174
+
175
+ 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()`.
176
+
177
+ **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.
178
+
179
+ **Testing:** Auto-resolution of `mock` factories in `testAll`, `testExamples`, `testContracts`, and `testCrosses`. Explicit `services` overrides with correct precedence (`explicit > ctx.extensions > auto-mock`). Service mock propagation through crossing graphs.
180
+
181
+ **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.
182
+
183
+ **Trailheads:** Provision overrides thread through `run` and `trailhead` on CLI, MCP, and HTTP.
184
+
185
+ **Introspection:** Survey and trailhead map outputs include provision graph. Topo exposes `.provisions`, `.getProvision()`, `.hasProvision()`, `.listProvisions()`, `.provisionIds()`, `.provisionCount`.
186
+
187
+ **Docs:** ADR-009 accepted. Unified services guide, updated vocabulary, getting-started, architecture, and package READMEs.
188
+
189
+ ## 1.0.0-beta.10
190
+
191
+ ### Minor Changes
192
+
193
+ - Cleanup and hardening pass across all packages.
194
+
195
+ **core**: Deduplicate `RunOptions` as type alias of `ExecuteTrailOptions`. Replace `TrailContext` index signature with typed `extensions` field for type safety. Deep-merge `extensions` in `executeTrail` context resolution. Remove unused `Trailhead` type, `connectors.ts`, `health.ts`, and `job.ts` proof-of-concept from published package.
196
+
197
+ **cli**: Remove vestigial `kind` checks from build. Run `validateTopo()` automatically in `trailhead()` with opt-out via `validate: false`.
198
+
199
+ **http**: Remove vestigial `kind` checks from build. Run `validateTopo()` automatically in `trailhead()` with opt-out.
200
+
201
+ **mcp**: Remove vestigial `kind` checks from build. Run `validateTopo()` automatically in `trailhead()` with opt-out.
202
+
203
+ **warden**: Project-aware rule context preserved in trail wrappers.
204
+
205
+ ## 1.0.0-beta.9
206
+
207
+ ### Minor Changes
208
+
209
+ - Consolidated improvements across all trailhead packages.
210
+
211
+ **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.
212
+
213
+ **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.
214
+
215
+ **mcp**: Return `Result` from `buildMcpTools()` on collision instead of throwing.
216
+
217
+ **cli**: Verify exception catching via centralized `executeTrail`.
218
+
219
+ **testing**: Cross-context awareness improvements.
220
+
221
+ **warden**: Refactor rules as composable trails with examples.
222
+
223
+ **schema**: Error code and empty body fixes.
224
+
225
+ ## 1.0.0-beta.8
226
+
227
+ ## 1.0.0-beta.7
228
+
229
+ ## 1.0.0-beta.6
230
+
231
+ ### Patch Changes
232
+
233
+ - Fix Codex review findings on type-utils and cross-declarations.
234
+
235
+ **core**: `inputOf()`/`outputOf()` now preserve the exact Zod schema subtype instead of widening to `z.ZodType`.
236
+
237
+ **warden**: `cross-declarations` rule now recognizes single-object trail overload, detects any context parameter name (not just `ctx`), matches destructured `cross()` calls, resolves const identifiers in `crosses` arrays, and restricts blaze body extraction to top-level config properties.
238
+
239
+ ## 1.0.0-beta.5
240
+
241
+ ### Minor Changes
242
+
243
+ - Type utilities and cross-declarations warden rule.
244
+
245
+ **core**: Add `TrailInput<T>`, `TrailOutput<T>` utility types and `inputOf()`, `outputOf()` runtime schema accessors.
246
+
247
+ **warden**: Add `cross-declarations` rule — statically analyzes `ctx.cross()` calls against declared `crosses: [...]` arrays. Errors on undeclared calls, warns on unused declarations.
248
+
249
+ ## 1.0.0-beta.4
250
+
251
+ ### Major Changes
252
+
253
+ - API simplification: unified trail model, intent enum, run, metadata.
254
+
255
+ **BREAKING CHANGES:**
256
+
257
+ - `hike()` removed — use `trail()` with optional `crosses: [...]` field
258
+ - `follows` renamed to `crosses` (matching `ctx.cross()`)
259
+ - `topo.hikes` removed — single `topo.trails` map
260
+ - `kind: 'hike'` removed — everything is `kind: 'trail'`
261
+ - `readOnly`/`destructive` booleans replaced by `intent: 'read' | 'write' | 'destroy'`
262
+ - `implementation` field renamed to `run`
263
+ - `markers` field renamed to `metadata`
264
+ - `testHike` renamed to `testCrosses`, `HikeScenario` to `CrossScenario`
265
+ - `trailhead()` now returns the trailhead handle (`Command` for CLI, `Server` for MCP)
266
+
267
+ ## 1.0.0-beta.3
268
+
269
+ ### Minor Changes
270
+
271
+ - Bug fixes across all trailhead packages found via parallel Codex review.
272
+
273
+ **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.
274
+
275
+ **cli**: Switch trailhead to parseAsync for proper async error handling, add boolean flag negation (--no-flag), and strict number parsing that rejects partial input.
276
+
277
+ **mcp**: Align BlobRef with core (including ReadableStream support) and detect tool-name collisions after normalization.
278
+
279
+ **testing**: Include hikes in testContracts validation, with cross-context awareness.
280
+
281
+ **warden**: Collect hike detour targets, validate detour refs in hike specs, and stop implementation-returns-result from walking into nested function bodies.
282
+
3
283
  ## 1.0.0-beta.2
4
284
 
5
285
  ### Patch Changes
@@ -22,9 +302,9 @@
22
302
  - Initial v1 beta release of the Trails framework.
23
303
 
24
304
  - **@ontrails/core** — Result type, error taxonomy, trail/hike/event/topo, validateTopo, validateInput/Output, deriveFields, patterns, redaction, branded types, resilience
25
- - **@ontrails/cli** — CLI surface adapter, Commander integration, flag derivation, layers
26
- - **@ontrails/mcp** — MCP surface adapter, tool generation, annotations, progress bridge
27
- - **@ontrails/logging** — Structured logging, sinks, formatters, LogTape adapter
28
- - **@ontrails/testing** — testAll, testExamples, testTrail, testHike, testContracts, testDetours, surface harnesses
305
+ - **@ontrails/cli** — CLI trailhead connector, Commander integration, flag derivation, gates
306
+ - **@ontrails/mcp** — MCP trailhead connector, tool generation, annotations, progress bridge
307
+ - **@ontrails/logging** — Structured logging, sinks, formatters, LogTape connector
308
+ - **@ontrails/testing** — testAll, testExamples, testTrail, testHike, testContracts, testDetours, trailhead harnesses
29
309
  - **@ontrails/warden** — AST-based code convention rules via oxc-parser, drift detection, CI formatters
30
- - **@ontrails/schema** — Surface map generation, hashing, semantic diffing
310
+ - **@ontrails/schema** — Trailhead map generation, hashing, semantic diffing
package/README.md CHANGED
@@ -11,26 +11,24 @@ import { z } from 'zod';
11
11
  const greet = trail('greet', {
12
12
  input: z.object({ name: z.string().describe('Who to greet') }),
13
13
  output: z.object({ message: z.string() }),
14
- readOnly: true,
14
+ intent: 'read',
15
15
  examples: [
16
16
  { name: 'Hello', input: { name: 'World' }, expected: { message: 'Hello, World!' } },
17
17
  ],
18
- implementation: (input) => Result.ok({ message: `Hello, ${input.name}!` }),
18
+ blaze: (input) => Result.ok({ message: `Hello, ${input.name}!` }),
19
19
  });
20
20
 
21
- const app = topo('myapp', { greet });
21
+ const graph = topo('myapp', { greet });
22
22
  ```
23
23
 
24
- Hikes compose trails through `ctx.follow()`:
24
+ Trails compose other trails through `composes` and `ctx.compose()`:
25
25
 
26
26
  ```typescript
27
- import { hike } from '@ontrails/core';
28
-
29
- const onboard = hike('entity.onboard', {
30
- follows: ['entity.add', 'entity.relate'],
27
+ const onboard = trail('entity.onboard', {
28
+ composes: ['entity.add', 'entity.relate'],
31
29
  input: z.object({ name: z.string(), type: z.string() }),
32
- implementation: async (input, ctx) => {
33
- const added = await ctx.follow('entity.add', input);
30
+ blaze: async (input, ctx) => {
31
+ const added = await ctx.compose('entity.add', input);
34
32
  if (added.isErr()) return added;
35
33
  return Result.ok({ entity: added.value });
36
34
  },
@@ -43,11 +41,59 @@ const onboard = hike('entity.onboard', {
43
41
 
44
42
  | Export | What it does |
45
43
  | --- | --- |
46
- | `trail(id, spec)` | Define an atomic unit of work with typed input and `Result` output |
47
- | `hike(id, spec)` | Define a composition that follows other trails via `ctx.follow()` |
48
- | `event(id, spec)` | Define a server-originated push with a typed data schema |
49
- | `topo(name, ...modules)` | Collect trail modules into a queryable topology |
50
- | `validateTopo(topo)` | Structural validation: follows exist, no cycles, examples parse, output schemas present |
44
+ | `trail(id, spec)` | Define a unit of work with typed input and `Result` output; use `composes` for composition |
45
+ | `signal(id, spec)` | Define a server-originated notification with a typed data schema |
46
+ | `resource(id, spec)` | Define an infrastructure dependency with `create`, `dispose`, and optional `mock` |
47
+ | `drainResources(resources, ctx, configValues?)` | Evict and dispose cached resource singletons for surface/test shutdown |
48
+ | `blobRefSchema` / `createBlobRef(...)` | Declare and create binary output references with a shared descriptor contract |
49
+ | `topo(name, ...modules, options?)` | Collect trail modules into a queryable topology with optional `observe:` sinks |
50
+ | `deriveTrail(contour, operation, spec)` | Derive CRUD-shaped trail contracts from a contour on the `@ontrails/core/trails` subpath |
51
+ | `validateTopo(topo)` | Structural validation: compose targets exist, no cycles, examples parse, output schemas present |
52
+
53
+ ### Execution
54
+
55
+ | Export | What it does |
56
+ | --- | --- |
57
+ | `executeTrail(trail, rawInput, options?)` | Centralized execution pipeline: validates input, builds context, composes layers, runs the blazed trail. Never throws -- exceptions become `Result.err(InternalError)`. |
58
+ | `run(topo, id, input, options?)` | Headless trail execution by ID. Looks up the trail in the topo, then delegates to `executeTrail`. Returns `Result.err(NotFoundError)` if the ID is not registered. |
59
+
60
+ ```typescript
61
+ // executeTrail — surfaces use this directly
62
+ const surfaceResult = await executeTrail(greet, { name: 'Alice' });
63
+
64
+ // run — headless execution by trail ID
65
+ const runResult = await run(graph, 'greet', { name: 'Alice' });
66
+ if (runResult.isOk()) console.log(runResult.value);
67
+ ```
68
+
69
+ ### Topo accessors
70
+
71
+ Beyond the `trail(id, spec)` builder, `Topo` exposes these accessors:
72
+
73
+ | Accessor | What it returns |
74
+ | --- | --- |
75
+ | `topo.ids()` | `string[]` of all registered trail IDs |
76
+ | `topo.count` | Number of registered trails |
77
+ | `topo.get(id)` | The `Trail` with that ID, or `undefined` |
78
+ | `topo.has(id)` | Whether a trail ID is registered |
79
+ | `topo.list()` | All registered trails as an array |
80
+
81
+ ### Type utilities
82
+
83
+ | Export | What it does |
84
+ | --- | --- |
85
+ | `TrailInput<T>` | Extract the input type from a `Trail` |
86
+ | `TrailOutput<T>` | Extract the output type from a `Trail` |
87
+ | `TrailResult<T>` | `Result<TrailOutput<T>, Error>` -- the Result type for a trail's output |
88
+ | `inputOf(trail)` | Get the input Zod schema from a trail instance |
89
+ | `outputOf(trail)` | Get the output Zod schema (or `undefined`) from a trail instance |
90
+
91
+ ### Execution option types
92
+
93
+ | Type | What it describes |
94
+ | --- | --- |
95
+ | `ExecuteTrailOptions` | Options for `executeTrail`: `ctx`, `abortSignal`, `layers`, `createContext` |
96
+ | `RunOptions` | Same shape as `ExecuteTrailOptions`; forwarded by `run` |
51
97
 
52
98
  ### Result
53
99
 
@@ -69,39 +115,73 @@ result.unwrapOr(fallback); // Value or fallback
69
115
 
70
116
  ### Error taxonomy
71
117
 
72
- 13 error classes across 10 categories. Each maps deterministically to exit codes, HTTP status, and JSON-RPC codes on every surface.
73
-
74
- | Category | Classes | HTTP | Retryable |
75
- | --- | --- | --- | --- |
76
- | `validation` | `ValidationError`, `AmbiguousError`, `AssertionError` | 400 | No |
77
- | `not_found` | `NotFoundError` | 404 | No |
78
- | `conflict` | `AlreadyExistsError`, `ConflictError` | 409 | No |
79
- | `permission` | `PermissionError` | 403 | No |
80
- | `timeout` | `TimeoutError` | 504 | Yes |
81
- | `rate_limit` | `RateLimitError` | 429 | Yes |
82
- | `network` | `NetworkError` | 502 | Yes |
83
- | `internal` | `InternalError` | 500 | No |
84
- | `auth` | `AuthError` | 401 | No |
85
- | `cancelled` | `CancelledError` | 499 | No |
118
+ The current taxonomy is generated from the `errorClasses` owner registry and category code maps in `@ontrails/core`.
119
+
120
+ <!-- error-taxonomy:start -->
121
+ <!-- GENERATED: run `bun run error-taxonomy:sync`; check with `bun run error-taxonomy:check`. Variant: category. -->
122
+
123
+ | Category | CLI Exit | HTTP | JSON-RPC | Retryable | Fixed Classes |
124
+ | --- | --- | --- | --- | --- | --- |
125
+ | `validation` | 1 | 400 | -32602 | No | `ValidationError`, `AmbiguousError` |
126
+ | `not_found` | 2 | 404 | -32601 | No | `NotFoundError`, `VersionNotSupportedError` |
127
+ | `conflict` | 3 | 409 | -32603 | No | `AlreadyExistsError`, `ConflictError` |
128
+ | `permission` | 4 | 403 | -32600 | No | `PermissionError`, `PermitError` |
129
+ | `timeout` | 5 | 504 | -32603 | Yes | `TimeoutError` |
130
+ | `rate_limit` | 6 | 429 | -32603 | Yes | `RateLimitError` |
131
+ | `network` | 7 | 502 | -32603 | Yes | `NetworkError` |
132
+ | `internal` | 8 | 500 | -32603 | No | `AssertionError`, `InternalError`, `DerivationError`, `RecoverableCompletionError` |
133
+ | `auth` | 9 | 401 | -32600 | No | `AuthError` |
134
+ | `cancelled` | 130 | 499 | -32603 | No | `CancelledError` |
135
+
136
+ Dynamic classes:
137
+
138
+ - `RetryExhaustedError` inherits category and surface codes from its wrapped `TrailsError`; retryable is always No.
139
+ <!-- error-taxonomy:end -->
140
+
141
+ Public surface projections redact sensitive substrings before exposing a non-internal `TrailsError` message. Internal-category `TrailsError` instances and unknown native errors project with the generic message `Internal server error`; diagnostics and serialized payloads keep their useful structure while redacting messages, context, and stack strings.
86
142
 
87
143
  The developer returns `Result.err(new NotFoundError(...))`. The framework maps it to the right code on every surface.
88
144
 
89
145
  ### Other exports
90
146
 
91
- - **Schema derivation** -- `deriveFields(schema)` extracts field metadata from Zod for prompts and forms
147
+ - **Schema derivation** -- `deriveFields(schema)` extracts faithfully
148
+ representable field metadata from Zod for prompts and forms
92
149
  - **Validation** -- `validateInput`, `formatZodIssues`, `zodToJsonSchema`
93
- - **Resilience** -- `retry`, `withTimeout`, `shouldRetry`, `getBackoffDelay`
150
+ - **Resilience** -- `retry`, `withTimeout`, `shouldRetry`, `deriveBackoffDelay`
94
151
  - **Serialization** -- `serializeError`, `deserializeError`
95
152
  - **Branded types** -- `uuid`, `email`, `nonEmptyString`, `positiveInt`
96
- - **Layers** -- cross-cutting middleware via `composeLayers`
153
+ - **Execution layers** -- low-level pipeline wrappers via `composeLayers`
97
154
  - **Guards and collections** -- `isDefined`, `chunk`, `dedupe`, `groupBy`, `sortBy`
98
155
  - **Patterns** (`@ontrails/core/patterns`) -- reusable Zod schemas for pagination, bulk ops, timestamps, sorting
156
+ - **Trail factories** (`@ontrails/core/trails`) -- derive CRUD-shaped trail contracts from contours without re-authoring IDs, schemas, examples, or intents
99
157
  - **Redaction** (`@ontrails/core/redaction`) -- strip sensitive data before logging
100
158
 
159
+ ### Public helper boundaries
160
+
161
+ The root package also exposes a few low-level contracts that other framework packages build on:
162
+
163
+ - **Intrinsic tracing** -- `TraceRecord`, `TraceSink`, `TraceContext`, and the sink registry helpers are the core-owned execution record shape shared by `@ontrails/observe`, `@ontrails/tracing`, and adapters.
164
+ - **Trails DB** -- `deriveTrailsDbPath`, `deriveTrailsDir`, `ensureSubsystemSchema`, `openReadTrailsDb`, and `openWriteTrailsDb` are the generic database primitive used by framework subsystems.
165
+ - **Surface projection helpers** -- safe error projection, layer field projection, compose-batch validation, late-bound signal references, and Zod default-wrapper stripping are stable root exports for first-party surfaces, store helpers, and tests.
166
+
101
167
  See the [API Reference](../../docs/api-reference.md) for the full list.
102
168
 
169
+ ## Migration: topo-store moved to `@ontrails/topographer`
170
+
171
+ Per [ADR-0042](../../docs/adr/0042-core-topographer-boundary-doctrine.md), the topo-store public API previously exported from `@ontrails/core` now lives in `@ontrails/topographer`. Generic `trails-db` helpers (`openReadTrailsDb`, `openWriteTrailsDb`, `ensureSubsystemSchema`, `deriveTrailsDbPath`, `deriveTrailsDir`) stay in core because tracing and other subsystems share them.
172
+
173
+ Update consumer imports:
174
+
175
+ ```diff
176
+ - import { topoStore, createTopoStore, createMockTopoStore, createTopoSnapshot, listTopoSnapshots, pinTopoSnapshot, unpinTopoSnapshot, createStoredTopoSnapshot, getStoredTopoExport, countTopoSnapshots, countPinnedSnapshots, countPrunableSnapshots, pruneUnpinnedSnapshots } from '@ontrails/core';
177
+ + import { topoStore, createTopoStore, createMockTopoStore, createTopoSnapshot, listTopoSnapshots, pinTopoSnapshot, unpinTopoSnapshot } from '@ontrails/topographer';
178
+ + import { createStoredTopoSnapshot, getStoredTopoExport, countTopoSnapshots, countPinnedSnapshots, countPrunableSnapshots, pruneUnpinnedSnapshots } from '@ontrails/topographer/backend-support';
179
+ ```
180
+
181
+ Types `ReadOnlyTopoStore`, `MockTopoStoreSeed`, `TopoSnapshot`, `TopoStoreRef`, `TopoStoreExportRecord`, `TopoStoreResourceRecord`, `TopoStoreTrailRecord`, `TopoStoreTrailDetailRecord`, `CreateTopoSnapshotInput`, and `ListTopoSnapshotsOptions` move to `@ontrails/topographer`. `StoredTopoExport` moves to `@ontrails/topographer/backend-support`.
182
+
103
183
  ## Installation
104
184
 
105
185
  ```bash
106
- bun add @ontrails/core zod
186
+ bun add @ontrails/core@beta zod
107
187
  ```
package/package.json CHANGED
@@ -1,11 +1,21 @@
1
1
  {
2
2
  "name": "@ontrails/core",
3
- "version": "1.0.0-beta.2",
3
+ "version": "1.0.0-beta.22",
4
+ "files": [
5
+ "src/**/*.ts",
6
+ "!src/**/__tests__/**",
7
+ "!src/**/*.test.ts",
8
+ "!src/**/*.test-d.ts",
9
+ "README.md",
10
+ "CHANGELOG.md"
11
+ ],
4
12
  "type": "module",
5
13
  "exports": {
6
14
  ".": "./src/index.ts",
7
15
  "./patterns": "./src/patterns/index.ts",
8
16
  "./redaction": "./src/redaction/index.ts",
17
+ "./store": "./src/store/index.ts",
18
+ "./trails": "./src/trails/index.ts",
9
19
  "./package.json": "./package.json"
10
20
  },
11
21
  "scripts": {
@@ -0,0 +1,111 @@
1
+ import type {
2
+ ActivationSourceKind,
3
+ ActivationSourceMeta,
4
+ } from './activation-source.js';
5
+
6
+ export const ACTIVATION_PROVENANCE_KEY =
7
+ '__trails_activation_provenance' as const;
8
+
9
+ export interface ActivationProvenanceSource {
10
+ readonly cron?: string | undefined;
11
+ readonly id: string;
12
+ readonly kind: ActivationSourceKind;
13
+ readonly meta?: ActivationSourceMeta | undefined;
14
+ readonly producerTrailId?: string | undefined;
15
+ readonly timezone?: string | undefined;
16
+ }
17
+
18
+ export interface ActivationProvenance {
19
+ readonly fireId: string;
20
+ readonly parentFireId?: string | undefined;
21
+ readonly rootFireId: string;
22
+ readonly source: ActivationProvenanceSource;
23
+ }
24
+
25
+ export interface ActivationProvenanceCarrier {
26
+ readonly activation?: ActivationProvenance | undefined;
27
+ readonly extensions?: Readonly<Record<string, unknown>> | undefined;
28
+ }
29
+
30
+ const isObjectRecord = (value: unknown): value is Record<string, unknown> =>
31
+ typeof value === 'object' && value !== null && !Array.isArray(value);
32
+
33
+ const optionalString = (value: unknown): boolean =>
34
+ value === undefined || typeof value === 'string';
35
+
36
+ const isActivationProvenanceSource = (
37
+ value: unknown
38
+ ): value is ActivationProvenanceSource =>
39
+ isObjectRecord(value) &&
40
+ typeof value['id'] === 'string' &&
41
+ typeof value['kind'] === 'string' &&
42
+ optionalString(value['cron']) &&
43
+ optionalString(value['producerTrailId']) &&
44
+ optionalString(value['timezone']) &&
45
+ (value['meta'] === undefined || isObjectRecord(value['meta']));
46
+
47
+ const isActivationProvenance = (
48
+ value: unknown
49
+ ): value is ActivationProvenance =>
50
+ isObjectRecord(value) &&
51
+ typeof value['fireId'] === 'string' &&
52
+ optionalString(value['parentFireId']) &&
53
+ typeof value['rootFireId'] === 'string' &&
54
+ isActivationProvenanceSource(value['source']);
55
+
56
+ export const getActivationProvenance = (
57
+ ctx: ActivationProvenanceCarrier | undefined
58
+ ): ActivationProvenance | undefined => {
59
+ if (isActivationProvenance(ctx?.activation)) {
60
+ return ctx.activation;
61
+ }
62
+ const fromExtensions = ctx?.extensions?.[ACTIVATION_PROVENANCE_KEY];
63
+ return isActivationProvenance(fromExtensions) ? fromExtensions : undefined;
64
+ };
65
+
66
+ export const withActivationProvenance = <
67
+ TCtx extends {
68
+ readonly extensions?: Readonly<Record<string, unknown>> | undefined;
69
+ },
70
+ >(
71
+ ctx: TCtx,
72
+ activation: ActivationProvenance
73
+ ): TCtx & { readonly activation: ActivationProvenance } => ({
74
+ ...ctx,
75
+ activation,
76
+ extensions: {
77
+ ...ctx.extensions,
78
+ [ACTIVATION_PROVENANCE_KEY]: activation,
79
+ },
80
+ });
81
+
82
+ export const buildActivationProvenanceTraceAttrs = (
83
+ activation: ActivationProvenance | undefined
84
+ ): Readonly<Record<string, unknown>> => {
85
+ if (activation === undefined) {
86
+ return {};
87
+ }
88
+
89
+ const attrs: Record<string, unknown> = {
90
+ 'trails.activation.fire_id': activation.fireId,
91
+ 'trails.activation.root_fire_id': activation.rootFireId,
92
+ 'trails.activation.source.id': activation.source.id,
93
+ 'trails.activation.source.kind': activation.source.kind,
94
+ };
95
+
96
+ if (activation.parentFireId !== undefined) {
97
+ attrs['trails.activation.parent_fire_id'] = activation.parentFireId;
98
+ }
99
+ if (activation.source.producerTrailId !== undefined) {
100
+ attrs['trails.activation.source.producer_trail.id'] =
101
+ activation.source.producerTrailId;
102
+ }
103
+ if (activation.source.cron !== undefined) {
104
+ attrs['trails.activation.source.cron'] = activation.source.cron;
105
+ }
106
+ if (activation.source.timezone !== undefined) {
107
+ attrs['trails.activation.source.timezone'] = activation.source.timezone;
108
+ }
109
+
110
+ return attrs;
111
+ };