@ontrails/core 1.0.0-beta.42 → 1.0.0-beta.45

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.
package/src/layer.ts CHANGED
@@ -12,13 +12,13 @@ import type { Implementation } from './types.js';
12
12
  *
13
13
  * Layers attach at trail, surface, or topo scope and may declare an object
14
14
  * `input` schema describing the configuration they need from the surrounding
15
- * surface. Surface packages (CLI, MCP, HTTP) project this schema onto their
15
+ * surface. Surface packages (CLI, MCP, HTTP) render this schema onto their
16
16
  * native idioms — flags, tool parameters, query strings — alongside the
17
17
  * trail's own input schema.
18
18
  *
19
19
  * @remarks
20
- * The `input` schema is metadata for surface projection. It must be an object
21
- * schema so every surface can project named fields consistently. It is
20
+ * The `input` schema is metadata for surface rendering. It must be an object
21
+ * schema so every surface can render named fields consistently. It is
22
22
  * optional; layers without an `input` schema behave as plain wrappers. The
23
23
  * layer's `wrap` function is the runtime contract.
24
24
  */
@@ -31,13 +31,13 @@ export interface Layer {
31
31
  /**
32
32
  * Authored configuration the layer needs from the surrounding surface.
33
33
  *
34
- * Surface packages project this schema onto their native idioms (CLI flags,
34
+ * Surface packages render this schema onto their native idioms (CLI flags,
35
35
  * MCP tool parameters, HTTP query strings) so a layer's input fields appear
36
36
  * alongside the trail's own input fields. Optional — layers that wrap purely
37
37
  * by behavior, with no surface-visible inputs, may omit it.
38
38
  *
39
- * @see TRL-473 for CLI flag projection.
40
- * @see TRL-474 for MCP and HTTP projection.
39
+ * @see TRL-473 for CLI flag rendering.
40
+ * @see TRL-474 for MCP and HTTP rendering.
41
41
  */
42
42
  readonly input?: LayerInputSchema | undefined;
43
43
 
package/src/observe.ts CHANGED
@@ -210,10 +210,10 @@ const stringifyDefaultConsoleRecord = (record: LogRecord): string => {
210
210
  };
211
211
 
212
212
  /**
213
- * In-core mirror of `@ontrails/observe`'s `createConsoleSink` shape, kept
213
+ * In-core mirror of `@ontrails/observability`'s `createConsoleSink` shape, kept
214
214
  * minimal and private to avoid a reverse dependency from `@ontrails/core`
215
- * onto `@ontrails/observe`. It mirrors the console level mapping in
216
- * `packages/observe/src/sinks.ts:50` and emits each record as a single-line
215
+ * onto `@ontrails/observability`. It mirrors the console level mapping in
216
+ * `packages/observability/src/sinks.ts:50` and emits each record as a single-line
217
217
  * JSON object written to the matching `console.{debug|info|warn|error}` method.
218
218
  *
219
219
  * @remarks
@@ -231,7 +231,7 @@ const createDefaultConsoleSink = (): LogSink => ({
231
231
  return;
232
232
  }
233
233
  const payload = stringifyDefaultConsoleRecord(record);
234
- // oxlint-disable-next-line trails-local/no-console-in-packages -- ADR 0041 mandates a default console logger in core; this is the single sanctioned console boundary, mirroring `@ontrails/observe`'s `createConsoleSink`.
234
+ // oxlint-disable-next-line trails-local/no-console-in-packages -- ADR 0041 mandates a default console logger in core; this is the single sanctioned console boundary, mirroring `@ontrails/observability`'s `createConsoleSink`.
235
235
  console[method](payload);
236
236
  },
237
237
  });
@@ -251,8 +251,8 @@ export const normalizeObserve = (
251
251
  if (observe === undefined) {
252
252
  // ADR 0041 promises a non-null `ctx.logger` with zero configuration.
253
253
  // Returning the default config here lets the existing topo → adapter
254
- // path project this log sink into `ctx.logger` without a second
255
- // resolution point or a reverse dependency on `@ontrails/observe`.
254
+ // path renders this log sink into `ctx.logger` without a second
255
+ // resolution point or a reverse dependency on `@ontrails/observability`.
256
256
  return DEFAULT_OBSERVE_CONFIG;
257
257
  }
258
258
 
package/src/resource.ts CHANGED
@@ -52,7 +52,7 @@ export interface ResourceSpec<T, C = unknown> {
52
52
  readonly description?: string | undefined;
53
53
  /** Arbitrary meta for tooling and filtering. */
54
54
  readonly meta?: Readonly<Record<string, unknown>> | undefined;
55
- /** Signals projected or owned by this resource. */
55
+ /** Signals derived or owned by this resource. */
56
56
  readonly signals?: readonly AnySignal[] | undefined;
57
57
  /** Reserved for future resource-specific design; trail versioning is trail-only. */
58
58
  readonly version?: never;
@@ -1,5 +1,5 @@
1
1
  import type { ActivationEntry } from './activation-source.js';
2
- import { activationSourceKey } from './activation-source-projection.js';
2
+ import { activationSourceKey } from './activation-source-derivation.js';
3
3
  import {
4
4
  buildActivationProvenanceTraceAttrs,
5
5
  withActivationProvenance,
@@ -26,7 +26,7 @@ import {
26
26
  redactErrorContext,
27
27
  redactErrorStack,
28
28
  redactErrorString,
29
- } from './error-projection.js';
29
+ } from './error-rendering.js';
30
30
  import { Result } from './result.js';
31
31
 
32
32
  // ---------------------------------------------------------------------------
@@ -40,7 +40,7 @@ export interface StructuredSignalExample {
40
40
  // `Date`, `RegExp`, `Map`, and `Set` are objects (`typeof === 'object'`),
41
41
  // so they would pass the structural walk and reach `JSON.stringify`, which
42
42
  // silently coerces them: a `Date` becomes its ISO string, a `RegExp` and
43
- // any `Map`/`Set` become `{}`. Either way the projected shape diverges
43
+ // any `Map`/`Set` become `{}`. Either way the derived shape diverges
44
44
  // from the example author's declared input. Treat them as non-serializable
45
45
  // leaves so the example is dropped rather than misrepresented to MCP
46
46
  // clients.
@@ -107,7 +107,7 @@ const signalIdFromAssertion = (
107
107
  : undefined;
108
108
  };
109
109
 
110
- const projectSignalAssertion = (
110
+ const deriveSignalAssertion = (
111
111
  assertion: TrailExampleSignalAssertion
112
112
  ): StructuredTrailExampleSignalAssertion | undefined => {
113
113
  const signalId = signalIdFromAssertion(assertion);
@@ -115,43 +115,43 @@ const projectSignalAssertion = (
115
115
  return undefined;
116
116
  }
117
117
 
118
- const projected: Record<string, unknown> = { signalId };
118
+ const derived: Record<string, unknown> = { signalId };
119
119
  if (assertion.payload !== undefined) {
120
120
  const payload = toJsonSerializable(assertion.payload);
121
121
  if (payload === undefined) {
122
122
  return undefined;
123
123
  }
124
- projected['payload'] = payload;
124
+ derived['payload'] = payload;
125
125
  }
126
126
  if (assertion.payloadMatch !== undefined) {
127
127
  const payloadMatch = toJsonSerializable(assertion.payloadMatch);
128
128
  if (payloadMatch === undefined) {
129
129
  return undefined;
130
130
  }
131
- projected['payloadMatch'] = payloadMatch;
131
+ derived['payloadMatch'] = payloadMatch;
132
132
  }
133
133
  if (assertion.times !== undefined) {
134
- projected['times'] = assertion.times;
134
+ derived['times'] = assertion.times;
135
135
  }
136
136
  return Object.freeze(
137
- projected
137
+ derived
138
138
  ) as unknown as StructuredTrailExampleSignalAssertion;
139
139
  };
140
140
 
141
- const projectSignalAssertions = (
141
+ const deriveSignalAssertions = (
142
142
  assertions: readonly TrailExampleSignalAssertion[] | undefined
143
143
  ): readonly StructuredTrailExampleSignalAssertion[] | undefined => {
144
144
  if (assertions === undefined) {
145
145
  return undefined;
146
146
  }
147
- const projected = assertions.map(projectSignalAssertion);
148
- if (projected.some((assertion) => assertion === undefined)) {
147
+ const derived = assertions.map(deriveSignalAssertion);
148
+ if (derived.some((assertion) => assertion === undefined)) {
149
149
  return undefined;
150
150
  }
151
- return Object.freeze(projected as StructuredTrailExampleSignalAssertion[]);
151
+ return Object.freeze(derived as StructuredTrailExampleSignalAssertion[]);
152
152
  };
153
153
 
154
- const projectExample = (
154
+ const deriveExample = (
155
155
  example: TrailExample<unknown, unknown>,
156
156
  provenance: StructuredTrailExampleProvenance
157
157
  ): StructuredTrailExample | undefined => {
@@ -160,7 +160,7 @@ const projectExample = (
160
160
  return undefined;
161
161
  }
162
162
 
163
- const projected: Record<string, unknown> = {
163
+ const derived: Record<string, unknown> = {
164
164
  input,
165
165
  kind: example.error === undefined ? 'success' : 'error',
166
166
  name: example.name,
@@ -168,37 +168,37 @@ const projectExample = (
168
168
  };
169
169
 
170
170
  if (example.description !== undefined) {
171
- projected['description'] = example.description;
171
+ derived['description'] = example.description;
172
172
  }
173
173
  if (example.expected !== undefined) {
174
174
  const expected = toJsonSerializable(example.expected);
175
175
  if (expected === undefined) {
176
176
  return undefined;
177
177
  }
178
- projected['expected'] = expected;
178
+ derived['expected'] = expected;
179
179
  }
180
180
  if (example.expectedMatch !== undefined) {
181
181
  const expectedMatch = toJsonSerializable(example.expectedMatch);
182
182
  if (expectedMatch === undefined) {
183
183
  return undefined;
184
184
  }
185
- projected['expectedMatch'] = expectedMatch;
185
+ derived['expectedMatch'] = expectedMatch;
186
186
  }
187
187
  if (example.error !== undefined) {
188
- projected['error'] = example.error;
188
+ derived['error'] = example.error;
189
189
  }
190
190
  if (example.signals !== undefined) {
191
- const signals = projectSignalAssertions(example.signals);
191
+ const signals = deriveSignalAssertions(example.signals);
192
192
  if (signals === undefined) {
193
193
  return undefined;
194
194
  }
195
- projected['signals'] = signals;
195
+ derived['signals'] = signals;
196
196
  }
197
197
 
198
- return Object.freeze(projected) as unknown as StructuredTrailExample;
198
+ return Object.freeze(derived) as unknown as StructuredTrailExample;
199
199
  };
200
200
 
201
- const projectSignalExample = (
201
+ const deriveSignalExample = (
202
202
  payload: unknown
203
203
  ): StructuredSignalExample | undefined => {
204
204
  const serializablePayload = toJsonSerializable(payload);
@@ -222,13 +222,13 @@ export const deriveStructuredTrailExamples = (
222
222
  }
223
223
 
224
224
  const provenance = options?.provenance ?? { source: 'trail.examples' };
225
- const projected = examples
226
- .map((example) => projectExample(example, provenance))
225
+ const derived = examples
226
+ .map((example) => deriveExample(example, provenance))
227
227
  .filter(
228
228
  (example): example is StructuredTrailExample => example !== undefined
229
229
  );
230
230
 
231
- return projected.length > 0 ? Object.freeze(projected) : undefined;
231
+ return derived.length > 0 ? Object.freeze(derived) : undefined;
232
232
  };
233
233
 
234
234
  export const deriveStructuredSignalExamples = (
@@ -238,11 +238,11 @@ export const deriveStructuredSignalExamples = (
238
238
  return undefined;
239
239
  }
240
240
 
241
- const projected = examples
242
- .map(projectSignalExample)
241
+ const derived = examples
242
+ .map(deriveSignalExample)
243
243
  .filter(
244
244
  (example): example is StructuredSignalExample => example !== undefined
245
245
  );
246
246
 
247
- return projected.length > 0 ? Object.freeze(projected) : undefined;
247
+ return derived.length > 0 ? Object.freeze(derived) : undefined;
248
248
  };
@@ -21,7 +21,7 @@ export interface SurfaceSelectionOptions {
21
21
  }
22
22
 
23
23
  export interface SurfaceValidationOptions {
24
- /** Set to `false` to skip established-topo validation during projection. */
24
+ /** Set to `false` to skip established-topo validation during derivation. */
25
25
  readonly validate?: boolean | undefined;
26
26
  }
27
27
 
@@ -33,7 +33,7 @@ export const SURFACES_OVERLAY_NAMESPACE = 'surfaces' as const;
33
33
  /**
34
34
  * Who authored an overlay envelope.
35
35
  *
36
- * `'adapter-derived'` marks facts an adapter projects from the topo;
36
+ * `'adapter-derived'` marks facts an adapter renders from the topo;
37
37
  * `'app-authored'` marks bindings the app wrote by hand. Surfaces obey
38
38
  * app-authored overlays only — adapters contribute facts, never bindings.
39
39
  *
@@ -242,7 +242,7 @@ export interface SurfaceOverlay {
242
242
  /** The bindings schema, enforced again on the compile path. */
243
243
  readonly schema: z.ZodType;
244
244
  /**
245
- * Project the overlay facts. Ignores the topo — bindings are authored —
245
+ * Derive the overlay facts. Ignores the topo — bindings are authored —
246
246
  * so the parameter is optional; the signature stays structurally
247
247
  * assignable to the adapter-kit `Overlay` contract's `(topo) => unknown`.
248
248
  */
@@ -313,7 +313,7 @@ export interface OverlayEnvelopeLike {
313
313
  readonly provenance?: OverlayProvenance | undefined;
314
314
  /** The envelope's fact schema. */
315
315
  readonly schema: z.ZodType;
316
- /** Project the envelope's facts. */
316
+ /** Derive the envelope's facts. */
317
317
  derive(topo?: Topo): unknown;
318
318
  /**
319
319
  * Static surface bindings, when the envelope carries them directly.
@@ -575,11 +575,11 @@ const assertMcpSynonymBindingName = (name: string): void => {
575
575
 
576
576
  /**
577
577
  * Derive the deterministic default description for an MCP grouped entry
578
- * projected from the `surfaces` overlay.
578
+ * rendered from the `surfaces` overlay.
579
579
  *
580
580
  * Both the MCP surface (the runtime tool description) and Topography (the
581
581
  * lock's trailhead entry description) read this helper, so the authored
582
- * binding projects one description everywhere.
582
+ * binding renders one description everywhere.
583
583
  *
584
584
  * @example
585
585
  * ```ts
@@ -5,7 +5,7 @@ import {
5
5
  } from './trail.js';
6
6
  import { deriveTrailVersionMarkers } from './version-marker.js';
7
7
 
8
- export interface SurfaceTrailVersionProjection {
8
+ export interface SurfaceTrailVersionRendering {
9
9
  readonly current: boolean;
10
10
  readonly deprecated: boolean;
11
11
  readonly marker?: string | undefined;
@@ -13,9 +13,9 @@ export interface SurfaceTrailVersionProjection {
13
13
  readonly version: number;
14
14
  }
15
15
 
16
- export const deriveSurfaceTrailVersionProjections = (
16
+ export const deriveSurfaceTrailVersionRenderings = (
17
17
  trail: AnyTrail
18
- ): readonly SurfaceTrailVersionProjection[] | undefined => {
18
+ ): readonly SurfaceTrailVersionRendering[] | undefined => {
19
19
  if (trail.version === undefined) {
20
20
  return undefined;
21
21
  }
package/src/tracing.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * This module is the home for the trace record type, the sink interface,
5
5
  * the sink registry, and the helpers `executeTrail` uses to create root
6
6
  * trace records and child spans. Core keeps this minimal contract public so
7
- * `@ontrails/observe`, `@ontrails/tracing`, adapters, and tests share the
7
+ * `@ontrails/observability`, adapters, and tests share the
8
8
  * same intrinsic execution record shape.
9
9
  *
10
10
  * Tracing is intrinsic: every `executeTrail` call automatically produces a
@@ -58,8 +58,8 @@ export interface TraceRecord {
58
58
  /**
59
59
  * Minimal shape a tracing sink must satisfy.
60
60
  *
61
- * Kept intentionally tiny so adapters in `@ontrails/tracing`,
62
- * `@ontrails/observe`, and user code can all satisfy it without
61
+ * Kept intentionally tiny so adapters in `@ontrails/observability`,
62
+ * `@ontrails/observability`, and user code can all satisfy it without
63
63
  * additional dependencies.
64
64
  */
65
65
  export interface TraceSink {
package/src/trail.ts CHANGED
@@ -15,7 +15,7 @@ import type { AnyEntity } from './entity.js';
15
15
  import type {
16
16
  FieldOverride,
17
17
  CliCommandPathInput,
18
- TrailCliProjection,
18
+ TrailCliRendering,
19
19
  } from './derive.js';
20
20
  import type { Layer } from './layer.js';
21
21
  import type { Result } from './result.js';
@@ -504,13 +504,13 @@ export interface TrailSpec<
504
504
  * `topo → surface → trail → implementation` (outermost-first).
505
505
  *
506
506
  * Layers are typed and inspectable. Omit `input` for surface-invisible
507
- * wrappers that do not project any fields.
507
+ * wrappers that do not render any fields.
508
508
  */
509
509
  readonly layers?: readonly Layer[] | undefined;
510
510
  /** Per-field overrides for deriveFields() (labels, hints, options) */
511
511
  readonly fields?: Readonly<Record<string, FieldOverride>> | undefined;
512
- /** CLI projection metadata for canonical command path overrides and aliases. */
513
- readonly cli?: CliCommandPathInput | TrailCliProjection | undefined;
512
+ /** CLI rendering metadata for canonical command path overrides and aliases. */
513
+ readonly cli?: CliCommandPathInput | TrailCliRendering | undefined;
514
514
  /** Entities this trail operates on. */
515
515
  readonly entities?: readonly AnyEntity[] | undefined;
516
516
  /** IDs or trail objects of downstream trails this trail may invoke via ctx.compose() */
@@ -548,13 +548,13 @@ export interface TrailSpec<
548
548
  | undefined;
549
549
  /** Auth requirement: scopes object, 'public', or omitted (undeclared) */
550
550
  readonly permit?: PermitRequirement | undefined;
551
- /** Primary input fields and their order. CLI projects as positional args. */
551
+ /** Primary input fields and their order. CLI derives as positional args. */
552
552
  readonly args?: readonly string[] | false | undefined;
553
553
  /** Current trail version number. Omit for current-only unversioned trails. */
554
554
  readonly version?: number | undefined;
555
555
  /** Explicit historical trail versions. Current stays top-level. */
556
556
  readonly versions?: TrailVersions<I, O> | undefined;
557
- /** Version markers are projected into the resolved graph, not authored. */
557
+ /** Version markers are derived into the resolved graph, not authored. */
558
558
  readonly marker?: never;
559
559
  }
560
560
 
@@ -976,12 +976,12 @@ const normalizeVersionEntry = <CurrentInput, CurrentOutput>(
976
976
 
977
977
  if (hasOwn(raw, 'kind')) {
978
978
  throw new ValidationError(
979
- `Trail "${trailId}" version ${version} must not author kind; it is projected`
979
+ `Trail "${trailId}" version ${version} must not author kind; it is derived`
980
980
  );
981
981
  }
982
982
  if (hasOwn(raw, 'marker')) {
983
983
  throw new ValidationError(
984
- `Trail "${trailId}" version ${version} must not author marker; it is projected`
984
+ `Trail "${trailId}" version ${version} must not author marker; it is derived`
985
985
  );
986
986
  }
987
987
 
@@ -1286,7 +1286,7 @@ export function trail<
1286
1286
 
1287
1287
  if (hasOwn(rawSpec, 'marker')) {
1288
1288
  throw new ValidationError(
1289
- `Trail "${resolved.id}" must not author marker; it is projected`
1289
+ `Trail "${resolved.id}" must not author marker; it is derived`
1290
1290
  );
1291
1291
  }
1292
1292
 
@@ -760,7 +760,7 @@ const synthesizeDefaultImplementation = <
760
760
  };
761
761
 
762
762
  /**
763
- * Mechanically project one CRUD-shaped trail from a entity declaration.
763
+ * Mechanically derive one CRUD-shaped trail from a entity declaration.
764
764
  *
765
765
  * When `spec.implementation` is omitted and the call declares a single resource, the
766
766
  * helper derives a default implementation that dispatches to the resource accessor
@@ -9,14 +9,12 @@ import {
9
9
  codesByCategory,
10
10
  errorClasses,
11
11
  exitCodeMap,
12
- isTrailsError,
13
12
  jsonRpcCodeMap,
14
13
  statusCodeMap,
15
14
  } from './errors.js';
16
- import {
17
- INTERNAL_ERROR_PUBLIC_MESSAGE,
18
- redactErrorString,
19
- } from './error-projection.js';
15
+ import { renderPublicError } from './error-rendering.js';
16
+
17
+ const CLI_INTERNAL_ERROR_PUBLIC_MESSAGE = 'Internal error';
20
18
 
21
19
  export const surfaceNames = ['cli', 'http', 'jsonRpc', 'mcp'] as const;
22
20
 
@@ -48,7 +46,7 @@ export type SurfaceErrorMappings<T> = Record<ErrorCategory, T>;
48
46
  export type SurfaceErrorCode =
49
47
  (typeof codesByCategory)[ErrorCategory][(typeof surfaceCodeKeys)[SurfaceName]];
50
48
 
51
- export interface SurfaceErrorProjection {
49
+ export interface SurfaceErrorRendering {
52
50
  readonly category: ErrorCategory;
53
51
  readonly code: SurfaceErrorCode;
54
52
  readonly message: string;
@@ -57,7 +55,7 @@ export interface SurfaceErrorProjection {
57
55
  readonly surface: SurfaceName;
58
56
  }
59
57
 
60
- export interface ErrorClassSurfaceProjection {
58
+ export interface ErrorClassSurfaceRendering {
61
59
  readonly category: ErrorCategory;
62
60
  readonly code: SurfaceErrorCode;
63
61
  readonly name: string;
@@ -102,10 +100,10 @@ export const mapSurfaceError = (
102
100
  ): SurfaceErrorCode =>
103
101
  codesByCategory[error.category][surfaceCodeKeys[surface]];
104
102
 
105
- export const projectSurfaceError = (
103
+ export const renderSurfaceError = (
106
104
  surface: SurfaceName,
107
105
  error: TrailsError
108
- ): SurfaceErrorProjection => ({
106
+ ): SurfaceErrorRendering => ({
109
107
  category: error.category,
110
108
  code: mapSurfaceError(surface, error),
111
109
  message: error.message,
@@ -114,27 +112,18 @@ export const projectSurfaceError = (
114
112
  surface,
115
113
  });
116
114
 
117
- export const projectPublicSurfaceError = (
115
+ export const renderPublicSurfaceError = (
118
116
  surface: SurfaceName,
119
117
  error: Error
120
- ): SurfaceErrorProjection => {
121
- if (isTrailsError(error)) {
122
- const projection = projectSurfaceError(surface, error);
123
- return {
124
- ...projection,
125
- message:
126
- projection.category === 'internal'
127
- ? INTERNAL_ERROR_PUBLIC_MESSAGE
128
- : redactErrorString(projection.message),
129
- };
130
- }
131
-
118
+ ): SurfaceErrorRendering => {
119
+ const rendering = renderPublicError(error);
132
120
  return {
133
- category: 'internal',
134
- code: codesByCategory.internal[surfaceCodeKeys[surface]],
135
- message: INTERNAL_ERROR_PUBLIC_MESSAGE,
136
- name: 'InternalError',
137
- retryable: false,
121
+ ...rendering,
122
+ code: codesByCategory[rendering.category][surfaceCodeKeys[surface]],
123
+ message:
124
+ surface === 'cli' && rendering.category === 'internal'
125
+ ? CLI_INTERNAL_ERROR_PUBLIC_MESSAGE
126
+ : rendering.message,
138
127
  surface,
139
128
  };
140
129
  };
@@ -151,15 +140,15 @@ const fixedErrorClassByName: ReadonlyMap<string, FixedErrorClassRegistryEntry> =
151
140
  );
152
141
 
153
142
  /**
154
- * Project a known error class name onto a surface without constructing it.
143
+ * Render a known error class name onto a surface without constructing it.
155
144
  *
156
145
  * Dynamic-category errors such as `RetryExhaustedError` return `undefined`
157
146
  * because their surface code depends on the wrapped runtime error.
158
147
  */
159
- export const projectErrorClassSurface = (
148
+ export const renderErrorClassSurface = (
160
149
  surface: SurfaceName,
161
150
  errorName: string
162
- ): ErrorClassSurfaceProjection | undefined => {
151
+ ): ErrorClassSurfaceRendering | undefined => {
163
152
  const entry = fixedErrorClassByName.get(errorName);
164
153
  if (entry === undefined) {
165
154
  return undefined;
package/src/types.ts CHANGED
@@ -215,13 +215,13 @@ export const SURFACE_LAYER_NAMES_KEY = '__trails_surface_layer_names' as const;
215
215
  /**
216
216
  * Context extension key carrying per-layer runtime input.
217
217
  *
218
- * Surfaces (CLI, MCP, HTTP) project each typed layer's `input` schema onto
218
+ * Surfaces (CLI, MCP, HTTP) render each typed layer's `input` schema onto
219
219
  * their native idioms (flags, tool params, query strings). At execute time
220
220
  * the parsed values are partitioned per layer and stored under this key as
221
221
  * `Record<layerName, unknown>`. Layers that need runtime input read their
222
222
  * own slot via `ctx.extensions?.[LAYER_INPUTS_KEY]?.[layer.name]`.
223
223
  *
224
- * @see TRL-473 for the CLI projection contract.
224
+ * @see TRL-473 for the CLI derivation contract.
225
225
  */
226
226
  export const LAYER_INPUTS_KEY = '__trails_layer_inputs' as const;
227
227
 
@@ -5,7 +5,7 @@ import { validateDraftFreeTopo } from './draft.js';
5
5
  import type { TopoDiagnostic } from './validate-topo.js';
6
6
  import { validateTopo } from './validate-topo.js';
7
7
 
8
- const PROJECTION_BLOCKING_RULES = new Set([
8
+ const DERIVATION_BLOCKING_RULES = new Set([
9
9
  'compose-cycle',
10
10
  'compose-exists',
11
11
  'no-self-compose',
@@ -20,12 +20,12 @@ const PROJECTION_BLOCKING_RULES = new Set([
20
20
  'signal-origin-exists',
21
21
  ]);
22
22
 
23
- const isProjectionBlockingIssue = (issue: TopoDiagnostic): boolean =>
24
- PROJECTION_BLOCKING_RULES.has(issue.rule) ||
23
+ const isDerivationBlockingIssue = (issue: TopoDiagnostic): boolean =>
24
+ DERIVATION_BLOCKING_RULES.has(issue.rule) ||
25
25
  (issue.rule === 'activation-source-input-compatible' &&
26
26
  issue.sourceKind === 'queue');
27
27
 
28
- const keepProjectionBlockingIssues = (
28
+ const keepDerivationBlockingIssues = (
29
29
  result: ReturnType<typeof validateTopo>
30
30
  ) => {
31
31
  if (result.isOk()) {
@@ -35,7 +35,7 @@ const keepProjectionBlockingIssues = (
35
35
  const issues = (
36
36
  result.error.context as { issues?: readonly TopoDiagnostic[] } | undefined
37
37
  )?.issues;
38
- const remainingIssues = issues?.filter(isProjectionBlockingIssue);
38
+ const remainingIssues = issues?.filter(isDerivationBlockingIssue);
39
39
 
40
40
  if (remainingIssues === undefined || remainingIssues.length === 0) {
41
41
  return Result.ok();
@@ -59,7 +59,7 @@ const keepProjectionBlockingIssues = (
59
59
  * valid, and they must also reject any remaining draft state.
60
60
  */
61
61
  export const validateEstablishedTopo = (topo: Topo) => {
62
- const structural = keepProjectionBlockingIssues(validateTopo(topo));
62
+ const structural = keepDerivationBlockingIssues(validateTopo(topo));
63
63
  if (structural.isErr()) {
64
64
  return structural;
65
65
  }
@@ -11,7 +11,7 @@ import { getActivationSourceInputCompatibilityIssues } from './activation-source
11
11
  import {
12
12
  activationSourceDeclarationSignature,
13
13
  activationSourceKey,
14
- } from './activation-source-projection.js';
14
+ } from './activation-source-derivation.js';
15
15
  import type { AnyEntity } from './entity.js';
16
16
  import { getEntityReferences } from './entity.js';
17
17
  import { ValidationError } from './errors.js';
package/src/validation.ts CHANGED
@@ -84,9 +84,9 @@ const getSchemaJsonSchemaOverride = (
84
84
  };
85
85
 
86
86
  /**
87
- * Whether a schema has a deterministic JSON-schema override projection (for
87
+ * Whether a schema has a deterministic JSON-schema override derivation (for
88
88
  * example `blobRefSchema`, a `z.custom(...)` carrying the descriptor metadata).
89
- * Such schemas project to a canonical descriptor regardless of their underlying
89
+ * Such schemas derive to a canonical descriptor regardless of their underlying
90
90
  * Zod internals, so marker derivation can treat them as supported.
91
91
  */
92
92
  export const schemaHasJsonSchemaOverride = (schema: z.ZodType): boolean =>