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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/README.md +1 -1
  3. package/package.json +17 -17
  4. package/src/app.ts +4 -4
  5. package/src/cli.ts +1 -1
  6. package/src/completions.ts +1 -1
  7. package/src/mcp-app.ts +2 -2
  8. package/src/regrade/history.ts +148 -38
  9. package/src/regrade/plan-artifact.ts +31 -11
  10. package/src/release/native-bun-registry.ts +12 -1
  11. package/src/release/policy.ts +4 -1
  12. package/src/retired-topo-command.ts +1 -1
  13. package/src/run-watch.ts +1 -1
  14. package/src/run-wayfind-outline.ts +6 -2
  15. package/src/trails/adapter-check.ts +8 -8
  16. package/src/trails/add-surface.ts +2 -2
  17. package/src/trails/add-trail.ts +3 -3
  18. package/src/trails/add-verify.ts +2 -2
  19. package/src/trails/compile.ts +9 -9
  20. package/src/trails/completions-complete.ts +10 -10
  21. package/src/trails/completions.ts +2 -2
  22. package/src/trails/create-adapter.ts +185 -424
  23. package/src/trails/create-scaffold.ts +12 -12
  24. package/src/trails/create-versions.ts +8 -8
  25. package/src/trails/create.ts +35 -35
  26. package/src/trails/deprecate.ts +2 -2
  27. package/src/trails/dev-clean.ts +11 -11
  28. package/src/trails/dev-reset.ts +11 -11
  29. package/src/trails/dev-stats.ts +8 -8
  30. package/src/trails/dev-support.ts +1 -1
  31. package/src/trails/doctor.ts +4 -4
  32. package/src/trails/draft-promote.ts +3 -3
  33. package/src/trails/guide.ts +9 -9
  34. package/src/trails/load-app.ts +3 -3
  35. package/src/trails/regrade.ts +56 -27
  36. package/src/trails/release-check.ts +8 -8
  37. package/src/trails/release-smoke.ts +2 -2
  38. package/src/trails/revise.ts +2 -2
  39. package/src/trails/run-example.ts +9 -9
  40. package/src/trails/run-examples.ts +9 -9
  41. package/src/trails/run.ts +26 -26
  42. package/src/trails/survey.ts +45 -45
  43. package/src/trails/topo-activation.ts +2 -2
  44. package/src/trails/topo-history.ts +8 -8
  45. package/src/trails/topo-output-schemas.ts +5 -5
  46. package/src/trails/topo-pin.ts +6 -6
  47. package/src/trails/topo-read-support.ts +4 -3
  48. package/src/trails/topo-reports.ts +16 -16
  49. package/src/trails/topo-store-support.ts +18 -9
  50. package/src/trails/topo-support.ts +2 -2
  51. package/src/trails/topo-unpin.ts +12 -12
  52. package/src/trails/topo.ts +4 -4
  53. package/src/trails/validate.ts +2 -2
  54. package/src/trails/version-lifecycle-support.ts +17 -16
  55. package/src/trails/warden-guide.ts +8 -8
  56. package/src/trails/warden.ts +21 -21
  57. package/src/trails/wayfind-outline.ts +876 -0
  58. package/src/trails/wayfind.ts +74 -74
@@ -164,7 +164,7 @@ bun run guide
164
164
  ## Lexicon
165
165
 
166
166
  - \`trail\`, not action or handler
167
- - \`blaze\`, not handler or impl
167
+ - \`implementation\`, not handler or impl
168
168
  - \`topo\`, not registry or collection
169
169
  - \`compose\`, not follow
170
170
  - \`surface\`, not transport
@@ -173,9 +173,9 @@ bun run guide
173
173
 
174
174
  ## Trail Rules
175
175
 
176
- - Blazes return \`Result\`; never throw from trail logic.
176
+ - Implementations return \`Result\`; never throw from trail logic.
177
177
  - Use \`Result.ok()\` and \`Result.err()\`; branch with \`isOk()\`, \`isErr()\`, or \`match()\`.
178
- - Keep trail logic surface-agnostic. Do not import CLI, MCP, HTTP, request, or response types into blazes.
178
+ - Keep trail logic surface-agnostic. Do not import CLI, MCP, HTTP, request, or response types into implementations.
179
179
  - Public MCP or HTTP trails declare an \`output\` schema.
180
180
  - Trails that compose other trails declare \`composes: [...]\` and invoke them with \`ctx.compose(...)\`.
181
181
  - Trails that use infrastructure declare \`resources: [...]\` and access them through the resource helpers.
@@ -236,7 +236,7 @@ const generateHelloTrail = (): string =>
236
236
  import { z } from 'zod';
237
237
 
238
238
  export const hello = trail('hello', {
239
- blaze: (input) => {
239
+ implementation: (input) => {
240
240
  const name = input.name ?? 'world';
241
241
  return Result.ok({ message: \`Hello, \${name}!\` });
242
242
  },
@@ -277,7 +277,7 @@ const entitySchema = z.object({
277
277
  });
278
278
 
279
279
  export const show = trail('entity.show', {
280
- blaze: (input, ctx) => {
280
+ implementation: (input, ctx) => {
281
281
  const store = entityStore.from(ctx);
282
282
  const entity = store.get(input.id);
283
283
  if (!entity) {
@@ -300,7 +300,7 @@ export const show = trail('entity.show', {
300
300
  });
301
301
 
302
302
  export const add = trail('entity.add', {
303
- blaze: (input, ctx) => {
303
+ implementation: (input, ctx) => {
304
304
  const store = entityStore.from(ctx);
305
305
  const entity = { id: randomUUID(), name: input.name };
306
306
  store.add(entity);
@@ -322,7 +322,7 @@ export const add = trail('entity.add', {
322
322
  });
323
323
 
324
324
  export const list = trail('entity.list', {
325
- blaze: (_input, ctx) => {
325
+ implementation: (_input, ctx) => {
326
326
  const store = entityStore.from(ctx);
327
327
  return Result.ok({ entities: store.list() });
328
328
  },
@@ -343,7 +343,7 @@ export const list = trail('entity.list', {
343
343
  });
344
344
 
345
345
  export const remove = trail('entity.delete', {
346
- blaze: (input, ctx) => {
346
+ implementation: (input, ctx) => {
347
347
  const store = entityStore.from(ctx);
348
348
  const deleted = store.delete(input.id);
349
349
  return Result.ok({ deleted, id: input.id });
@@ -372,7 +372,7 @@ const generateSearchTrail = (): string =>
372
372
  import { z } from 'zod';
373
373
 
374
374
  export const search = trail('search', {
375
- blaze: () => {
375
+ implementation: () => {
376
376
  return Result.ok({ results: [] });
377
377
  },
378
378
  description: 'Search entities by query',
@@ -396,7 +396,7 @@ const generateOnboardTrail = (): string =>
396
396
  import { z } from 'zod';
397
397
 
398
398
  export const onboard = trail('entity.onboard', {
399
- blaze: async (input, ctx) => {
399
+ implementation: async (input, ctx) => {
400
400
  const result = await ctx.compose('entity.add', { name: input.name });
401
401
  if (result.isErr()) {
402
402
  return result;
@@ -569,7 +569,8 @@ const collectScaffoldOperations = (
569
569
  // ---------------------------------------------------------------------------
570
570
 
571
571
  export const createScaffold = trail('create.scaffold', {
572
- blaze: async (input) => {
572
+ description: 'Scaffold a new Trails project',
573
+ implementation: async (input) => {
573
574
  const projectDirResult = resolveProjectDir(input.dir ?? '.', input.name);
574
575
  if (projectDirResult.isErr()) {
575
576
  return projectDirResult;
@@ -606,7 +607,6 @@ export const createScaffold = trail('create.scaffold', {
606
607
  plannedOperations: plannedOperations.value,
607
608
  } satisfies ScaffoldResult);
608
609
  },
609
- description: 'Scaffold a new Trails project',
610
610
  input: z.object({
611
611
  dir: z.string().optional().describe('Parent directory'),
612
612
  dryRun: z
@@ -27,7 +27,14 @@ const createVersionsOutputSchema = z.object({
27
27
  });
28
28
 
29
29
  export const createVersionsTrail = trail('create.versions', {
30
- blaze: async (input, ctx) => {
30
+ description: 'Sync generated scaffold dependency versions',
31
+ examples: [
32
+ {
33
+ input: { check: true },
34
+ name: 'Verify generated scaffold versions are current',
35
+ },
36
+ ],
37
+ implementation: async (input, ctx) => {
31
38
  const rootDirResult = resolveTrailRootDir(input.rootDir, ctx.cwd);
32
39
  if (rootDirResult.isErr()) {
33
40
  return rootDirResult;
@@ -48,13 +55,6 @@ export const createVersionsTrail = trail('create.versions', {
48
55
  );
49
56
  }
50
57
  },
51
- description: 'Sync generated scaffold dependency versions',
52
- examples: [
53
- {
54
- input: { check: true },
55
- name: 'Verify generated scaffold versions are current',
56
- },
57
- ],
58
58
  input: createVersionsInputSchema,
59
59
  intent: 'write',
60
60
  output: createVersionsOutputSchema,
@@ -200,7 +200,41 @@ const writeReadme = async (
200
200
  // ---------------------------------------------------------------------------
201
201
 
202
202
  export const createTrail = trail('create', {
203
- blaze: async (input: CreateInput, ctx) => {
203
+ composes: ['create.scaffold', 'add.surface', 'add.verify'],
204
+ description: 'Create a new Trails project',
205
+ fields: {
206
+ starter: {
207
+ options: [
208
+ {
209
+ hint: 'One trail, one example',
210
+ label: 'Hello world',
211
+ value: 'hello',
212
+ },
213
+ {
214
+ hint: '4 trails, signal, store',
215
+ label: 'Entity CRUD',
216
+ value: 'entity',
217
+ },
218
+ { hint: 'Just the structure', label: 'Empty', value: 'empty' },
219
+ ],
220
+ },
221
+ surfaces: {
222
+ options: [
223
+ { hint: 'Commander-based command line', label: 'CLI', value: 'cli' },
224
+ {
225
+ hint: 'Model Context Protocol for agents',
226
+ label: 'MCP',
227
+ value: 'mcp',
228
+ },
229
+ {
230
+ hint: 'Hono-powered HTTP endpoints',
231
+ label: 'HTTP',
232
+ value: 'http',
233
+ },
234
+ ],
235
+ },
236
+ },
237
+ implementation: async (input: CreateInput, ctx) => {
204
238
  if (!hasCompose(ctx)) {
205
239
  return Result.err(new InternalError('create trail requires ctx.compose'));
206
240
  }
@@ -257,40 +291,6 @@ export const createTrail = trail('create', {
257
291
 
258
292
  return finishCreate();
259
293
  },
260
- composes: ['create.scaffold', 'add.surface', 'add.verify'],
261
- description: 'Create a new Trails project',
262
- fields: {
263
- starter: {
264
- options: [
265
- {
266
- hint: 'One trail, one example',
267
- label: 'Hello world',
268
- value: 'hello',
269
- },
270
- {
271
- hint: '4 trails, signal, store',
272
- label: 'Entity CRUD',
273
- value: 'entity',
274
- },
275
- { hint: 'Just the structure', label: 'Empty', value: 'empty' },
276
- ],
277
- },
278
- surfaces: {
279
- options: [
280
- { hint: 'Commander-based command line', label: 'CLI', value: 'cli' },
281
- {
282
- hint: 'Model Context Protocol for agents',
283
- label: 'MCP',
284
- value: 'mcp',
285
- },
286
- {
287
- hint: 'Hono-powered HTTP endpoints',
288
- label: 'HTTP',
289
- value: 'http',
290
- },
291
- ],
292
- },
293
- },
294
294
  input: z.object({
295
295
  dir: z.string().optional().describe('Parent directory'),
296
296
  name: z
@@ -9,7 +9,8 @@ import {
9
9
 
10
10
  export const deprecateTrail = trail('deprecate', {
11
11
  args: ['target'],
12
- blaze: async (input, ctx) =>
12
+ description: 'Mark a historical trail version deprecated or archived',
13
+ implementation: async (input, ctx) =>
13
14
  withLifecycleApp(input, ctx.cwd, async (_app, rootDir) => {
14
15
  const target = parseLifecycleTarget(input.target);
15
16
  if (target.isErr()) {
@@ -27,7 +28,6 @@ export const deprecateTrail = trail('deprecate', {
27
28
  }
28
29
  );
29
30
  }),
30
- description: 'Mark a historical trail version deprecated or archived',
31
31
  input: z.object({
32
32
  archive: z
33
33
  .boolean()
@@ -9,7 +9,17 @@ import { resolveTrailRootDir } from './root-dir.js';
9
9
  import { createIsolatedExampleInput } from './topo-support.js';
10
10
 
11
11
  export const devCleanTrail = trail('dev.clean', {
12
- blaze: (input, ctx) => {
12
+ description: 'Prune unpinned topo snapshots and old trace records',
13
+ examples: [
14
+ {
15
+ input: {
16
+ dryRun: true,
17
+ rootDir: createIsolatedExampleInput('dev-clean').rootDir,
18
+ },
19
+ name: 'Preview local cleanup',
20
+ },
21
+ ],
22
+ implementation: (input, ctx) => {
13
23
  if (input.dryRun !== true && input.yes !== true) {
14
24
  return Result.err(
15
25
  new ValidationError(
@@ -33,16 +43,6 @@ export const devCleanTrail = trail('dev.clean', {
33
43
  })
34
44
  );
35
45
  },
36
- description: 'Prune unpinned topo snapshots and old trace records',
37
- examples: [
38
- {
39
- input: {
40
- dryRun: true,
41
- rootDir: createIsolatedExampleInput('dev-clean').rootDir,
42
- },
43
- name: 'Preview local cleanup',
44
- },
45
- ],
46
46
  input: z.object({
47
47
  dryRun: z
48
48
  .boolean()
@@ -6,7 +6,17 @@ import { resolveTrailRootDir } from './root-dir.js';
6
6
  import { createIsolatedExampleInput } from './topo-support.js';
7
7
 
8
8
  export const devResetTrail = trail('dev.reset', {
9
- blaze: (input, ctx) => {
9
+ description: 'Remove local Trails database artifacts',
10
+ examples: [
11
+ {
12
+ input: {
13
+ dryRun: true,
14
+ rootDir: createIsolatedExampleInput('dev-reset').rootDir,
15
+ },
16
+ name: 'Preview local reset',
17
+ },
18
+ ],
19
+ implementation: (input, ctx) => {
10
20
  if (input.dryRun !== true && input.yes !== true) {
11
21
  return Result.err(
12
22
  new ValidationError(
@@ -22,16 +32,6 @@ export const devResetTrail = trail('dev.reset', {
22
32
  const rootDir = rootDirResult.value;
23
33
  return Result.ok(resetDevState({ dryRun: input.dryRun, rootDir }));
24
34
  },
25
- description: 'Remove local Trails database artifacts',
26
- examples: [
27
- {
28
- input: {
29
- dryRun: true,
30
- rootDir: createIsolatedExampleInput('dev-reset').rootDir,
31
- },
32
- name: 'Preview local reset',
33
- },
34
- ],
35
35
  input: z.object({
36
36
  dryRun: z
37
37
  .boolean()
@@ -9,7 +9,14 @@ import { resolveTrailRootDir } from './root-dir.js';
9
9
  import { createIsolatedExampleInput } from './topo-support.js';
10
10
 
11
11
  export const devStatsTrail = trail('dev.stats', {
12
- blaze: (input, ctx) => {
12
+ description: 'Show local Trails workspace state and retention',
13
+ examples: [
14
+ {
15
+ input: { rootDir: createIsolatedExampleInput('dev-stats').rootDir },
16
+ name: 'Show local dev state',
17
+ },
18
+ ],
19
+ implementation: (input, ctx) => {
13
20
  const rootDirResult = resolveTrailRootDir(input.rootDir, ctx.cwd);
14
21
  if (rootDirResult.isErr()) {
15
22
  return rootDirResult;
@@ -24,13 +31,6 @@ export const devStatsTrail = trail('dev.stats', {
24
31
  })
25
32
  );
26
33
  },
27
- description: 'Show local Trails workspace state and retention',
28
- examples: [
29
- {
30
- input: { rootDir: createIsolatedExampleInput('dev-stats').rootDir },
31
- name: 'Show local dev state',
32
- },
33
- ],
34
34
  input: z.object({
35
35
  rootDir: z.string().optional().describe('Workspace root directory'),
36
36
  snapshots: z
@@ -11,7 +11,7 @@ import {
11
11
  countPrunableSnapshots,
12
12
  countTopoSnapshots,
13
13
  pruneUnpinnedSnapshots,
14
- } from '@ontrails/topographer/backend-support';
14
+ } from '@ontrails/topography/backend-support';
15
15
  import {
16
16
  DEFAULT_MAX_AGE,
17
17
  DEFAULT_MAX_RECORDS,
@@ -5,7 +5,7 @@ import {
5
5
  Result,
6
6
  trail,
7
7
  } from '@ontrails/core';
8
- import { readTopoGraph } from '@ontrails/topographer';
8
+ import { readTopoGraph } from '@ontrails/topography';
9
9
  import { z } from 'zod';
10
10
 
11
11
  import {
@@ -30,7 +30,8 @@ const toDoctorSummaryError = (error: unknown): InternalError =>
30
30
  : new InternalError(`Unable to derive doctor summary: ${String(error)}`);
31
31
 
32
32
  export const doctorTrail = trail('doctor', {
33
- blaze: async (input, ctx) =>
33
+ description: 'Diagnose trail versioning lifecycle state',
34
+ implementation: async (input, ctx) =>
34
35
  withLifecycleApp(input, ctx.cwd, async (app, rootDir) => {
35
36
  const forceGraph = await readDoctorForceGraph(rootDir);
36
37
  try {
@@ -45,7 +46,6 @@ export const doctorTrail = trail('doctor', {
45
46
  return Result.err(toDoctorSummaryError(error));
46
47
  }
47
48
  }),
48
- description: 'Diagnose trail versioning lifecycle state',
49
49
  input: z.object({
50
50
  module: z.string().optional().describe('Path to the app module'),
51
51
  rootDir: z.string().optional().describe('Workspace root directory'),
@@ -61,7 +61,7 @@ export const doctorTrail = trail('doctor', {
61
61
  change: z.enum(['modified', 'removed']),
62
62
  detail: z.string(),
63
63
  id: z.string(),
64
- kind: z.enum(['contour', 'trail', 'signal', 'resource']),
64
+ kind: z.enum(['entity', 'trail', 'signal', 'resource']),
65
65
  reason: z.string().optional(),
66
66
  scope: z.enum(['entry', 'graph']),
67
67
  severity: z.literal('breaking'),
@@ -21,7 +21,7 @@ import {
21
21
  isDraftMarkedFile,
22
22
  stripDraftFileMarkers,
23
23
  } from '@ontrails/warden';
24
- import { findStringLiterals, parse } from '@ontrails/warden/ast';
24
+ import { findStringLiterals, parse } from '@ontrails/source';
25
25
  import { z } from 'zod';
26
26
 
27
27
  import {
@@ -674,7 +674,7 @@ const resolvePromotionAppModule = async (
674
674
  * @remarks
675
675
  * The lease deletes its on-disk mirror on release. Any Topo consumption that
676
676
  * may trigger deferred filesystem imports (for example inside a trail's
677
- * `blaze` or a lazy relative `import()`) must run before the lease is
677
+ * `implementation` or a lazy relative `import()`) must run before the lease is
678
678
  * released, otherwise those resolutions race the mirror teardown. Collapsing
679
679
  * consumption into the leased critical section keeps that contract
680
680
  * structural rather than relying on the caller to discover it.
@@ -884,7 +884,6 @@ const promoteDraftState = async (
884
884
  };
885
885
 
886
886
  export const draftPromoteTrail = trail('draft.promote', {
887
- blaze: promoteDraftState,
888
887
  description:
889
888
  'Promote a draft id to an established id, rewrite inbound references, and verify the result against a fresh topo load.',
890
889
  examples: [
@@ -900,6 +899,7 @@ export const draftPromoteTrail = trail('draft.promote', {
900
899
  name: 'Rejects a missing project root before any rewrite begins',
901
900
  },
902
901
  ],
902
+ implementation: promoteDraftState,
903
903
  input: z.object({
904
904
  appModule: z
905
905
  .string()
@@ -50,7 +50,15 @@ type GuideTrailInput = z.output<typeof guideTrailInputSchema>;
50
50
  // ---------------------------------------------------------------------------
51
51
 
52
52
  export const guideTrail = trail('guide', {
53
- blaze: async (input: GuideTrailInput, ctx) =>
53
+ description: 'Runtime guidance for trails',
54
+ examples: [
55
+ {
56
+ description: 'Lists all trails with descriptions and example counts',
57
+ input: createIsolatedExampleInput('guide-list'),
58
+ name: 'List trail guidance',
59
+ },
60
+ ],
61
+ implementation: async (input: GuideTrailInput, ctx) =>
54
62
  withFreshOperatorApp<GuideTrailOutput>(input, ctx, ({ lease, rootDir }) => {
55
63
  if (input.trailId) {
56
64
  const detail = deriveCurrentTopoDetail(lease.app, input.trailId, {
@@ -76,14 +84,6 @@ export const guideTrail = trail('guide', {
76
84
  mode: 'list' as const,
77
85
  });
78
86
  }),
79
- description: 'Runtime guidance for trails',
80
- examples: [
81
- {
82
- description: 'Lists all trails with descriptions and example counts',
83
- input: createIsolatedExampleInput('guide-list'),
84
- name: 'List trail guidance',
85
- },
86
- ],
87
87
  input: guideTrailInputSchema,
88
88
  intent: 'read',
89
89
  output: z.discriminatedUnion('mode', [
@@ -26,7 +26,7 @@ import {
26
26
  } from '@ontrails/core';
27
27
  import type { Topo } from '@ontrails/core';
28
28
  import { resolveTrailsOverlays } from '@ontrails/adapter-kit';
29
- import type { TopoGraphOverlayRegistration } from '@ontrails/topographer';
29
+ import type { TopoGraphOverlayRegistration } from '@ontrails/topography';
30
30
  import { findAppModule } from '@ontrails/cli';
31
31
 
32
32
  import {
@@ -75,7 +75,7 @@ const getImportScanner = (loader: TranspilerLoader): Bun.Transpiler => {
75
75
  * @remarks
76
76
  * A fresh-loaded module may expose functions whose deferred relative imports
77
77
  * are resolved only when those functions run (for example inside a trail's
78
- * `blaze`). If we deleted the mirror tree immediately after the initial
78
+ * `implementation`). If we deleted the mirror tree immediately after the initial
79
79
  * `import()` resolved, those later resolutions would hit an ENOENT. We keep
80
80
  * the mirrors on disk and clean them up once, on process exit.
81
81
  */
@@ -964,7 +964,7 @@ const mirrorFreshImportGraph = async (
964
964
  * filesystem imports are mirrored into the fresh temp root. The mirror tree
965
965
  * is retained for the lifetime of the process so that deferred relative
966
966
  * `import()`/`require()` calls originating from the loaded module (e.g.
967
- * inside a trail's `blaze`) can still resolve. If the graph walk itself
967
+ * inside a trail's `implementation`) can still resolve. If the graph walk itself
968
968
  * fails, the partially-written mirror is removed immediately so failed
969
969
  * loads do not leak disk space.
970
970
  */