@ontrails/trails 1.0.0-beta.30 → 1.0.0-beta.39

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.
@@ -8,7 +8,7 @@
8
8
  import { existsSync } from 'node:fs';
9
9
  import { join } from 'node:path';
10
10
 
11
- import type { CliCommandAliasInput, Topo, TrailContext } from '@ontrails/core';
11
+ import type { Topo, TrailContext } from '@ontrails/core';
12
12
  import {
13
13
  ConflictError,
14
14
  deriveTrailsDbPath,
@@ -27,7 +27,11 @@ import {
27
27
  readTrailsLock,
28
28
  stripTopoGraphForces,
29
29
  } from '@ontrails/topographer';
30
- import type { LockManifest, TopoGraph } from '@ontrails/topographer';
30
+ import type {
31
+ LockManifest,
32
+ TopoGraph,
33
+ TopoGraphOverlayRegistration,
34
+ } from '@ontrails/topographer';
31
35
 
32
36
  import type {
33
37
  BriefReport,
@@ -72,10 +76,8 @@ export interface CurrentTopoMatch {
72
76
  }
73
77
 
74
78
  export interface CurrentTopoReadOptions {
75
- readonly cliAliases?:
76
- | Readonly<Record<string, readonly CliCommandAliasInput[]>>
77
- | undefined;
78
79
  readonly rootDir?: string | undefined;
80
+ readonly overlays?: readonly TopoGraphOverlayRegistration[] | undefined;
79
81
  readonly surfaceLayerNames?: Partial<SurfaceLayerNames> | undefined;
80
82
  }
81
83
 
@@ -144,7 +146,7 @@ const readCommittedLock = async (
144
146
  // Public read-only consumers
145
147
  // ---------------------------------------------------------------------------
146
148
 
147
- export const buildTopoSummary = (
149
+ export const deriveTopoSummary = (
148
150
  app: Topo,
149
151
  options?: { readonly rootDir?: string }
150
152
  ): TopoSummaryReport => {
@@ -160,17 +162,17 @@ export const buildTopoSummary = (
160
162
  };
161
163
  };
162
164
 
163
- export const buildCurrentTopoBrief = (
165
+ export const deriveCurrentTopoBrief = (
164
166
  app: Topo,
165
167
  _options?: { readonly rootDir?: string }
166
168
  ): BriefReport => deriveBriefReport(app);
167
169
 
168
- export const buildCurrentTopoList = (
170
+ export const deriveCurrentTopoList = (
169
171
  app: Topo,
170
172
  _options?: { readonly rootDir?: string }
171
173
  ): SurveyListReport => deriveSurveyList(app);
172
174
 
173
- export const buildCurrentGuideEntries = (
175
+ export const deriveCurrentGuideEntries = (
174
176
  app: Topo,
175
177
  _options?: { readonly rootDir?: string }
176
178
  ): readonly {
@@ -189,7 +191,7 @@ export const buildCurrentGuideEntries = (
189
191
  }))
190
192
  .toSorted((a, b) => a.id.localeCompare(b.id));
191
193
 
192
- export const buildCurrentTrailDetail = (
194
+ export const deriveCurrentTrailDetail = (
193
195
  app: Topo,
194
196
  id: string,
195
197
  options?: CurrentTopoReadOptions
@@ -199,11 +201,13 @@ export const buildCurrentTrailDetail = (
199
201
  ? undefined
200
202
  : deriveTrailDetail(trail, app, undefined, {
201
203
  surfaceLayerNames: options?.surfaceLayerNames,
202
- topoGraph: deriveTopoGraph(app, { cliAliases: options?.cliAliases }),
204
+ topoGraph: deriveTopoGraph(app, {
205
+ overlays: options?.overlays,
206
+ }),
203
207
  });
204
208
  };
205
209
 
206
- export const buildCurrentResourceDetail = (
210
+ export const deriveCurrentResourceDetail = (
207
211
  app: Topo,
208
212
  id: string,
209
213
  _options?: { readonly rootDir?: string }
@@ -212,22 +216,22 @@ export const buildCurrentResourceDetail = (
212
216
  ? undefined
213
217
  : (deriveResourceDetail(app, id) as CurrentResourceDetail);
214
218
 
215
- export const buildCurrentSignalDetail = (
219
+ export const deriveCurrentSignalDetail = (
216
220
  app: Topo,
217
221
  id: string,
218
222
  _options?: { readonly rootDir?: string }
219
223
  ): SignalDetailReport | undefined => deriveSignalDetail(app, id);
220
224
 
221
- export const buildCurrentTopoDetail = (
225
+ export const deriveCurrentTopoDetail = (
222
226
  app: Topo,
223
227
  id: string,
224
228
  options?: CurrentTopoReadOptions
225
229
  ): CurrentTopoDetail | undefined =>
226
- buildCurrentTrailDetail(app, id, options) ??
227
- buildCurrentResourceDetail(app, id) ??
228
- buildCurrentSignalDetail(app, id);
230
+ deriveCurrentTrailDetail(app, id, options) ??
231
+ deriveCurrentResourceDetail(app, id) ??
232
+ deriveCurrentSignalDetail(app, id);
229
233
 
230
- export const buildCurrentTopoMatches = (
234
+ export const deriveCurrentTopoMatches = (
231
235
  app: Topo,
232
236
  id: string,
233
237
  options?: CurrentTopoReadOptions
@@ -238,7 +242,9 @@ export const buildCurrentTopoMatches = (
238
242
  (activationGraph ??= deriveActivationGraph(app));
239
243
  let topoGraph: ReturnType<typeof deriveTopoGraph> | undefined;
240
244
  const getTopoGraph = (): ReturnType<typeof deriveTopoGraph> =>
241
- (topoGraph ??= deriveTopoGraph(app, { cliAliases: options?.cliAliases }));
245
+ (topoGraph ??= deriveTopoGraph(app, {
246
+ overlays: options?.overlays,
247
+ }));
242
248
 
243
249
  const trail = app.get(id);
244
250
  if (trail !== undefined) {
@@ -251,7 +257,7 @@ export const buildCurrentTopoMatches = (
251
257
  });
252
258
  }
253
259
 
254
- const resource = buildCurrentResourceDetail(app, id);
260
+ const resource = deriveCurrentResourceDetail(app, id);
255
261
  if (resource !== undefined) {
256
262
  matches.push({ detail: resource, kind: 'resource' });
257
263
  }
@@ -267,10 +273,8 @@ export const buildCurrentTopoMatches = (
267
273
  export const validateCurrentTopo = async (
268
274
  app: Topo,
269
275
  options?: {
270
- readonly cliAliases?:
271
- | Readonly<Record<string, readonly CliCommandAliasInput[]>>
272
- | undefined;
273
276
  readonly rootDir?: string;
277
+ readonly overlays?: readonly TopoGraphOverlayRegistration[] | undefined;
274
278
  }
275
279
  ): Promise<Result<TopoValidateReport, Error>> => {
276
280
  const rootDir = deriveRootDir(options?.rootDir);
@@ -298,7 +302,7 @@ export const validateCurrentTopo = async (
298
302
  }
299
303
 
300
304
  const currentExport = deriveCurrentTopoExport(app, {
301
- cliAliases: options?.cliAliases,
305
+ overlays: options?.overlays,
302
306
  rootDir,
303
307
  });
304
308
  if (currentExport.isErr()) {
@@ -7,7 +7,7 @@
7
7
 
8
8
  import { Database } from 'bun:sqlite';
9
9
 
10
- import type { CliCommandAliasInput, Topo } from '@ontrails/core';
10
+ import type { Topo } from '@ontrails/core';
11
11
  import {
12
12
  ConflictError,
13
13
  deriveTrailsDir,
@@ -19,6 +19,7 @@ import {
19
19
  import type {
20
20
  LockManifest,
21
21
  TopoGraph,
22
+ TopoGraphOverlayRegistration,
22
23
  TopoSnapshot,
23
24
  TrailsLock,
24
25
  } from '@ontrails/topographer';
@@ -26,6 +27,7 @@ import type { StoredTopoExport } from '@ontrails/topographer/backend-support';
26
27
  import {
27
28
  annotateTopoGraphForces,
28
29
  carryForwardTopoGraphForces,
30
+ deriveSourceFingerprint,
29
31
  deriveTopoGraphDiff,
30
32
  deriveTopoGraphHash,
31
33
  readTopoGraph,
@@ -45,21 +47,24 @@ import {
45
47
  readGitState,
46
48
  } from './topo-support.js';
47
49
 
48
- type CliAliasesOption = Readonly<
49
- Record<string, readonly CliCommandAliasInput[]>
50
- >;
50
+ type OverlaysOption = readonly TopoGraphOverlayRegistration[];
51
51
 
52
52
  const persistAndReadStoredExport = (
53
53
  app: Topo,
54
54
  db: ReturnType<typeof openWriteTrailsDb>,
55
55
  rootDir: string,
56
- options?: { readonly cliAliases?: CliAliasesOption | undefined } | undefined
56
+ options?:
57
+ | {
58
+ readonly overlays?: OverlaysOption | undefined;
59
+ }
60
+ | undefined
57
61
  ): Result<
58
62
  { snapshot: TopoSnapshot; storedExport: StoredTopoExport },
59
63
  Error
60
64
  > => {
61
65
  const snapshotResult = createStoredTopoSnapshot(db, app, {
62
- cliAliases: options?.cliAliases,
66
+ overlays: options?.overlays,
67
+ sourceFingerprint: deriveSourceFingerprint(rootDir),
63
68
  ...readGitState(rootDir),
64
69
  ...deriveTopoCounts(app),
65
70
  });
@@ -125,8 +130,8 @@ export const mapTopoExportError = (error: unknown): Error => {
125
130
  export const deriveCurrentTopoExport = (
126
131
  app: Topo,
127
132
  options?: {
128
- readonly cliAliases?: CliAliasesOption | undefined;
129
133
  readonly rootDir?: string;
134
+ readonly overlays?: OverlaysOption | undefined;
130
135
  }
131
136
  ): Result<StoredTopoExport, Error> => {
132
137
  const rootDir = deriveRootDir(options?.rootDir);
@@ -134,7 +139,7 @@ export const deriveCurrentTopoExport = (
134
139
 
135
140
  try {
136
141
  const projected = persistAndReadStoredExport(app, db, rootDir, {
137
- cliAliases: options?.cliAliases,
142
+ overlays: options?.overlays,
138
143
  });
139
144
  return projected.isErr()
140
145
  ? projected
@@ -219,6 +224,10 @@ const writeStoredExportArtifacts = async (
219
224
  const lockManifest = JSON.parse(
220
225
  storedExport.lockManifestJson
221
226
  ) as LockManifest;
227
+ // Omit wallclock provenance from the committed artifact so recompiling the
228
+ // same sources yields byte-identical lock files; the hash never covered it.
229
+ const { generatedAt: _generatedAt, ...committedTopoGraph } =
230
+ prepared.topoGraph;
222
231
  const lockPath = await writeTrailsLock(
223
232
  {
224
233
  scope: lockManifest.scope,
@@ -236,7 +245,7 @@ const writeStoredExportArtifacts = async (
236
245
  (entry) => entry.kind === 'trail'
237
246
  ).length,
238
247
  },
239
- topoGraph: prepared.topoGraph,
248
+ topoGraph: committedTopoGraph,
240
249
  topoGraphHash: prepared.hash,
241
250
  version: 4,
242
251
  } as TrailsLock,
@@ -256,9 +265,9 @@ const writeStoredExportArtifacts = async (
256
265
  export const exportCurrentTopo = async (
257
266
  app: Topo,
258
267
  options?: {
259
- readonly cliAliases?: CliAliasesOption | undefined;
260
268
  readonly force?: boolean | undefined;
261
269
  readonly rootDir?: string;
270
+ readonly overlays?: OverlaysOption | undefined;
262
271
  }
263
272
  ): Promise<Result<TopoExportReport, Error>> => {
264
273
  const rootDir = deriveRootDir(options?.rootDir);
@@ -266,7 +275,7 @@ export const exportCurrentTopo = async (
266
275
 
267
276
  try {
268
277
  const candidate = deriveCurrentTopoExport(app, {
269
- cliAliases: options?.cliAliases,
278
+ overlays: options?.overlays,
270
279
  rootDir,
271
280
  });
272
281
  if (candidate.isErr()) {
@@ -283,7 +292,7 @@ export const exportCurrentTopo = async (
283
292
 
284
293
  db = openWriteTrailsDb({ rootDir });
285
294
  const persisted = persistAndReadStoredExport(app, db, rootDir, {
286
- cliAliases: options?.cliAliases,
295
+ overlays: options?.overlays,
287
296
  });
288
297
  if (persisted.isErr()) {
289
298
  return persisted;
@@ -29,6 +29,7 @@ export const topoSnapshotOutput = z.object({
29
29
  pinnedAs: z.string().optional(),
30
30
  resourceCount: z.number(),
31
31
  signalCount: z.number(),
32
+ sourceFingerprint: z.string().optional(),
32
33
  trailCount: z.number(),
33
34
  });
34
35
 
@@ -3,7 +3,7 @@ import { z } from 'zod';
3
3
 
4
4
  import { withFreshOperatorApp } from './operator-context.js';
5
5
  import { activationOverviewOutput } from './topo-output-schemas.js';
6
- import { buildTopoSummary } from './topo-read-support.js';
6
+ import { deriveTopoSummary } from './topo-read-support.js';
7
7
  import { createIsolatedExampleInput } from './topo-support.js';
8
8
 
9
9
  const summaryOutput = z.object({
@@ -74,7 +74,7 @@ const summaryOutput = z.object({
74
74
  export const topoTrail = trail('topo', {
75
75
  blaze: async (input, ctx) =>
76
76
  withFreshOperatorApp(input, ctx, ({ lease, rootDir }) =>
77
- Result.ok(buildTopoSummary(lease.app, { rootDir }))
77
+ Result.ok(deriveTopoSummary(lease.app, { rootDir }))
78
78
  ),
79
79
  description: 'Show the current topo summary and entry list',
80
80
  examples: [
@@ -8,7 +8,7 @@ export const validateTrail = trail('validate', {
8
8
  blaze: async (input, ctx) =>
9
9
  withFreshOperatorApp(input, ctx, ({ lease, rootDir }) =>
10
10
  validateCurrentTopo(lease.app, {
11
- cliAliases: lease.cliAliases,
11
+ overlays: lease.overlays,
12
12
  rootDir,
13
13
  })
14
14
  ),
@@ -23,7 +23,7 @@ export interface LifecycleCommandInput {
23
23
  }
24
24
 
25
25
  export interface LifecycleWriteResult {
26
- readonly file: string;
26
+ readonly filePath: string;
27
27
  readonly trailId: string;
28
28
  readonly updated: boolean;
29
29
  readonly warnings?: readonly string[] | undefined;
@@ -32,8 +32,8 @@ export interface LifecycleWriteResult {
32
32
  interface TrailSourceMatch {
33
33
  readonly configEnd: number;
34
34
  readonly configStart: number;
35
- readonly filePath: string;
36
35
  readonly source: string;
36
+ readonly sourcePath: string;
37
37
  }
38
38
 
39
39
  interface PropertyMatch {
@@ -108,8 +108,8 @@ const findTrailSource = (
108
108
  return Result.ok({
109
109
  configEnd: match.config.end,
110
110
  configStart: match.config.start,
111
- filePath,
112
111
  source: source.value,
112
+ sourcePath: filePath,
113
113
  });
114
114
  }
115
115
  }
@@ -566,13 +566,13 @@ export const reviseTrailSource = (
566
566
  blaze?.value
567
567
  )
568
568
  );
569
- const written = writeLifecycleSourceFile(match.value.filePath, nextSource);
569
+ const written = writeLifecycleSourceFile(match.value.sourcePath, nextSource);
570
570
  if (written.isErr()) {
571
571
  return written;
572
572
  }
573
573
 
574
574
  return Result.ok({
575
- file: match.value.filePath,
575
+ filePath: match.value.sourcePath,
576
576
  trailId: trail.id,
577
577
  updated: true,
578
578
  ...(usesForkPlaceholder
@@ -724,18 +724,18 @@ export const setVersionStatusSource = (
724
724
  );
725
725
  if (nextSource === match.value.source) {
726
726
  return Result.ok({
727
- file: match.value.filePath,
727
+ filePath: match.value.sourcePath,
728
728
  trailId: target.trailId,
729
729
  updated: false,
730
730
  });
731
731
  }
732
- const written = writeLifecycleSourceFile(match.value.filePath, nextSource);
732
+ const written = writeLifecycleSourceFile(match.value.sourcePath, nextSource);
733
733
  if (written.isErr()) {
734
734
  return written;
735
735
  }
736
736
 
737
737
  return Result.ok({
738
- file: match.value.filePath,
738
+ filePath: match.value.sourcePath,
739
739
  trailId: target.trailId,
740
740
  updated: true,
741
741
  });
@@ -768,18 +768,18 @@ export const forkVersionEntrySource = (
768
768
  const nextSource = rewrite.source;
769
769
  if (nextSource === match.value.source) {
770
770
  return Result.ok({
771
- file: match.value.filePath,
771
+ filePath: match.value.sourcePath,
772
772
  trailId: target.trailId,
773
773
  updated: false,
774
774
  });
775
775
  }
776
- const written = writeLifecycleSourceFile(match.value.filePath, nextSource);
776
+ const written = writeLifecycleSourceFile(match.value.sourcePath, nextSource);
777
777
  if (written.isErr()) {
778
778
  return written;
779
779
  }
780
780
 
781
781
  return Result.ok({
782
- file: match.value.filePath,
782
+ filePath: match.value.sourcePath,
783
783
  trailId: target.trailId,
784
784
  updated: true,
785
785
  ...(rewrite.usedPlaceholder
@@ -37,6 +37,12 @@ const wardenRuleGuideEntrySchema = z.object({
37
37
  .object({
38
38
  class: z.enum(wardenFixClasses),
39
39
  safety: z.enum(wardenFixSafeties),
40
+ scanTargets: z
41
+ .object({
42
+ exclude: z.array(z.string()).readonly().optional(),
43
+ extensions: z.array(z.string()).readonly().optional(),
44
+ })
45
+ .optional(),
40
46
  })
41
47
  .optional(),
42
48
  guidance: wardenGuidanceSchema.optional(),
@@ -54,10 +60,9 @@ const wardenRuleGuideEntrySchema = z.object({
54
60
  const wardenGuideManifestSchema = z.object({
55
61
  generatedFrom: z.object({
56
62
  package: z.literal('@ontrails/warden'),
57
- registries: z.tuple([
58
- z.literal('wardenRules'),
59
- z.literal('wardenTopoRules'),
60
- ]),
63
+ registries: z
64
+ .tuple([z.literal('wardenRules'), z.literal('wardenTopoRules')])
65
+ .readonly(),
61
66
  source: z.literal('builtin-rule-metadata'),
62
67
  }),
63
68
  kind: z.literal('trails-warden-guide-manifest'),
@@ -66,6 +66,10 @@ const wardenInputSchema = z.object({
66
66
  prePush: z.boolean().default(false).describe('Use the pre-push preset'),
67
67
  refresh: z.boolean().default(false).describe('Alias for --lock refresh'),
68
68
  rootDir: z.string().optional().describe('Root directory to scan'),
69
+ scopeExclude: z
70
+ .array(z.string())
71
+ .optional()
72
+ .describe('Root-relative path globs that Warden should not govern'),
69
73
  skipLock: z.boolean().default(false).describe('Alias for --lock skip'),
70
74
  strict: z.boolean().default(false).describe('Alias for --fail-on warning'),
71
75
  summary: z.boolean().default(false).describe('Alias for --format summary'),
@@ -106,6 +110,16 @@ const pushApps = (
106
110
  }
107
111
  };
108
112
 
113
+ const pushRepeatedValues = (
114
+ args: string[],
115
+ flag: string,
116
+ values: readonly string[] | undefined
117
+ ): void => {
118
+ for (const value of values ?? []) {
119
+ args.push(flag, value);
120
+ }
121
+ };
122
+
109
123
  export const buildWardenCommandArgs = (
110
124
  input: WardenTrailInput
111
125
  ): readonly string[] => {
@@ -150,6 +164,7 @@ export const buildWardenCommandArgs = (
150
164
  pushFlag(args, input.fix, '--fix');
151
165
  pushFlag(args, input.adapterCheck, '--adapter-check');
152
166
  pushValue(args, '--config-path', input.configPath);
167
+ pushRepeatedValues(args, '--scope-exclude', input.scopeExclude);
153
168
  pushApps(args, input.apps);
154
169
 
155
170
  return args;
@@ -40,7 +40,6 @@ const wayfindInputSchema = z
40
40
  .default(false)
41
41
  .describe('Render the describe view for the selected target'),
42
42
  errors: z.boolean().default(false).describe('Resolve trail error facts'),
43
- facets: z.boolean().default(false).describe('Resolve surface facet facts'),
44
43
  impact: z
45
44
  .boolean()
46
45
  .default(false)
@@ -66,6 +65,12 @@ const wayfindInputSchema = z
66
65
  .boolean()
67
66
  .default(false)
68
67
  .describe('Render the outline view for a source file target'),
68
+ overlay: z
69
+ .string()
70
+ .optional()
71
+ .describe(
72
+ 'Read a namespaced fact overlay from the saved graph (e.g. --overlay cloudflare)'
73
+ ),
69
74
  overview: z
70
75
  .boolean()
71
76
  .default(false)
@@ -81,6 +86,10 @@ const wayfindInputSchema = z
81
86
  .string()
82
87
  .optional()
83
88
  .describe('Graph entity ID or source file path to inspect'),
89
+ trailheads: z
90
+ .boolean()
91
+ .default(false)
92
+ .describe('Resolve surface trailhead facts'),
84
93
  trails: z.boolean().default(false).describe('Resolve trail facts'),
85
94
  view: wayfinderViewSchema
86
95
  .default('list')
@@ -134,7 +143,7 @@ const wayfindInputSchema = z
134
143
  (input.adapter === undefined &&
135
144
  !input.contours &&
136
145
  !input.errors &&
137
- !input.facets &&
146
+ !input.trailheads &&
138
147
  input.intent === undefined &&
139
148
  !input.resources &&
140
149
  !input.signals &&
@@ -155,7 +164,34 @@ const wayfindInputSchema = z
155
164
  '--include attaches facts to a target or filtered population from locked artifacts; impact/deps and live-source includes are not supported yet.',
156
165
  path: ['include'],
157
166
  }
158
- );
167
+ )
168
+ .refine(
169
+ (input) =>
170
+ input.overlay === undefined ||
171
+ (input.target === undefined &&
172
+ !input.deps &&
173
+ !input.impact &&
174
+ input.include.length === 0 &&
175
+ input.adapter === undefined &&
176
+ !input.contours &&
177
+ !input.errors &&
178
+ !input.trailheads &&
179
+ input.intent === undefined &&
180
+ !input.resources &&
181
+ !input.signals &&
182
+ !input.surfaces &&
183
+ !input.trails),
184
+ {
185
+ message:
186
+ 'The --overlay flag reads one lock overlay and cannot be combined with targets, population selectors, or includes.',
187
+ path: ['overlay'],
188
+ }
189
+ )
190
+ .refine((input) => input.overlay === undefined || input.source !== 'live', {
191
+ message:
192
+ '--overlay reads namespaced overlays from locked artifacts; live source does not carry lock overlays.',
193
+ path: ['overlay'],
194
+ });
159
195
 
160
196
  const wayfindComposeInputSchema = z
161
197
  .object({
@@ -200,7 +236,7 @@ const hasLiveTypedFilter = (input: WayfindInput): boolean =>
200
236
  input.adapter !== undefined ||
201
237
  input.contours ||
202
238
  input.errors ||
203
- input.facets ||
239
+ input.trailheads ||
204
240
  input.intent !== undefined ||
205
241
  input.resources ||
206
242
  input.signals ||
@@ -214,14 +250,14 @@ const populationFilters = (
214
250
  readonly kind?:
215
251
  | readonly (
216
252
  | 'contour'
217
- | 'facet'
253
+ | 'trailhead'
218
254
  | 'resource'
219
255
  | 'signal'
220
256
  | 'surface'
221
257
  | 'trail'
222
258
  )[]
223
259
  | 'contour'
224
- | 'facet'
260
+ | 'trailhead'
225
261
  | 'resource'
226
262
  | 'signal'
227
263
  | 'surface'
@@ -232,7 +268,7 @@ const populationFilters = (
232
268
  } => {
233
269
  const kinds = [
234
270
  ...(input.contours ? ['contour' as const] : []),
235
- ...(input.facets ? ['facet' as const] : []),
271
+ ...(input.trailheads ? ['trailhead' as const] : []),
236
272
  ...(input.resources ? ['resource' as const] : []),
237
273
  ...(input.signals ? ['signal' as const] : []),
238
274
  ...(input.surfaces ? ['surface' as const] : []),
@@ -713,9 +749,9 @@ const viewPopulation = async (
713
749
  view: 'list' as const,
714
750
  };
715
751
  }
716
- if (input.facets) {
752
+ if (input.trailheads) {
717
753
  return {
718
- result: ctx.compose('wayfind.facets', {
754
+ result: ctx.compose('wayfind.trailheads', {
719
755
  filters,
720
756
  limit: input.limit,
721
757
  ...sourceInput(input),
@@ -767,6 +803,17 @@ export const wayfindTrail = trail('wayfind.navigate', {
767
803
  );
768
804
  }
769
805
  }
806
+ if (input.overlay !== undefined) {
807
+ return envelopeFor(
808
+ await ctx.compose('wayfind.overlay', {
809
+ namespace: input.overlay,
810
+ ...sourceInput(input),
811
+ }),
812
+ input,
813
+ ctx,
814
+ 'list'
815
+ );
816
+ }
770
817
  const dispatched =
771
818
  (await viewRelation(input, ctx)) ??
772
819
  (await (input.target === undefined
@@ -791,7 +838,8 @@ export const wayfindTrail = trail('wayfind.navigate', {
791
838
  'wayfind.describe',
792
839
  'wayfind.errors',
793
840
  'wayfind.examples',
794
- 'wayfind.facets',
841
+ 'wayfind.overlay',
842
+ 'wayfind.trailheads',
795
843
  'wayfind.impact',
796
844
  'wayfind.nearby',
797
845
  'wayfind.outline',
@@ -842,13 +890,17 @@ export const wayfindTrail = trail('wayfind.navigate', {
842
890
  name: 'List surface facts',
843
891
  },
844
892
  {
845
- input: { facets: true },
846
- name: 'List facet facts',
893
+ input: { trailheads: true },
894
+ name: 'List trailhead facts',
847
895
  },
848
896
  {
849
897
  input: { overview: true },
850
898
  name: 'Show graph overview',
851
899
  },
900
+ {
901
+ input: { overlay: 'cloudflare' },
902
+ name: 'Read a namespaced lock overlay',
903
+ },
852
904
  {
853
905
  input: { include: ['examples'], target: 'wayfind.search' },
854
906
  name: 'Attach examples for a target',