@ontrails/topography 1.0.0-beta.41 → 1.0.0-beta.43

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/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @ontrails/topography
2
2
 
3
+ ## 1.0.0-beta.43
4
+
5
+ ### Minor Changes
6
+
7
+ - [`88a6a62`](https://github.com/outfitter-dev/trails/commit/88a6a62a9e9e230ca6d368fa78dc3ece6c816204): Complete the v1 classification-first cutover from projection/project vocabulary
8
+ to derive/derived for contract-owned fact production and render/rendered for
9
+ surface presentation. Public type, helper, rule, relation, and report names move
10
+ without compatibility aliases; ordinary repository/project nouns remain
11
+ explicit preserves or structured review inventory.
12
+
13
+ ### Patch Changes
14
+
15
+ - [`9f0842e`](https://github.com/outfitter-dev/trails/commit/9f0842ee9d7c7155d86a4fd023760ac0a5636f5d): Retire the temporary root vocabulary-cutover toolchain now that Regrade owns
16
+ structured migration plans, safe rewrites, classification, census, CLI/MCP
17
+ reports, and immutable history. Remove the obsolete source exemptions so
18
+ Oxlint and Warden enforce the durable transition contract directly, and add a
19
+ history-driven Regrade audit surface for current-tree regression checks.
20
+
21
+ ## 1.0.0-beta.42
22
+
3
23
  ## 1.0.0-beta.41
4
24
 
5
25
  ## 1.0.0-beta.40
package/README.md CHANGED
@@ -20,7 +20,7 @@ This is not a private helper package. The Trails operator app consumes Topograph
20
20
  ## What it owns
21
21
 
22
22
  - deterministic TopoGraph generation from an established topo
23
- - structured example and field-override provenance projection for TopoGraph entries
23
+ - structured example and field-override provenance derivation for TopoGraph entries
24
24
  - stable hashing for CI drift detection
25
25
  - semantic diffing between two TopoGraphs
26
26
  - file I/O helpers for root `trails.lock` plus legacy artifact-family readers
@@ -91,11 +91,11 @@ Compatibility helpers still read the previous `.trails/trails.lock` plus `.trail
91
91
  | `readTopoGraph(options?)` | Read a TopoGraph from v4 `trails.lock` or legacy `topo.lock` |
92
92
  | `writeTopoGraph(topoGraph, options?)` | Write legacy `topo.lock` for explicit migration/testing paths |
93
93
  | `writeLockManifest(manifest, options?)` | Write legacy `trails.lock` as a v3 manifest |
94
- | `readLockManifest(options?)` | Read v3 manifests, projecting v4 locks back to v3 for compatibility |
94
+ | `readLockManifest(options?)` | Read v3 manifests, deriving v4 locks back to v3 for compatibility |
95
95
  | `createTopoStore(options?)` | Read-only query interface over the persisted topo state in the Trails state-store `trails.db` |
96
96
  | `createMockTopoStore(seed?)` | Seeded in-memory mock for tests that need a `ReadOnlyTopoStore` |
97
97
  | `topoStore` | Read-only `resource()` wrapper around `createTopoStore`, suitable for `resources: [...]` |
98
- | `createTopoSnapshot(topo, options?)` | Persist a new topo snapshot row plus its denormalized projections |
98
+ | `createTopoSnapshot(topo, options?)` | Persist a new topo snapshot row plus its denormalized derived facts |
99
99
  | `listTopoSnapshots(options?)` | List historical topo snapshots (filterable by pinned status) |
100
100
  | `pinTopoSnapshot(id, name, options?)` / `unpinTopoSnapshot(nameOrId, options?)` | Manage human-named pins |
101
101
 
@@ -132,7 +132,7 @@ Wayfind trails are internal by default. Surface hosts expose selected query trai
132
132
 
133
133
  ### Operator File Outline
134
134
 
135
- File outline is an operator capability, not a public Topographer query trail. Use `trails wayfind file <file> --outline` for a compact map of authored trail and app declarations, surface membership, saved graph matches, and diagnostics. Add `--source` when the inspection also needs import, export, and declaration rows. The operator parses the explicit file through `@ontrails/source` and reconciles trail IDs with saved Topographer artifacts. Missing artifacts are diagnostics, not hard failures, so outline remains useful in a fresh checkout or during repair work.
135
+ File outline is an operator capability, not a public Topography query trail. Use `trails wayfind file <file> --outline` for a compact map of authored trail and app declarations, surface membership, saved graph matches, and diagnostics. Add `--source` when the inspection also needs import, export, and declaration rows. The operator parses the explicit file through `@ontrails/source` and reconciles trail IDs with saved Topography artifacts. Missing artifacts are diagnostics, not hard failures, so outline remains useful in a fresh checkout or during repair work.
136
136
 
137
137
  ### Backend Support Subpath
138
138
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ontrails/topography",
3
- "version": "1.0.0-beta.41",
3
+ "version": "1.0.0-beta.43",
4
4
  "description": "Durable graph substrate for Trails: deterministic TopoGraphs, lockfile helpers, and semantic diffing.",
5
5
  "files": [
6
6
  "src/**/*.ts",
@@ -24,10 +24,10 @@
24
24
  "clean": "rm -rf dist *.tsbuildinfo"
25
25
  },
26
26
  "dependencies": {
27
- "@ontrails/adapter-kit": "^1.0.0-beta.41"
27
+ "@ontrails/adapter-kit": "^1.0.0-beta.43"
28
28
  },
29
29
  "peerDependencies": {
30
- "@ontrails/core": "^1.0.0-beta.41",
30
+ "@ontrails/core": "^1.0.0-beta.43",
31
31
  "zod": "^4.3.5"
32
32
  }
33
33
  }
@@ -1,13 +1,13 @@
1
1
  import type {
2
2
  ActivationEntry,
3
3
  ActivationSource,
4
- ActivationSourceProjection,
4
+ ActivationSourceFacts,
5
5
  AnyTrail,
6
6
  Topo,
7
7
  } from '@ontrails/core';
8
8
  import {
9
9
  activationSourceKey,
10
- projectActivationSourceDeclaration,
10
+ deriveActivationSourceFacts,
11
11
  } from '@ontrails/core';
12
12
 
13
13
  export interface ActivationChainReport {
@@ -18,7 +18,7 @@ export interface ActivationChainReport {
18
18
 
19
19
  type JsonSchemaReport = Readonly<Record<string, unknown>>;
20
20
 
21
- export interface ActivationSourceReport extends ActivationSourceProjection {
21
+ export interface ActivationSourceReport extends ActivationSourceFacts {
22
22
  readonly cron?: string | undefined;
23
23
  readonly hasParse?: true | undefined;
24
24
  readonly hasPayloadSchema?: true | undefined;
@@ -153,12 +153,12 @@ const compareChains = (
153
153
  const sortedUnique = (values: Iterable<string>): readonly string[] =>
154
154
  [...new Set(values)].toSorted();
155
155
 
156
- const projectActivationSource = (
156
+ const deriveActivationSource = (
157
157
  source: ActivationSource
158
158
  ): ActivationSourceReport =>
159
- projectActivationSourceDeclaration(source) as ActivationSourceReport;
159
+ deriveActivationSourceFacts(source) as ActivationSourceReport;
160
160
 
161
- const projectActivationEdge = (
161
+ const deriveActivationEdge = (
162
162
  trailId: string,
163
163
  activation: ActivationEntry
164
164
  ): ActivationEdgeReport => {
@@ -187,8 +187,8 @@ const collectActivationSourceCatalog = (
187
187
  const sources = new Map<string, ActivationSourceReport>();
188
188
  for (const trail of trails) {
189
189
  for (const activation of trail.activationSources) {
190
- const projected = projectActivationSource(activation.source);
191
- sources.set(projected.key, projected);
190
+ const derived = deriveActivationSource(activation.source);
191
+ sources.set(derived.key, derived);
192
192
  }
193
193
  }
194
194
  return [...sources.values()].toSorted((a, b) => a.key.localeCompare(b.key));
@@ -200,7 +200,7 @@ const collectActivationEdges = (
200
200
  const edges = new Map<string, ActivationEdgeReport>();
201
201
  for (const trail of trails) {
202
202
  for (const activation of trail.activationSources) {
203
- const edge = projectActivationEdge(trail.id, activation);
203
+ const edge = deriveActivationEdge(trail.id, activation);
204
204
  const key = `${edge.sourceKey}\0${edge.trailId}`;
205
205
  const previous = edges.get(key);
206
206
  edges.set(
package/src/derive.ts CHANGED
@@ -7,9 +7,9 @@ import {
7
7
  activationSourceKey,
8
8
  deriveStructuredSignalExamples,
9
9
  deriveStructuredTrailExamples,
10
- deriveTrailCliCommandProjection,
10
+ deriveTrailCliCommandRendering,
11
11
  getEntityReferences,
12
- projectActivationSourceDeclaration,
12
+ deriveActivationSourceFacts,
13
13
  validateEstablishedTopo,
14
14
  signalDiagnosticDefinitions,
15
15
  zodToJsonSchema,
@@ -28,14 +28,14 @@ import type {
28
28
  } from '@ontrails/core';
29
29
 
30
30
  import { addPermitRequirement } from './permit.js';
31
- import { collectLibraryProjection } from './library-projection.js';
31
+ import { deriveTopoGraphLibrary } from './library-derivation.js';
32
32
  import { collectTopoGraphOverlays } from './overlays.js';
33
33
  import {
34
34
  resolveCliAliasInputsFromOverlays,
35
35
  resolveTrailheadEntriesFromOverlays,
36
36
  } from './surface-bindings.js';
37
37
  import { TOPO_GRAPH_SCHEMA_VERSION } from './types.js';
38
- import { projectTrailVersions } from './versioning.js';
38
+ import { deriveTrailVersions } from './versioning.js';
39
39
  import type {
40
40
  DeriveTopoGraphOptions,
41
41
  JsonSchema,
@@ -156,12 +156,12 @@ const SIGNAL_GOVERNANCE_HOOKS = {
156
156
  producers: 'trail.fires',
157
157
  } as const;
158
158
 
159
- const projectActivationSource = (
159
+ const deriveActivationSource = (
160
160
  source: ActivationSource
161
161
  ): TopoGraphActivationSource =>
162
- projectActivationSourceDeclaration(source) as TopoGraphActivationSource;
162
+ deriveActivationSourceFacts(source) as TopoGraphActivationSource;
163
163
 
164
- const projectActivationEdge = (
164
+ const deriveActivationEdge = (
165
165
  trailId: string,
166
166
  activation: ActivationEntry
167
167
  ): TopoGraphActivationEdge => {
@@ -190,8 +190,8 @@ const collectActivationSourceCatalog = (
190
190
  const sources = new Map<string, TopoGraphActivationSource>();
191
191
  for (const trail of topo.trails.values()) {
192
192
  for (const activation of trail.activationSources) {
193
- const projected = projectActivationSource(activation.source);
194
- sources.set(projected.key, projected);
193
+ const derived = deriveActivationSource(activation.source);
194
+ sources.set(derived.key, derived);
195
195
  }
196
196
  }
197
197
  return [...sources.values()].toSorted((a, b) => a.key.localeCompare(b.key));
@@ -203,7 +203,7 @@ const collectActivationGraphEdges = (
203
203
  const edges = new Map<string, TopoGraphActivationEdge>();
204
204
  for (const trail of topo.trails.values()) {
205
205
  for (const activation of trail.activationSources) {
206
- const edge = projectActivationEdge(trail.id, activation);
206
+ const edge = deriveActivationEdge(trail.id, activation);
207
207
  const key = `${edge.sourceKey}\0${edge.trailId}`;
208
208
  const previous = edges.get(key);
209
209
  edges.set(
@@ -359,7 +359,7 @@ const addTrailRelations = (
359
359
  ...(activation.meta === undefined
360
360
  ? {}
361
361
  : { meta: canonicalize(activation.meta) }),
362
- source: projectActivationSource(activation.source),
362
+ source: deriveActivationSource(activation.source),
363
363
  ...(activation.where === undefined
364
364
  ? {}
365
365
  : { where: sortKeys({ predicate: true }) }),
@@ -482,16 +482,16 @@ const addVersioning = (
482
482
  if (t.version === undefined) {
483
483
  return;
484
484
  }
485
- const projection = projectTrailVersions(t, toSortedJsonSchema);
486
- if (projection === undefined) {
485
+ const derivation = deriveTrailVersions(t, toSortedJsonSchema);
486
+ if (derivation === undefined) {
487
487
  return;
488
488
  }
489
489
 
490
- entry['marker'] = projection.marker;
491
- entry['supports'] = projection.supports;
492
- entry['version'] = projection.version;
493
- if (projection.versions !== undefined) {
494
- entry['versions'] = projection.versions;
490
+ entry['marker'] = derivation.marker;
491
+ entry['supports'] = derivation.supports;
492
+ entry['version'] = derivation.version;
493
+ if (derivation.versions !== undefined) {
494
+ entry['versions'] = derivation.versions;
495
495
  }
496
496
  };
497
497
 
@@ -503,7 +503,7 @@ const trailToEntry = (
503
503
  const raw = t as unknown as Record<string, unknown>;
504
504
  const surfaces = extractSurfaces(raw);
505
505
  const entry: Record<string, unknown> = {
506
- cli: deriveTrailCliCommandProjection(t, {
506
+ cli: deriveTrailCliCommandRendering(t, {
507
507
  aliasSource: 'surface',
508
508
  aliases: surfaceAliases?.[t.id],
509
509
  }),
@@ -673,7 +673,7 @@ export const deriveTopoGraph = (
673
673
  options?.overlays
674
674
  );
675
675
  const overlays = collectTopoGraphOverlays(topo, options?.overlays);
676
- const library = collectLibraryProjection(topo);
676
+ const library = deriveTopoGraphLibrary(topo);
677
677
 
678
678
  return {
679
679
  activationGraph: buildActivationGraph(activationEdges, activationSources),
package/src/index.ts CHANGED
@@ -61,7 +61,7 @@ export {
61
61
  TRAILS_LOCK_SCHEMA_VERSION,
62
62
  trailsLockSchema,
63
63
  topoGraphTrailheadEntrySchema,
64
- topoGraphLibraryProjectionSchema,
64
+ topoGraphLibraryDerivedSchema,
65
65
  workspaceTopoMetadataSchema,
66
66
  workspaceTrailCollisionSchema,
67
67
  workspaceTrailEntrySchema,
@@ -98,7 +98,7 @@ export type {
98
98
  TopoGraphLibraryExclusionReason,
99
99
  TopoGraphLibraryExport,
100
100
  TopoGraphLibraryExportSource,
101
- TopoGraphLibraryProjection,
101
+ TopoGraphLibraryDerived,
102
102
  TopoGraphLayerReference,
103
103
  TopoGraphOverlayRegistration,
104
104
  TopoGraphOverlays,
@@ -151,7 +151,7 @@ export type {
151
151
  TopoStoreRef,
152
152
  TopoStoreSignalDetailRecord,
153
153
  TopoStoreSignalRecord,
154
- TopoStoreSurfaceProjectionRecord,
154
+ TopoStoreSurfaceDerivedRecord,
155
155
  TopoStoreTopoGraphEntryRecord,
156
156
  TopoStoreTopoGraphRecord,
157
157
  TopoStoreTrailDetailRecord,
@@ -169,7 +169,7 @@ export type {
169
169
  TrailErrorFacts,
170
170
  TrailErrorFactsCompleteness,
171
171
  TrailErrorFactsOptions,
172
- TrailErrorTaxonomyProjection,
172
+ TrailErrorTaxonomyFacts,
173
173
  } from './wayfind/error-facts.js';
174
174
  export {
175
175
  createWayfinderEntityPredicate,
@@ -52,7 +52,7 @@ export interface TopoStoreActivationContextRecord {
52
52
  readonly trailIds: readonly string[];
53
53
  }
54
54
 
55
- export interface TopoStoreSurfaceProjectionRecord {
55
+ export interface TopoStoreSurfaceDerivedRecord {
56
56
  readonly derivedName: string;
57
57
  readonly method: string | null;
58
58
  readonly surface: string;
@@ -103,7 +103,7 @@ export interface TopoStoreTrailDetailRecord extends TopoStoreTrailRecord {
103
103
  readonly layers: readonly TopoGraphLayerReference[];
104
104
  readonly output: JsonSchema | null;
105
105
  readonly resources: readonly string[];
106
- readonly surfaceProjections: readonly TopoStoreSurfaceProjectionRecord[];
106
+ readonly derivedSurfaces: readonly TopoStoreSurfaceDerivedRecord[];
107
107
  readonly surfaces: readonly string[];
108
108
  }
109
109
 
@@ -175,7 +175,7 @@ interface TopoExampleRow {
175
175
  readonly signals: string | null;
176
176
  }
177
177
 
178
- interface TopoSurfaceProjectionRow {
178
+ interface TopoSurfaceDerivedRow {
179
179
  readonly derived_name: string;
180
180
  readonly method: string | null;
181
181
  readonly surface: string;
@@ -424,13 +424,13 @@ const readTrailExamples = (
424
424
  signals: row.signals === null ? null : parseJson(row.signals),
425
425
  }));
426
426
 
427
- const readTrailSurfaceProjections = (
427
+ const readTrailSurfaceDerived = (
428
428
  db: Database,
429
429
  snapshotId: string,
430
430
  trailId: string
431
- ): readonly TopoStoreSurfaceProjectionRecord[] =>
431
+ ): readonly TopoStoreSurfaceDerivedRecord[] =>
432
432
  db
433
- .query<TopoSurfaceProjectionRow, [string, string]>(
433
+ .query<TopoSurfaceDerivedRow, [string, string]>(
434
434
  `SELECT trail_id, surface, derived_name, method
435
435
  FROM topo_surfaces
436
436
  WHERE snapshot_id = ? AND trail_id = ?
@@ -567,7 +567,7 @@ const buildTrailGraphDetail = (
567
567
  | 'input'
568
568
  | 'layers'
569
569
  | 'output'
570
- | 'surfaceProjections'
570
+ | 'derivedSurfaces'
571
571
  | 'surfaces'
572
572
  > => {
573
573
  const storedTopoGraph = readStoredTopoGraph(db, snapshotId);
@@ -579,6 +579,7 @@ const buildTrailGraphDetail = (
579
579
  activationEdges: readTrailActivationEdges(storedTopoGraph, trailId),
580
580
  activationSources: entryDetail.activationSources,
581
581
  cli: entryDetail.cli,
582
+ derivedSurfaces: readTrailSurfaceDerived(db, snapshotId, trailId),
582
583
  detours: entryDetail.detours,
583
584
  entities: entryDetail.entities,
584
585
  entityDetails: readTrailEntityDetails(
@@ -591,7 +592,6 @@ const buildTrailGraphDetail = (
591
592
  input: entryDetail.input,
592
593
  layers: entryDetail.layers,
593
594
  output: entryDetail.output,
594
- surfaceProjections: readTrailSurfaceProjections(db, snapshotId, trailId),
595
595
  surfaces: entryDetail.surfaces,
596
596
  };
597
597
  };
@@ -871,6 +871,7 @@ export const getTopoStoreTrail = (
871
871
  activationSources: graphDetail.activationSources,
872
872
  cli: graphDetail.cli,
873
873
  composes: readTrailComposings(db, snapshot.id, trailId),
874
+ derivedSurfaces: graphDetail.derivedSurfaces,
874
875
  detours: graphDetail.detours,
875
876
  entities: graphDetail.entities,
876
877
  entityDetails: graphDetail.entityDetails,
@@ -881,7 +882,6 @@ export const getTopoStoreTrail = (
881
882
  layers: graphDetail.layers,
882
883
  output: graphDetail.output,
883
884
  resources: readTrailResourceIds(db, snapshot.id, trailId),
884
- surfaceProjections: graphDetail.surfaceProjections,
885
885
  surfaces: graphDetail.surfaces,
886
886
  };
887
887
  };
@@ -7,9 +7,9 @@ import {
7
7
  deriveCliPath,
8
8
  deriveStructuredSignalExamples,
9
9
  deriveStructuredTrailExamples,
10
- deriveTrailCliCommandProjection,
10
+ deriveTrailCliCommandRendering,
11
11
  getEntityReferences,
12
- projectActivationSourceDeclaration,
12
+ deriveActivationSourceFacts,
13
13
  signalDiagnosticDefinitions,
14
14
  validateEstablishedTopo,
15
15
  zodToJsonSchema,
@@ -28,7 +28,7 @@ import type {
28
28
  } from '@ontrails/core';
29
29
 
30
30
  import { addPermitRequirement } from '../permit.js';
31
- import { collectLibraryProjection } from '../library-projection.js';
31
+ import { deriveTopoGraphLibrary } from '../library-derivation.js';
32
32
  import { collectTopoGraphOverlays } from '../overlays.js';
33
33
  import {
34
34
  resolveCliAliasInputsFromOverlays,
@@ -39,12 +39,12 @@ import {
39
39
  LOCK_MANIFEST_SCHEMA_VERSION,
40
40
  TOPO_GRAPH_SCHEMA_VERSION,
41
41
  } from '../types.js';
42
- import { projectTrailVersions } from '../versioning.js';
42
+ import { deriveTrailVersions } from '../versioning.js';
43
43
  import type {
44
44
  LockManifest,
45
45
  TopoGraphFieldOverride,
46
46
  TopoGraphFieldOverrideKey,
47
- TopoGraphLibraryProjection,
47
+ TopoGraphLibraryDerived,
48
48
  TopoGraphOverlays,
49
49
  TopoGraphTrailheadEntry,
50
50
  } from '../types.js';
@@ -69,7 +69,7 @@ type TopoGraphRecord = Readonly<{
69
69
  >;
70
70
  readonly entries: readonly TopoGraphEntryRecord[];
71
71
  readonly generatedAt: string;
72
- readonly library: TopoGraphLibraryProjection;
72
+ readonly library: TopoGraphLibraryDerived;
73
73
  readonly overlays?: TopoGraphOverlays | undefined;
74
74
  readonly topoGraphSchemaVersion: typeof TOPO_GRAPH_SCHEMA_VERSION;
75
75
  readonly trailheads?: readonly TopoGraphTrailheadEntry[] | undefined;
@@ -268,7 +268,7 @@ const SIGNAL_GOVERNANCE_HOOKS = {
268
268
  producers: 'trail.fires',
269
269
  } as const;
270
270
 
271
- interface NormalizedTopoProjection {
271
+ interface NormalizedTopoFacts {
272
272
  readonly activationEdges: readonly TopoActivationEdgeRow[];
273
273
  readonly activationSources: readonly TopoActivationSourceRow[];
274
274
  readonly composings: readonly TopoComposingRow[];
@@ -450,12 +450,12 @@ export const normalizeOnRows = (
450
450
  }))
451
451
  );
452
452
 
453
- const projectActivationSource = (
453
+ const deriveActivationSource = (
454
454
  source: ActivationSource
455
455
  ): ActivationSourceCatalogRecord =>
456
- projectActivationSourceDeclaration(source) as ActivationSourceCatalogRecord;
456
+ deriveActivationSourceFacts(source) as ActivationSourceCatalogRecord;
457
457
 
458
- const projectActivationEdge = (
458
+ const deriveActivationEdge = (
459
459
  trailId: string,
460
460
  activation: ActivationEntry
461
461
  ): ActivationGraphEdgeRecord => {
@@ -484,8 +484,8 @@ const collectActivationSourceCatalog = (
484
484
  const sources = new Map<string, ActivationSourceCatalogRecord>();
485
485
  for (const trail of trails) {
486
486
  for (const activation of trail.activationSources) {
487
- const projected = projectActivationSource(activation.source);
488
- sources.set(projected.key, projected);
487
+ const derived = deriveActivationSource(activation.source);
488
+ sources.set(derived.key, derived);
489
489
  }
490
490
  }
491
491
  return [...sources.values()].toSorted((a, b) => a.key.localeCompare(b.key));
@@ -497,7 +497,7 @@ const collectActivationGraphEdges = (
497
497
  const edges = new Map<string, ActivationGraphEdgeRecord>();
498
498
  for (const trail of trails) {
499
499
  for (const activation of trail.activationSources) {
500
- const edge = projectActivationEdge(trail.id, activation);
500
+ const edge = deriveActivationEdge(trail.id, activation);
501
501
  const key = `${edge.sourceKey}\0${edge.trailId}`;
502
502
  const previous = edges.get(key);
503
503
  edges.set(
@@ -606,10 +606,10 @@ const normalizeTrailSignalRows = (
606
606
  });
607
607
 
608
608
  /**
609
- * Project surface rows for stored topo.
609
+ * Derive surface rows for stored topo.
610
610
  *
611
611
  * Currently records only CLI-derived rows. MCP, HTTP, and other surface
612
- * projections are intentionally deferred until the topo-store schema supports
612
+ * derivations are intentionally deferred until the topo-store schema supports
613
613
  * multi-surface representation. The JSON export (`topo_graph` in
614
614
  * `topo_exports`) is more faithful for now. See ADR-0015 for the target shape.
615
615
  */
@@ -657,10 +657,10 @@ const normalizeExampleRows = (
657
657
  }));
658
658
  });
659
659
 
660
- const normalizeTopoProjection = (
660
+ const deriveNormalizedTopoRows = (
661
661
  topo: Topo,
662
662
  snapshotId: string
663
- ): NormalizedTopoProjection => {
663
+ ): NormalizedTopoFacts => {
664
664
  const trails = topo.list().toSorted((a, b) => a.id.localeCompare(b.id));
665
665
  const resources = topo
666
666
  .listResources()
@@ -896,7 +896,7 @@ const addTrailRelations = (
896
896
  ...(activation.meta === undefined
897
897
  ? {}
898
898
  : { meta: canonicalize(activation.meta) }),
899
- source: projectActivationSource(activation.source),
899
+ source: deriveActivationSource(activation.source),
900
900
  ...(activation.where === undefined
901
901
  ? {}
902
902
  : { where: sortKeys({ predicate: true }) }),
@@ -1024,7 +1024,7 @@ const buildTrailEntryBase = (
1024
1024
  } => {
1025
1025
  const raw = trail as unknown as Record<string, unknown>;
1026
1026
  const entry: Record<string, unknown> = {
1027
- cli: deriveTrailCliCommandProjection(trail, {
1027
+ cli: deriveTrailCliCommandRendering(trail, {
1028
1028
  aliasSource: 'surface',
1029
1029
  aliases: surfaceAliases?.[trail.id],
1030
1030
  }),
@@ -1065,19 +1065,19 @@ const addVersioning = (
1065
1065
  if (trail.version === undefined) {
1066
1066
  return;
1067
1067
  }
1068
- const projection = projectTrailVersions(
1068
+ const derivation = deriveTrailVersions(
1069
1069
  trail,
1070
1070
  (schema) => sortedJsonSchema(schema as ZodSchemaInput).value
1071
1071
  );
1072
- if (projection === undefined) {
1072
+ if (derivation === undefined) {
1073
1073
  return;
1074
1074
  }
1075
1075
 
1076
- entry['marker'] = projection.marker;
1077
- entry['supports'] = projection.supports;
1078
- entry['version'] = projection.version;
1079
- if (projection.versions !== undefined) {
1080
- entry['versions'] = projection.versions;
1076
+ entry['marker'] = derivation.marker;
1077
+ entry['supports'] = derivation.supports;
1078
+ entry['version'] = derivation.version;
1079
+ if (derivation.versions !== undefined) {
1080
+ entry['versions'] = derivation.versions;
1081
1081
  }
1082
1082
  };
1083
1083
 
@@ -1306,7 +1306,7 @@ const buildTopoGraph = (
1306
1306
  ),
1307
1307
  entries,
1308
1308
  generatedAt,
1309
- library: collectLibraryProjection(topo),
1309
+ library: deriveTopoGraphLibrary(topo),
1310
1310
  ...(overlays === undefined ? {} : { overlays }),
1311
1311
  topoGraphSchemaVersion: TOPO_GRAPH_SCHEMA_VERSION,
1312
1312
  ...(trailheads === undefined ? {} : { trailheads }),
@@ -1400,13 +1400,13 @@ const insertRows = <TRow>(
1400
1400
  }
1401
1401
  };
1402
1402
 
1403
- const insertProjectedRows = (
1403
+ const insertDerivedRows = (
1404
1404
  db: Database,
1405
- projection: NormalizedTopoProjection
1405
+ derivation: NormalizedTopoFacts
1406
1406
  ): void => {
1407
1407
  insertRows(
1408
1408
  db,
1409
- projection.trails,
1409
+ derivation.trails,
1410
1410
  `INSERT INTO topo_trails (
1411
1411
  id, intent, idempotent, has_output, has_examples, example_count, description, pattern, meta, snapshot_id
1412
1412
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
@@ -1425,54 +1425,54 @@ const insertProjectedRows = (
1425
1425
  );
1426
1426
  insertRows(
1427
1427
  db,
1428
- projection.composings,
1428
+ derivation.composings,
1429
1429
  'INSERT INTO topo_composings (source_id, target_id, snapshot_id) VALUES (?, ?, ?)',
1430
1430
  (row) => [row.sourceId, row.targetId, row.snapshotId]
1431
1431
  );
1432
1432
  insertRows(
1433
1433
  db,
1434
- projection.trailResources,
1434
+ derivation.trailResources,
1435
1435
  `INSERT INTO topo_trail_resources (trail_id, resource_id, snapshot_id)
1436
1436
  VALUES (?, ?, ?)`,
1437
1437
  (row) => [row.trailId, row.resourceId, row.snapshotId]
1438
1438
  );
1439
1439
  insertRows(
1440
1440
  db,
1441
- projection.resources,
1441
+ derivation.resources,
1442
1442
  `INSERT INTO topo_resources (id, has_mock, has_health, snapshot_id)
1443
1443
  VALUES (?, ?, ?, ?)`,
1444
1444
  (row) => [row.id, row.hasMock, row.hasHealth, row.snapshotId]
1445
1445
  );
1446
1446
  insertRows(
1447
1447
  db,
1448
- projection.signals,
1448
+ derivation.signals,
1449
1449
  'INSERT INTO topo_signals (id, description, snapshot_id) VALUES (?, ?, ?)',
1450
1450
  (row) => [row.id, row.description, row.snapshotId]
1451
1451
  );
1452
1452
  insertRows(
1453
1453
  db,
1454
- projection.trailSignals,
1454
+ derivation.trailSignals,
1455
1455
  `INSERT INTO topo_trail_signals (trail_id, signal_id, snapshot_id)
1456
1456
  VALUES (?, ?, ?)`,
1457
1457
  (row) => [row.trailId, row.signalId, row.snapshotId]
1458
1458
  );
1459
1459
  insertRows(
1460
1460
  db,
1461
- projection.fires,
1461
+ derivation.fires,
1462
1462
  `INSERT INTO topo_trail_fires (trail_id, signal_id, snapshot_id)
1463
1463
  VALUES (?, ?, ?)`,
1464
1464
  (row) => [row.trailId, row.signalId, row.snapshotId]
1465
1465
  );
1466
1466
  insertRows(
1467
1467
  db,
1468
- projection.on,
1468
+ derivation.on,
1469
1469
  `INSERT INTO topo_trail_on (trail_id, signal_id, snapshot_id)
1470
1470
  VALUES (?, ?, ?)`,
1471
1471
  (row) => [row.trailId, row.signalId, row.snapshotId]
1472
1472
  );
1473
1473
  insertRows(
1474
1474
  db,
1475
- projection.activationSources,
1475
+ derivation.activationSources,
1476
1476
  `INSERT INTO topo_activation_sources (
1477
1477
  source_key, source_id, source_kind, source, snapshot_id
1478
1478
  ) VALUES (?, ?, ?, ?, ?)`,
@@ -1486,7 +1486,7 @@ const insertProjectedRows = (
1486
1486
  );
1487
1487
  insertRows(
1488
1488
  db,
1489
- projection.activationEdges,
1489
+ derivation.activationEdges,
1490
1490
  `INSERT INTO topo_activation_edges (
1491
1491
  source_key, source_id, source_kind, trail_id, has_where, edge, snapshot_id
1492
1492
  ) VALUES (?, ?, ?, ?, ?, ?, ?)`,
@@ -1502,7 +1502,7 @@ const insertProjectedRows = (
1502
1502
  );
1503
1503
  insertRows(
1504
1504
  db,
1505
- projection.surfaces,
1505
+ derivation.surfaces,
1506
1506
  `INSERT INTO topo_surfaces (trail_id, surface, derived_name, method, snapshot_id)
1507
1507
  VALUES (?, ?, ?, ?, ?)`,
1508
1508
  (row) => [
@@ -1515,7 +1515,7 @@ const insertProjectedRows = (
1515
1515
  );
1516
1516
  insertRows(
1517
1517
  db,
1518
- projection.examples,
1518
+ derivation.examples,
1519
1519
  `INSERT INTO topo_examples (
1520
1520
  id, trail_id, ordinal, name, description, input, expected, expected_match, error, signals, snapshot_id
1521
1521
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
@@ -1641,7 +1641,7 @@ export const createTopoSnapshot = (
1641
1641
  const snapshot = db.transaction(() => {
1642
1642
  const record = insertTopoSnapshotRecord(db, snapshotInput);
1643
1643
  const artifacts = buildStoredTopoExport(db, record, topo, snapshotInput);
1644
- insertProjectedRows(db, normalizeTopoProjection(topo, record.id));
1644
+ insertDerivedRows(db, deriveNormalizedTopoRows(topo, record.id));
1645
1645
  insertSchemaRows(db, artifacts.schemaRows);
1646
1646
  insertStoredExport(db, artifacts.exportRow);
1647
1647
  return record;
package/src/io.ts CHANGED
@@ -222,7 +222,7 @@ export const writeTrailsLock = async (
222
222
  /**
223
223
  * Read a lock v4 manifest from `<dir>/trails.lock`.
224
224
  *
225
- * v5 root locks are projected back to the v4 manifest shape for compatibility.
225
+ * v5 root locks are derived back to the v4 manifest shape for compatibility.
226
226
  */
227
227
  export const readLockManifest = async (
228
228
  options?: ReadOptions
@@ -10,7 +10,7 @@ import type {
10
10
  TopoGraphLibraryCollision,
11
11
  TopoGraphLibraryExclusion,
12
12
  TopoGraphLibraryExport,
13
- TopoGraphLibraryProjection,
13
+ TopoGraphLibraryDerived,
14
14
  } from './types.js';
15
15
 
16
16
  const sortKeys = <T extends Record<string, unknown>>(obj: T): T => {
@@ -75,9 +75,7 @@ const collectLibraryExclusions = (
75
75
  return excluded.toSorted((a, b) => a.trailId.localeCompare(b.trailId));
76
76
  };
77
77
 
78
- export const collectLibraryProjection = (
79
- topo: Topo
80
- ): TopoGraphLibraryProjection => {
78
+ export const deriveTopoGraphLibrary = (topo: Topo): TopoGraphLibraryDerived => {
81
79
  const selected = filterSurfaceTrails([...topo.trails.values()]).filter(
82
80
  (trail) => !isDraftId(trail.id)
83
81
  );
@@ -129,5 +127,5 @@ export const collectLibraryProjection = (
129
127
  collisions,
130
128
  excluded: collectLibraryExclusions(topo, selectedIds),
131
129
  exports,
132
- }) as unknown as TopoGraphLibraryProjection;
130
+ }) as unknown as TopoGraphLibraryDerived;
133
131
  };
package/src/permit.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import type { AnyTrail, PermitRequirement } from '@ontrails/core';
2
2
 
3
- export type ProjectedPermitRequirement =
3
+ export type DerivedPermitRequirement =
4
4
  | 'public'
5
5
  | { readonly scopes: readonly string[] };
6
6
 
7
- export const projectPermitRequirement = (
7
+ export const derivePermitRequirement = (
8
8
  permit: PermitRequirement
9
- ): ProjectedPermitRequirement =>
9
+ ): DerivedPermitRequirement =>
10
10
  permit === 'public' ? 'public' : { scopes: [...permit.scopes].toSorted() };
11
11
 
12
12
  export const addPermitRequirement = (
@@ -14,6 +14,6 @@ export const addPermitRequirement = (
14
14
  trail: AnyTrail
15
15
  ): void => {
16
16
  if (trail.permit !== undefined) {
17
- entry['permit'] = projectPermitRequirement(trail.permit);
17
+ entry['permit'] = derivePermitRequirement(trail.permit);
18
18
  }
19
19
  };
@@ -4,7 +4,7 @@
4
4
  * Both derivation pipelines — `deriveTopoGraph` and the store-side
5
5
  * `buildTopoGraph` — resolve the app-authored `surfaces` overlay's `cli`
6
6
  * bindings into per-trail CLI alias inputs and its `mcp` list bindings into
7
- * projected trailhead entries through this single helper module, so compiled
7
+ * derived trailhead entries through this single helper module, so compiled
8
8
  * locks and fresh derivations cannot diverge from the runtime surfaces'
9
9
  * reading of the same bindings.
10
10
  */
@@ -55,15 +55,15 @@ export const resolveCliAliasInputsFromOverlays = (
55
55
  };
56
56
 
57
57
  /**
58
- * Resolve projected trailhead entries from overlay registrations.
58
+ * Resolve derived trailhead entries from overlay registrations.
59
59
  *
60
60
  * Finds the app-authored `surfaces` overlay among the registrations and
61
- * projects each `mcp` list binding into one `TopoGraphTrailheadEntry`: the
61
+ * derives each `mcp` list binding into one `TopoGraphTrailheadEntry`: the
62
62
  * binding name becomes the trailhead id, the sorted expanded member trail
63
63
  * ids become `memberIds`, the surfaces list is `['mcp']`, and the
64
64
  * description is the deterministic derived default shared with the MCP
65
65
  * surface. Scalar `mcp` bindings are tool synonyms, not grouped entries, so
66
- * they project no trailhead. Throws a `ValidationError` for group bindings
66
+ * they render no trailhead. Throws a `ValidationError` for group bindings
67
67
  * whose member union is empty or synonym bindings that violate the shared
68
68
  * expansion rules. Returns `undefined` when no `mcp` list bindings exist.
69
69
  *
package/src/topo-store.ts CHANGED
@@ -190,7 +190,7 @@ export type {
190
190
  TopoStoreRef,
191
191
  TopoStoreSignalDetailRecord,
192
192
  TopoStoreSignalRecord,
193
- TopoStoreSurfaceProjectionRecord,
193
+ TopoStoreSurfaceDerivedRecord,
194
194
  TopoStoreTopoGraphEntryRecord,
195
195
  TopoStoreTopoGraphRecord,
196
196
  TopoStoreTrailDetailRecord,
package/src/types.ts CHANGED
@@ -173,7 +173,7 @@ export interface TopoGraphLibraryCollision {
173
173
  readonly trailIds: readonly string[];
174
174
  }
175
175
 
176
- export interface TopoGraphLibraryProjection {
176
+ export interface TopoGraphLibraryDerived {
177
177
  readonly app: string;
178
178
  readonly collisions: readonly TopoGraphLibraryCollision[];
179
179
  readonly excluded: readonly TopoGraphLibraryExclusion[];
@@ -278,7 +278,7 @@ export interface TopoGraph {
278
278
  readonly entries: readonly TopoGraphEntry[];
279
279
  readonly trailheads?: readonly TopoGraphTrailheadEntry[] | undefined;
280
280
  readonly forces?: readonly TopoGraphForceEntry[] | undefined;
281
- readonly library?: TopoGraphLibraryProjection | undefined;
281
+ readonly library?: TopoGraphLibraryDerived | undefined;
282
282
  /**
283
283
  * Namespaced fact overlays contributed by registered overlay contributions
284
284
  * (adapters). Unknown namespaces are preserved verbatim by every reader
@@ -406,7 +406,7 @@ const topoGraphLibraryCollisionSchema = z
406
406
  })
407
407
  .strict();
408
408
 
409
- export const topoGraphLibraryProjectionSchema = z
409
+ export const topoGraphLibraryDerivedSchema = z
410
410
  .object({
411
411
  app: z.string(),
412
412
  collisions: z.array(topoGraphLibraryCollisionSchema),
@@ -661,7 +661,7 @@ export const topoGraphSchema = z
661
661
  entries: z.array(topoGraphEntrySchema),
662
662
  forces: z.array(topoGraphForceEntrySchema).optional(),
663
663
  generatedAt: z.string().optional(),
664
- library: topoGraphLibraryProjectionSchema.optional(),
664
+ library: topoGraphLibraryDerivedSchema.optional(),
665
665
  overlays: z.record(z.string(), z.unknown()).optional(),
666
666
  topoGraphSchemaVersion: z.literal(TOPO_GRAPH_SCHEMA_VERSION),
667
667
  trailheads: z.array(topoGraphTrailheadEntrySchema).optional(),
package/src/versioning.ts CHANGED
@@ -23,7 +23,7 @@ import type {
23
23
  TopoGraphVersionEntry,
24
24
  } from './types.js';
25
25
 
26
- type SchemaProjector = (schema: unknown) => JsonSchema;
26
+ type SchemaDeriver = (schema: unknown) => JsonSchema;
27
27
 
28
28
  const sortPlainRecord = <T extends Record<string, unknown>>(value: T): T => {
29
29
  const sorted: Record<string, unknown> = {};
@@ -33,7 +33,7 @@ const sortPlainRecord = <T extends Record<string, unknown>>(value: T): T => {
33
33
  return sorted as T;
34
34
  };
35
35
 
36
- const projectVersionDetours = (
36
+ const deriveVersionDetours = (
37
37
  entry: TrailVersionEntry
38
38
  ): TopoGraphVersionEntry['detours'] => {
39
39
  const raw = entry as unknown as Record<string, unknown>;
@@ -57,7 +57,7 @@ const projectVersionDetours = (
57
57
  });
58
58
  };
59
59
 
60
- const projectVersionRuntimeRefs = (
60
+ const deriveVersionRuntimeRefs = (
61
61
  entry: TrailVersionEntry,
62
62
  field: 'composes' | 'resources'
63
63
  ): readonly string[] | undefined => {
@@ -85,46 +85,46 @@ const projectVersionRuntimeRefs = (
85
85
  return refs.toSorted();
86
86
  };
87
87
 
88
- export const projectTrailVersionEntry = (
88
+ export const deriveTrailVersionEntry = (
89
89
  entry: TrailVersionEntry,
90
- projectSchema: SchemaProjector
90
+ deriveSchema: SchemaDeriver
91
91
  ): TopoGraphVersionEntry => {
92
92
  const kind = getTrailVersionEntryKind(entry);
93
93
  const examples = deriveStructuredTrailExamples(entry.examples, {
94
94
  provenance: { source: 'trail.versions.examples' },
95
95
  });
96
- const projected: Record<string, unknown> = {
96
+ const derived: Record<string, unknown> = {
97
97
  exampleCount: entry.examples?.length ?? 0,
98
- input: projectSchema(entry.input),
98
+ input: deriveSchema(entry.input),
99
99
  kind,
100
100
  marker: deriveTrailVersionEntryMarker(entry),
101
- output: projectSchema(entry.output),
101
+ output: deriveSchema(entry.output),
102
102
  };
103
103
 
104
104
  if (examples !== undefined) {
105
- projected['examples'] = examples;
105
+ derived['examples'] = examples;
106
106
  }
107
107
 
108
108
  if (entry.status !== undefined) {
109
- projected['status'] = sortPlainRecord({ ...entry.status });
109
+ derived['status'] = sortPlainRecord({ ...entry.status });
110
110
  }
111
111
 
112
112
  if (kind === 'fork') {
113
- const composes = projectVersionRuntimeRefs(entry, 'composes');
114
- const resources = projectVersionRuntimeRefs(entry, 'resources');
115
- const detours = projectVersionDetours(entry);
113
+ const composes = deriveVersionRuntimeRefs(entry, 'composes');
114
+ const resources = deriveVersionRuntimeRefs(entry, 'resources');
115
+ const detours = deriveVersionDetours(entry);
116
116
  if (composes !== undefined) {
117
- projected['composes'] = composes;
117
+ derived['composes'] = composes;
118
118
  }
119
119
  if (resources !== undefined) {
120
- projected['resources'] = resources;
120
+ derived['resources'] = resources;
121
121
  }
122
122
  if (detours !== undefined) {
123
- projected['detours'] = detours;
123
+ derived['detours'] = detours;
124
124
  }
125
125
  }
126
126
 
127
- return sortPlainRecord(projected) as unknown as TopoGraphVersionEntry;
127
+ return sortPlainRecord(derived) as unknown as TopoGraphVersionEntry;
128
128
  };
129
129
 
130
130
  export interface TopoGraphVersionMarkerRecord {
@@ -241,9 +241,9 @@ export const resolveTopoGraphVersionReference = (
241
241
  };
242
242
  };
243
243
 
244
- export const projectTrailVersions = (
244
+ export const deriveTrailVersions = (
245
245
  trail: AnyTrail,
246
- projectSchema: SchemaProjector
246
+ deriveSchema: SchemaDeriver
247
247
  ):
248
248
  | {
249
249
  readonly marker: string;
@@ -256,14 +256,11 @@ export const projectTrailVersions = (
256
256
  return undefined;
257
257
  }
258
258
 
259
- const projectedEntries: Record<string, TopoGraphVersionEntry> = {};
259
+ const derivedEntries: Record<string, TopoGraphVersionEntry> = {};
260
260
  for (const [rawVersion, entry] of Object.entries(
261
261
  trail.versions ?? {}
262
262
  ).toSorted(([left], [right]) => Number(left) - Number(right))) {
263
- projectedEntries[rawVersion] = projectTrailVersionEntry(
264
- entry,
265
- projectSchema
266
- );
263
+ derivedEntries[rawVersion] = deriveTrailVersionEntry(entry, deriveSchema);
267
264
  }
268
265
 
269
266
  const currentMarker = deriveCurrentTrailVersionMarker(trail);
@@ -273,8 +270,8 @@ export const projectTrailVersions = (
273
270
  marker: currentMarker,
274
271
  supports: deriveSupportedTrailVersions(trail),
275
272
  version: trail.version,
276
- ...(Object.keys(projectedEntries).length > 0
277
- ? { versions: projectedEntries }
273
+ ...(Object.keys(derivedEntries).length > 0
274
+ ? { versions: derivedEntries }
278
275
  : {}),
279
276
  };
280
277
  };
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  errorClasses,
3
- projectErrorClassSurface,
3
+ renderErrorClassSurface,
4
4
  surfaceNames,
5
5
  } from '@ontrails/core';
6
6
  import type {
7
7
  ErrorCategory,
8
8
  ErrorClassRegistryEntry,
9
- ErrorClassSurfaceProjection,
9
+ ErrorClassSurfaceRendering,
10
10
  SurfaceName,
11
11
  } from '@ontrails/core';
12
12
  import type {
@@ -35,7 +35,7 @@ export type TrailErrorFactsCompleteness =
35
35
  readonly status: 'unknown';
36
36
  };
37
37
 
38
- export interface TrailErrorTaxonomyProjection {
38
+ export interface TrailErrorTaxonomyFacts {
39
39
  readonly category?: ErrorCategory | undefined;
40
40
  readonly dynamicCategory?:
41
41
  | {
@@ -45,7 +45,7 @@ export interface TrailErrorTaxonomyProjection {
45
45
  readonly known: boolean;
46
46
  readonly name: string;
47
47
  readonly retryable?: boolean | undefined;
48
- readonly surfaces: readonly ErrorClassSurfaceProjection[];
48
+ readonly surfaces: readonly ErrorClassSurfaceRendering[];
49
49
  }
50
50
 
51
51
  export type TrailErrorFactProvenance =
@@ -78,7 +78,7 @@ export interface TrailErrorFact {
78
78
  readonly completeness: TrailErrorFactsCompleteness;
79
79
  readonly kind: TrailErrorFactKind;
80
80
  readonly provenance: TrailErrorFactProvenance;
81
- readonly taxonomy: TrailErrorTaxonomyProjection;
81
+ readonly taxonomy: TrailErrorTaxonomyFacts;
82
82
  }
83
83
 
84
84
  export interface TrailErrorFacts {
@@ -110,10 +110,10 @@ const errorClassByName: ReadonlyMap<string, ErrorClassRegistryEntry> = new Map(
110
110
  errorClasses.map((entry) => [entry.name, entry])
111
111
  );
112
112
 
113
- const taxonomyProjection = (
113
+ const deriveTaxonomyFacts = (
114
114
  errorName: string,
115
115
  surfaces: readonly SurfaceName[]
116
- ): TrailErrorTaxonomyProjection => {
116
+ ): TrailErrorTaxonomyFacts => {
117
117
  const registryEntry = errorClassByName.get(errorName);
118
118
  if (registryEntry === undefined) {
119
119
  return {
@@ -141,8 +141,8 @@ const taxonomyProjection = (
141
141
  name: registryEntry.name,
142
142
  retryable: registryEntry.retryable,
143
143
  surfaces: surfaces.flatMap((surface) => {
144
- const projected = projectErrorClassSurface(surface, errorName);
145
- return projected === undefined ? [] : [projected];
144
+ const derived = renderErrorClassSurface(surface, errorName);
145
+ return derived === undefined ? [] : [derived];
146
146
  }),
147
147
  };
148
148
  };
@@ -189,7 +189,7 @@ const documentedFacts = (
189
189
  source: 'trail.examples',
190
190
  trailId: entry.id,
191
191
  },
192
- taxonomy: taxonomyProjection(example.error, surfaces),
192
+ taxonomy: deriveTaxonomyFacts(example.error, surfaces),
193
193
  },
194
194
  ];
195
195
  });
@@ -207,7 +207,7 @@ const handledFacts = (
207
207
  source: 'trail.detours',
208
208
  trailId: entry.id,
209
209
  },
210
- taxonomy: taxonomyProjection(detour.on, surfaces),
210
+ taxonomy: deriveTaxonomyFacts(detour.on, surfaces),
211
211
  })
212
212
  );
213
213
 
@@ -231,7 +231,7 @@ const versionDocumentedFacts = (
231
231
  trailId,
232
232
  version,
233
233
  },
234
- taxonomy: taxonomyProjection(example.error, surfaces),
234
+ taxonomy: deriveTaxonomyFacts(example.error, surfaces),
235
235
  },
236
236
  ];
237
237
  });
@@ -252,7 +252,7 @@ const versionHandledFacts = (
252
252
  trailId,
253
253
  version,
254
254
  },
255
- taxonomy: taxonomyProjection(detour.on, surfaces),
255
+ taxonomy: deriveTaxonomyFacts(detour.on, surfaces),
256
256
  })
257
257
  );
258
258
 
@@ -285,7 +285,7 @@ const inputFact = (
285
285
  trailId: input.trailId,
286
286
  ...(input.version === undefined ? {} : { version: input.version }),
287
287
  },
288
- taxonomy: taxonomyProjection(input.errorName, surfaces),
288
+ taxonomy: deriveTaxonomyFacts(input.errorName, surfaces),
289
289
  });
290
290
 
291
291
  const byTrail = (
@@ -198,7 +198,7 @@ const cliRouteSchema = z.object({
198
198
  target: z.string(),
199
199
  });
200
200
 
201
- const cliProjectionSchema = z
201
+ const cliDerivedSchema = z
202
202
  .object({
203
203
  path: z.array(z.string()).readonly(),
204
204
  routes: z.array(cliRouteSchema).readonly().optional(),
@@ -206,7 +206,7 @@ const cliProjectionSchema = z
206
206
  .nullable();
207
207
 
208
208
  const trailSummarySchema = entrySummarySchema.extend({
209
- cli: cliProjectionSchema,
209
+ cli: cliDerivedSchema,
210
210
  composes: z.array(z.string()).readonly(),
211
211
  intent: z.enum(['destroy', 'read', 'write']),
212
212
  kind: z.literal('trail'),
@@ -280,7 +280,7 @@ const errorFactsCompletenessSchema = z.discriminatedUnion('status', [
280
280
  }),
281
281
  ]);
282
282
 
283
- const errorSurfaceProjectionSchema = z.object({
283
+ const errorSurfaceDerivedSchema = z.object({
284
284
  category: z.enum(errorCategories),
285
285
  code: z.number(),
286
286
  name: z.string(),
@@ -288,7 +288,7 @@ const errorSurfaceProjectionSchema = z.object({
288
288
  surface: z.enum(surfaceNames),
289
289
  });
290
290
 
291
- const errorTaxonomyProjectionSchema = z.object({
291
+ const errorTaxonomyDerivedSchema = z.object({
292
292
  category: z.enum(errorCategories).optional(),
293
293
  dynamicCategory: z
294
294
  .object({
@@ -298,7 +298,7 @@ const errorTaxonomyProjectionSchema = z.object({
298
298
  known: z.boolean(),
299
299
  name: z.string(),
300
300
  retryable: z.boolean().optional(),
301
- surfaces: z.array(errorSurfaceProjectionSchema).readonly(),
301
+ surfaces: z.array(errorSurfaceDerivedSchema).readonly(),
302
302
  });
303
303
 
304
304
  const errorFactProvenanceSchema = z.object({
@@ -321,7 +321,7 @@ const errorFactSchema = z.object({
321
321
  completeness: errorFactsCompletenessSchema,
322
322
  kind: z.enum(['documented', 'handled', 'inferred', 'observed']),
323
323
  provenance: errorFactProvenanceSchema,
324
- taxonomy: errorTaxonomyProjectionSchema,
324
+ taxonomy: errorTaxonomyDerivedSchema,
325
325
  });
326
326
 
327
327
  const trailErrorFactsSchema = z.object({
@@ -1097,13 +1097,13 @@ const contractFor = (
1097
1097
  const withGraph = async <TValue>(
1098
1098
  input: SourceInput,
1099
1099
  cwd: string | undefined,
1100
- project: (loaded: LoadedWayfinderGraph) => TValue
1100
+ derive: (loaded: LoadedWayfinderGraph) => TValue
1101
1101
  ): Promise<Result<TValue, TrailsError>> => {
1102
1102
  const loaded = await loadGraph(input, cwd);
1103
1103
  if (loaded.isErr()) {
1104
1104
  return loaded;
1105
1105
  }
1106
- return Result.ok(project(loaded.value));
1106
+ return Result.ok(derive(loaded.value));
1107
1107
  };
1108
1108
 
1109
1109
  const notFound = (kind: string, id: string): NotFoundError =>
@@ -12,7 +12,7 @@ export const relationKindSchema = z.enum([
12
12
  'trailhead-groups',
13
13
  'fired-by',
14
14
  'has-version',
15
- 'surface-projects',
15
+ 'surface-renders',
16
16
  'used-by',
17
17
  ]);
18
18
 
@@ -142,7 +142,7 @@ export const relationEdges = (graph: TopoGraph): readonly RelationEdge[] => {
142
142
  add(refFor(graph, signalId, 'signal'), relation, target);
143
143
  }
144
144
  for (const surfaceId of entry.surfaces) {
145
- add(refFor(graph, surfaceId, 'surface'), 'surface-projects', target);
145
+ add(refFor(graph, surfaceId, 'surface'), 'surface-renders', target);
146
146
  }
147
147
  if (entry.kind === 'trail' && entry.version !== undefined) {
148
148
  add(target, 'has-version', {
@@ -174,7 +174,7 @@ export const relationEdges = (graph: TopoGraph): readonly RelationEdge[] => {
174
174
  const memberRef = refFor(graph, memberId, 'trail');
175
175
  add(trailheadRef, 'trailhead-groups', memberRef);
176
176
  for (const surfaceRef of surfaceRefs) {
177
- add(surfaceRef, 'surface-projects', memberRef);
177
+ add(surfaceRef, 'surface-renders', memberRef);
178
178
  }
179
179
  }
180
180
  }