@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.
- package/CHANGELOG.md +153 -0
- package/README.md +3 -3
- package/package.json +17 -16
- package/src/app.ts +27 -6
- package/src/cli.ts +3 -2
- package/src/mcp-app.ts +2 -0
- package/src/mcp-options.ts +20 -5
- package/src/regrade/config.ts +152 -0
- package/src/regrade/history.ts +320 -0
- package/src/regrade/live-api-preserve.ts +8 -0
- package/src/regrade/plan-artifact.ts +265 -0
- package/src/release/index.ts +17 -0
- package/src/release/lock-roundtrip-smoke.ts +230 -0
- package/src/release/notes-cli.ts +171 -0
- package/src/release/notes.ts +390 -0
- package/src/release/pack-coherence.ts +1 -3
- package/src/release/smoke.ts +11 -1
- package/src/release/wayfinder-dogfood-smoke.ts +1 -1
- package/src/run-schema.ts +34 -1
- package/src/trails/compile.ts +4 -5
- package/src/trails/create-adapter.ts +19 -79
- package/src/trails/deprecate.ts +1 -1
- package/src/trails/guide.ts +5 -5
- package/src/trails/load-app.ts +47 -116
- package/src/trails/regrade.ts +3017 -27
- package/src/trails/release-smoke.ts +2 -1
- package/src/trails/revise.ts +1 -1
- package/src/trails/survey.ts +37 -50
- package/src/trails/topo-activation.ts +14 -385
- package/src/trails/topo-read-support.ts +28 -24
- package/src/trails/topo-store-support.ts +21 -12
- package/src/trails/topo-support.ts +1 -0
- package/src/trails/topo.ts +2 -2
- package/src/trails/validate.ts +1 -1
- package/src/trails/version-lifecycle-support.ts +11 -11
- package/src/trails/warden-guide.ts +9 -4
- package/src/trails/warden.ts +15 -0
- package/src/trails/wayfind.ts +64 -12
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { existsSync } from 'node:fs';
|
|
9
9
|
import { join } from 'node:path';
|
|
10
10
|
|
|
11
|
-
import type {
|
|
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 {
|
|
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
|
|
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
|
|
165
|
+
export const deriveCurrentTopoBrief = (
|
|
164
166
|
app: Topo,
|
|
165
167
|
_options?: { readonly rootDir?: string }
|
|
166
168
|
): BriefReport => deriveBriefReport(app);
|
|
167
169
|
|
|
168
|
-
export const
|
|
170
|
+
export const deriveCurrentTopoList = (
|
|
169
171
|
app: Topo,
|
|
170
172
|
_options?: { readonly rootDir?: string }
|
|
171
173
|
): SurveyListReport => deriveSurveyList(app);
|
|
172
174
|
|
|
173
|
-
export const
|
|
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
|
|
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, {
|
|
204
|
+
topoGraph: deriveTopoGraph(app, {
|
|
205
|
+
overlays: options?.overlays,
|
|
206
|
+
}),
|
|
203
207
|
});
|
|
204
208
|
};
|
|
205
209
|
|
|
206
|
-
export const
|
|
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
|
|
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
|
|
225
|
+
export const deriveCurrentTopoDetail = (
|
|
222
226
|
app: Topo,
|
|
223
227
|
id: string,
|
|
224
228
|
options?: CurrentTopoReadOptions
|
|
225
229
|
): CurrentTopoDetail | undefined =>
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
230
|
+
deriveCurrentTrailDetail(app, id, options) ??
|
|
231
|
+
deriveCurrentResourceDetail(app, id) ??
|
|
232
|
+
deriveCurrentSignalDetail(app, id);
|
|
229
233
|
|
|
230
|
-
export const
|
|
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, {
|
|
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 =
|
|
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
|
-
|
|
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 {
|
|
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
|
|
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?:
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
295
|
+
overlays: options?.overlays,
|
|
287
296
|
});
|
|
288
297
|
if (persisted.isErr()) {
|
|
289
298
|
return persisted;
|
package/src/trails/topo.ts
CHANGED
|
@@ -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 {
|
|
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(
|
|
77
|
+
Result.ok(deriveTopoSummary(lease.app, { rootDir }))
|
|
78
78
|
),
|
|
79
79
|
description: 'Show the current topo summary and entry list',
|
|
80
80
|
examples: [
|
package/src/trails/validate.ts
CHANGED
|
@@ -23,7 +23,7 @@ export interface LifecycleCommandInput {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export interface LifecycleWriteResult {
|
|
26
|
-
readonly
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
727
|
+
filePath: match.value.sourcePath,
|
|
728
728
|
trailId: target.trailId,
|
|
729
729
|
updated: false,
|
|
730
730
|
});
|
|
731
731
|
}
|
|
732
|
-
const written = writeLifecycleSourceFile(match.value.
|
|
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
|
-
|
|
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
|
-
|
|
771
|
+
filePath: match.value.sourcePath,
|
|
772
772
|
trailId: target.trailId,
|
|
773
773
|
updated: false,
|
|
774
774
|
});
|
|
775
775
|
}
|
|
776
|
-
const written = writeLifecycleSourceFile(match.value.
|
|
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
|
-
|
|
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
|
|
58
|
-
z.literal('wardenRules'),
|
|
59
|
-
|
|
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'),
|
package/src/trails/warden.ts
CHANGED
|
@@ -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;
|
package/src/trails/wayfind.ts
CHANGED
|
@@ -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.
|
|
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.
|
|
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
|
-
| '
|
|
253
|
+
| 'trailhead'
|
|
218
254
|
| 'resource'
|
|
219
255
|
| 'signal'
|
|
220
256
|
| 'surface'
|
|
221
257
|
| 'trail'
|
|
222
258
|
)[]
|
|
223
259
|
| 'contour'
|
|
224
|
-
| '
|
|
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.
|
|
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.
|
|
752
|
+
if (input.trailheads) {
|
|
717
753
|
return {
|
|
718
|
-
result: ctx.compose('wayfind.
|
|
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.
|
|
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: {
|
|
846
|
-
name: 'List
|
|
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',
|