@ontrails/cli 1.0.0-beta.3 → 1.0.0-beta.4

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.
@@ -1,3 +1,3 @@
1
1
  $ oxlint ./src
2
2
  Found 0 warnings and 0 errors.
3
- Finished in 24ms on 18 files with 93 rules using 24 threads.
3
+ Finished in 18ms on 18 files with 93 rules using 24 threads.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # @ontrails/cli
2
2
 
3
+ ## 1.0.0-beta.4
4
+
5
+ ### Major Changes
6
+
7
+ - API simplification: unified trail model, intent enum, run, metadata.
8
+
9
+ **BREAKING CHANGES:**
10
+
11
+ - `hike()` removed — use `trail()` with optional `follow: [...]` field
12
+ - `follows` renamed to `follow` (singular, matching `ctx.follow()`)
13
+ - `topo.hikes` removed — single `topo.trails` map
14
+ - `kind: 'hike'` removed — everything is `kind: 'trail'`
15
+ - `readOnly`/`destructive` booleans replaced by `intent: 'read' | 'write' | 'destroy'`
16
+ - `implementation` field renamed to `run`
17
+ - `markers` field renamed to `metadata`
18
+ - `testHike` renamed to `testFollows`, `HikeScenario` to `FollowScenario`
19
+ - `blaze()` now returns the surface handle (`Command` for CLI, `Server` for MCP)
20
+
21
+ ### Patch Changes
22
+
23
+ - Updated dependencies
24
+ - @ontrails/core@1.0.0-beta.4
25
+
3
26
  ## 1.0.0-beta.3
4
27
 
5
28
  ### Minor Changes
package/README.md CHANGED
@@ -11,7 +11,7 @@ import { z } from 'zod';
11
11
 
12
12
  const greet = trail('greet', {
13
13
  input: z.object({ name: z.string().describe('Who to greet') }),
14
- implementation: (input) => Result.ok(`Hello, ${input.name}!`),
14
+ run: (input) => Result.ok(`Hello, ${input.name}!`),
15
15
  });
16
16
 
17
17
  const app = topo('myapp', { greet });
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAS,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EACL,MAAM,EAKP,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAElE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAMjD,+CAA+C;AAC/C,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;CAC1B;AAED,oCAAoC;AACpC,MAAM,WAAW,uBAAuB;IACtC,aAAa,CAAC,EAAE,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,GAAG,SAAS,CAAC;IACzE,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IACrE,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,GAAG,SAAS,CAAC;IAClC,YAAY,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;CAC1C;AAiND,eAAO,MAAM,gBAAgB,GAC3B,KAAK,IAAI,EACT,UAAU,uBAAuB,KAChC,UAAU,EAiBZ,CAAC"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAS,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EACL,MAAM,EAKP,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAElE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAMjD,+CAA+C;AAC/C,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;CAC1B;AAED,oCAAoC;AACpC,MAAM,WAAW,uBAAuB;IACtC,aAAa,CAAC,EAAE,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,GAAG,SAAS,CAAC;IACzE,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IACrE,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,GAAG,SAAS,CAAC;IAClC,YAAY,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;CAC1C;AAgND,eAAO,MAAM,gBAAgB,GAC3B,KAAK,IAAI,EACT,UAAU,uBAAuB,KAChC,UAAU,EAiBZ,CAAC"}
package/dist/build.js CHANGED
@@ -90,7 +90,7 @@ const reportResult = async (options, ctx) => {
90
90
  const executeTrail = async (t, validatedInput, ctxOverrides, options) => {
91
91
  const ctx = await resolveContext(ctxOverrides, options);
92
92
  const layers = options?.layers ?? [];
93
- const impl = composeLayers(layers, t, t.implementation);
93
+ const impl = composeLayers(layers, t, t.run);
94
94
  return impl(validatedInput, ctx);
95
95
  };
96
96
  /** Create the execute function for a CLI command. */
@@ -120,12 +120,12 @@ const createExecute = (t, fields, _flags, options) => async (parsedArgs, parsedF
120
120
  return result;
121
121
  };
122
122
  /** Derive and merge flags for a trail. */
123
- const buildFlags = (fields, destructive, options) => {
123
+ const buildFlags = (fields, intent, options) => {
124
124
  let flags = toFlags(fields);
125
125
  if (options?.presets) {
126
126
  flags = mergeFlags(options.presets.flat(), flags);
127
127
  }
128
- if (destructive) {
128
+ if (intent === 'destroy') {
129
129
  flags = mergeFlags(dryRunPreset(), flags);
130
130
  }
131
131
  return flags;
@@ -134,30 +134,29 @@ const buildFlags = (fields, destructive, options) => {
134
134
  const toCliCommand = (t, options) => {
135
135
  const { group, name } = parseTrailId(t.id);
136
136
  const fields = deriveFields(t.input, t.fields);
137
- const flags = buildFlags(fields, t.destructive, options);
137
+ const flags = buildFlags(fields, t.intent, options);
138
138
  return {
139
139
  args: [],
140
140
  description: t.description,
141
- destructive: t.destructive,
142
141
  execute: createExecute(t, fields, flags, options),
143
142
  flags,
144
143
  group,
145
144
  idempotent: t.idempotent,
145
+ intent: t.intent,
146
146
  layers: options?.layers,
147
147
  name,
148
- readOnly: t.readOnly,
149
148
  trail: t,
150
149
  };
151
150
  };
152
151
  export const buildCliCommands = (app, options) => {
153
152
  const commands = [];
154
153
  for (const item of app.list()) {
155
- if (item.kind !== 'trail' && item.kind !== 'hike') {
154
+ if (item.kind !== 'trail') {
156
155
  continue;
157
156
  }
158
157
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
159
158
  const t = item;
160
- if (t.markers?.['internal'] === true) {
159
+ if (t.metadata?.['internal'] === true) {
161
160
  continue;
162
161
  }
163
162
  commands.push(toCliCommand(t, options));
package/dist/build.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
package/dist/command.d.ts CHANGED
@@ -39,8 +39,7 @@ export interface CliCommand {
39
39
  readonly args: CliArg[];
40
40
  readonly trail: AnyTrail;
41
41
  readonly layers?: Layer[] | undefined;
42
- readonly readOnly?: boolean | undefined;
43
- readonly destructive?: boolean | undefined;
42
+ readonly intent: 'read' | 'write' | 'destroy';
44
43
  readonly idempotent?: boolean | undefined;
45
44
  execute(parsedArgs: Record<string, unknown>, parsedFlags: Record<string, unknown>, ctx?: Partial<TrailContext>): Promise<Result<unknown, Error>>;
46
45
  }
@@ -1 +1 @@
1
- {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAMzE;;;;GAIG;AAEH,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAMvC,mEAAmE;AACnE,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;IACzE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAMD,iCAAiC;AACjC,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAMD,4DAA4D;AAC5D,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAE1C,OAAO,CACL,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,GAAG,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAC1B,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;CACpC"}
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAMzE;;;;GAIG;AAEH,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAMvC,mEAAmE;AACnE,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;IACzE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAMD,iCAAiC;AACjC,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAMD,4DAA4D;AAC5D,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAE1C,OAAO,CACL,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,GAAG,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAC1B,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;CACpC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ontrails/cli",
3
- "version": "1.0.0-beta.3",
3
+ "version": "1.0.0-beta.4",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/index.ts",
@@ -15,8 +15,8 @@ import { defaultOnResult } from '../on-result.js';
15
15
  describe('blaze', () => {
16
16
  test('smoke test: buildCliCommands + toCommander wiring does not throw', () => {
17
17
  const t = trail('ping', {
18
- implementation: () => Result.ok('pong'),
19
18
  input: z.object({}),
19
+ run: () => Result.ok('pong'),
20
20
  });
21
21
  const app = topo('smoke-test', { ping: t });
22
22
 
@@ -33,8 +33,8 @@ describe('blaze', () => {
33
33
 
34
34
  test('uses defaultOnResult when none provided', () => {
35
35
  const t = trail('echo', {
36
- implementation: (input: { msg: string }) => Result.ok(input.msg),
37
36
  input: z.object({ msg: z.string() }),
37
+ run: (input: { msg: string }) => Result.ok(input.msg),
38
38
  });
39
39
  const app = topo('default-on-result', { echo: t });
40
40
 
@@ -67,9 +67,8 @@ describe('blaze', () => {
67
67
 
68
68
  try {
69
69
  const t = trail('greet', {
70
- implementation: (input: { name: string }) =>
71
- Result.ok(`Hello, ${input.name}!`),
72
70
  input: z.object({ name: z.string() }),
71
+ run: (input: { name: string }) => Result.ok(`Hello, ${input.name}!`),
73
72
  });
74
73
  const app = topo('e2e-test', { greet: t });
75
74
 
@@ -36,9 +36,8 @@ const requireCommand = (commands: ReturnType<typeof buildCliCommands>) => {
36
36
  describe('buildCliCommands', () => {
37
37
  test('builds commands from a simple app with one trail', () => {
38
38
  const t = trail('greet', {
39
- implementation: (input: { name: string }) =>
40
- Result.ok(`Hello, ${input.name}`),
41
39
  input: z.object({ name: z.string() }),
40
+ run: (input: { name: string }) => Result.ok(`Hello, ${input.name}`),
42
41
  });
43
42
  const app = makeApp(t);
44
43
  const commands = buildCliCommands(app);
@@ -49,13 +48,12 @@ describe('buildCliCommands', () => {
49
48
 
50
49
  test('builds grouped subcommands from dotted trail IDs', () => {
51
50
  const show = trail('entity.show', {
52
- implementation: (input: { id: string }) => Result.ok({ id: input.id }),
53
51
  input: z.object({ id: z.string() }),
52
+ run: (input: { id: string }) => Result.ok({ id: input.id }),
54
53
  });
55
54
  const add = trail('entity.add', {
56
- implementation: (input: { name: string }) =>
57
- Result.ok({ name: input.name }),
58
55
  input: z.object({ name: z.string() }),
56
+ run: (input: { name: string }) => Result.ok({ name: input.name }),
59
57
  });
60
58
  const app = makeApp(show, add);
61
59
  const commands = buildCliCommands(app);
@@ -68,11 +66,11 @@ describe('buildCliCommands', () => {
68
66
 
69
67
  test('derives flags from input schema', () => {
70
68
  const t = trail('search', {
71
- implementation: () => Result.ok([]),
72
69
  input: z.object({
73
70
  limit: z.number().optional(),
74
71
  query: z.string(),
75
72
  }),
73
+ run: () => Result.ok([]),
76
74
  });
77
75
  const app = makeApp(t);
78
76
  const { flags } = requireCommand(buildCliCommands(app));
@@ -84,11 +82,11 @@ describe('buildCliCommands', () => {
84
82
  expect(limitFlag?.required).toBe(false);
85
83
  });
86
84
 
87
- test('adds --dry-run for destructive trails', () => {
85
+ test('adds --dry-run for destroy intent trails', () => {
88
86
  const t = trail('entity.delete', {
89
- destructive: true,
90
- implementation: () => Result.ok(),
91
87
  input: z.object({ id: z.string() }),
88
+ intent: 'destroy',
89
+ run: () => Result.ok(),
92
90
  });
93
91
  const app = makeApp(t);
94
92
  const commands = buildCliCommands(app);
@@ -100,8 +98,8 @@ describe('buildCliCommands', () => {
100
98
  test('calls onResult with correct context', async () => {
101
99
  let captured: ActionResultContext | undefined;
102
100
  const t = trail('ping', {
103
- implementation: (input: { msg: string }) => Result.ok(input.msg),
104
101
  input: z.object({ msg: z.string() }),
102
+ run: (input: { msg: string }) => Result.ok(input.msg),
105
103
  });
106
104
  const app = makeApp(t);
107
105
  const commands = buildCliCommands(app, {
@@ -122,11 +120,11 @@ describe('buildCliCommands', () => {
122
120
  test('validates input before calling implementation', async () => {
123
121
  let implCalled = false;
124
122
  const t = trail('strict', {
125
- implementation: () => {
123
+ input: z.object({ name: z.string() }),
124
+ run: () => {
126
125
  implCalled = true;
127
126
  return Result.ok('done');
128
127
  },
129
- input: z.object({ name: z.string() }),
130
128
  });
131
129
  const app = makeApp(t);
132
130
  const commands = buildCliCommands(app);
@@ -143,11 +141,11 @@ describe('buildCliCommands', () => {
143
141
  test('applies layers in order', async () => {
144
142
  const order: string[] = [];
145
143
  const t = trail('layered', {
146
- implementation: (input: { x: string }) => {
144
+ input: z.object({ x: z.string() }),
145
+ run: (input: { x: string }) => {
147
146
  order.push('impl');
148
147
  return Result.ok(input.x);
149
148
  },
150
- input: z.object({ x: z.string() }),
151
149
  });
152
150
  const app = makeApp(t);
153
151
  const commands = buildCliCommands(app, {
@@ -186,11 +184,11 @@ describe('buildCliCommands', () => {
186
184
  test('uses provided createContext factory', async () => {
187
185
  let usedRequestId: string | undefined;
188
186
  const t = trail('ctx-test', {
189
- implementation: (_input: Record<string, never>, ctx: TrailContext) => {
187
+ input: z.object({}),
188
+ run: (_input: Record<string, never>, ctx: TrailContext) => {
190
189
  usedRequestId = ctx.requestId;
191
190
  return Result.ok('ok');
192
191
  },
193
- input: z.object({}),
194
192
  });
195
193
  const app = makeApp(t);
196
194
  const commands = buildCliCommands(app, {
@@ -204,11 +202,11 @@ describe('buildCliCommands', () => {
204
202
  test('converts kebab-case flags back to camelCase for input', async () => {
205
203
  let receivedInput: unknown;
206
204
  const t = trail('camel', {
207
- implementation: (input) => {
205
+ input: z.object({ sortOrder: z.string() }),
206
+ run: (input) => {
208
207
  receivedInput = input;
209
208
  return Result.ok('ok');
210
209
  },
211
- input: z.object({ sortOrder: z.string() }),
212
210
  });
213
211
  const app = makeApp(t);
214
212
  const commands = buildCliCommands(app);
@@ -48,7 +48,6 @@ const expectSameDate = (value: string | undefined, expected: Date) => {
48
48
 
49
49
  describe('autoIterateLayer', () => {
50
50
  const paginatedTrail = trail('list-items', {
51
- implementation: () => Result.ok({ hasMore: false, items: [] }),
52
51
  input: z.object({
53
52
  all: z.boolean().optional(),
54
53
  cursor: z.string().optional(),
@@ -58,6 +57,7 @@ describe('autoIterateLayer', () => {
58
57
  items: z.array(z.string()),
59
58
  nextCursor: z.string().optional(),
60
59
  }),
60
+ run: () => Result.ok({ hasMore: false, items: [] }),
61
61
  });
62
62
 
63
63
  test('collects paginated results with --all flag', async () => {
@@ -112,8 +112,8 @@ describe('autoIterateLayer', () => {
112
112
 
113
113
  test('ignores non-paginated trails', () => {
114
114
  const simpleTrail = trail('simple', {
115
- implementation: (input: { name: string }) => Result.ok(input.name),
116
115
  input: z.object({ name: z.string() }),
116
+ run: (input: { name: string }) => Result.ok(input.name),
117
117
  });
118
118
 
119
119
  const impl: Implementation<{ name: string }, string> = async (input) =>
@@ -132,14 +132,12 @@ describe('autoIterateLayer', () => {
132
132
 
133
133
  describe('dateShortcutsLayer', () => {
134
134
  const dateTrail = trail('events', {
135
- implementation: (input: {
136
- since?: string | undefined;
137
- until?: string | undefined;
138
- }) => Result.ok(input),
139
135
  input: z.object({
140
136
  since: z.string().optional(),
141
137
  until: z.string().optional(),
142
138
  }),
139
+ run: (input: { since?: string | undefined; until?: string | undefined }) =>
140
+ Result.ok(input),
143
141
  });
144
142
 
145
143
  test("expands 'today' to correct date", async () => {
@@ -180,8 +178,8 @@ describe('dateShortcutsLayer', () => {
180
178
 
181
179
  test('ignores trails without date range fields', () => {
182
180
  const noDateTrail = trail('no-dates', {
183
- implementation: (input: { name: string }) => Result.ok(input.name),
184
181
  input: z.object({ name: z.string() }),
182
+ run: (input: { name: string }) => Result.ok(input.name),
185
183
  });
186
184
 
187
185
  const impl: Implementation<{ name: string }, string> = async (input) =>
@@ -62,9 +62,8 @@ const requireCommand = (
62
62
  describe('toCommander', () => {
63
63
  test('creates a Commander program with correct commands', () => {
64
64
  const t = trail('greet', {
65
- implementation: (input: { name: string }) =>
66
- Result.ok(`Hello, ${input.name}`),
67
65
  input: z.object({ name: z.string() }),
66
+ run: (input: { name: string }) => Result.ok(`Hello, ${input.name}`),
68
67
  });
69
68
  const app = makeApp(t);
70
69
  const commands = buildCliCommands(app);
@@ -78,12 +77,12 @@ describe('toCommander', () => {
78
77
 
79
78
  test('grouped commands create parent/subcommand structure', () => {
80
79
  const show = trail('entity.show', {
81
- implementation: () => Result.ok({}),
82
80
  input: z.object({ id: z.string() }),
81
+ run: () => Result.ok({}),
83
82
  });
84
83
  const add = trail('entity.add', {
85
- implementation: () => Result.ok({}),
86
84
  input: z.object({ name: z.string() }),
85
+ run: () => Result.ok({}),
87
86
  });
88
87
  const app = makeApp(show, add);
89
88
  const commands = buildCliCommands(app);
@@ -100,7 +99,6 @@ describe('toCommander', () => {
100
99
 
101
100
  test('flag types map correctly to Commander options', () => {
102
101
  const t = trail('search', {
103
- implementation: () => Result.ok([]),
104
102
  input: z.object({
105
103
  format: z.enum(['json', 'text']).optional(),
106
104
  limit: z.number().optional(),
@@ -108,6 +106,7 @@ describe('toCommander', () => {
108
106
  tags: z.array(z.string()).optional(),
109
107
  verbose: z.boolean().optional(),
110
108
  }),
109
+ run: () => Result.ok([]),
111
110
  });
112
111
  const app = makeApp(t);
113
112
  const commands = buildCliCommands(app);
@@ -125,8 +124,8 @@ describe('toCommander', () => {
125
124
  describe('boolean flag negation', () => {
126
125
  test('boolean flags get --no-<name> negation options', () => {
127
126
  const t = trail('check', {
128
- implementation: () => Result.ok('ok'),
129
127
  input: z.object({ strict: z.boolean() }),
128
+ run: () => Result.ok('ok'),
130
129
  });
131
130
  const app = makeApp(t);
132
131
  const commands = buildCliCommands(app);
@@ -142,8 +141,8 @@ describe('toCommander', () => {
142
141
 
143
142
  test('--no-<flag> sets value to false via parseAsync', async () => {
144
143
  const t = trail('check', {
145
- implementation: () => Result.ok('ok'),
146
144
  input: z.object({ strict: z.boolean().default(true) }),
145
+ run: () => Result.ok('ok'),
147
146
  });
148
147
  const app = makeApp(t);
149
148
  const commands = buildCliCommands(app, { onResult: noopResult });
@@ -157,8 +156,8 @@ describe('toCommander', () => {
157
156
 
158
157
  test('--flag sets boolean value to true via parseAsync', async () => {
159
158
  const t = trail('check', {
160
- implementation: () => Result.ok('ok'),
161
159
  input: z.object({ strict: z.boolean().default(false) }),
160
+ run: () => Result.ok('ok'),
162
161
  });
163
162
  const app = makeApp(t);
164
163
  const commands = buildCliCommands(app, { onResult: noopResult });
@@ -174,8 +173,8 @@ describe('toCommander', () => {
174
173
  describe('strict number parsing', () => {
175
174
  const buildNumberProgram = () => {
176
175
  const t = trail('count', {
177
- implementation: () => Result.ok('ok'),
178
176
  input: z.object({ limit: z.number() }),
177
+ run: () => Result.ok('ok'),
179
178
  });
180
179
  const app = makeApp(t);
181
180
  const commands = buildCliCommands(app);
@@ -247,8 +246,8 @@ describe('toCommander', () => {
247
246
  { expected: -5, input: '-5' },
248
247
  ])('accepts valid number "$input"', async ({ expected, input }) => {
249
248
  const t = trail('count', {
250
- implementation: () => Result.ok('ok'),
251
249
  input: z.object({ limit: z.number() }),
250
+ run: () => Result.ok('ok'),
252
251
  });
253
252
  const app = makeApp(t);
254
253
  const commands = buildCliCommands(app, { onResult: noopResult });
@@ -263,8 +262,8 @@ describe('toCommander', () => {
263
262
 
264
263
  test('sets version when provided', () => {
265
264
  const t = trail('ping', {
266
- implementation: () => Result.ok('pong'),
267
265
  input: z.object({}),
266
+ run: () => Result.ok('pong'),
268
267
  });
269
268
  const app = makeApp(t);
270
269
  const commands = buildCliCommands(app);
@@ -283,8 +282,8 @@ describe('toCommander', () => {
283
282
  // This test verifies the error handling structure exists.
284
283
  // Full integration would need process.exit mocking.
285
284
  const t = trail('fail', {
286
- implementation: () => Result.ok('ok'),
287
285
  input: z.object({}),
286
+ run: () => Result.ok('ok'),
288
287
  });
289
288
  const app = makeApp(t);
290
289
  const commands = buildCliCommands(app);
package/src/build.ts CHANGED
@@ -155,7 +155,7 @@ const executeTrail = async (
155
155
  ): Promise<Result<unknown, Error>> => {
156
156
  const ctx = await resolveContext(ctxOverrides, options);
157
157
  const layers = options?.layers ?? [];
158
- const impl = composeLayers(layers, t, t.implementation);
158
+ const impl = composeLayers(layers, t, t.run);
159
159
  return impl(validatedInput, ctx);
160
160
  };
161
161
 
@@ -207,14 +207,14 @@ const createExecute =
207
207
  /** Derive and merge flags for a trail. */
208
208
  const buildFlags = (
209
209
  fields: readonly Field[],
210
- destructive: boolean | undefined,
210
+ intent: 'read' | 'write' | 'destroy',
211
211
  options?: BuildCliCommandsOptions
212
212
  ): CliFlag[] => {
213
213
  let flags = toFlags(fields);
214
214
  if (options?.presets) {
215
215
  flags = mergeFlags(options.presets.flat(), flags);
216
216
  }
217
- if (destructive) {
217
+ if (intent === 'destroy') {
218
218
  flags = mergeFlags(dryRunPreset(), flags);
219
219
  }
220
220
  return flags;
@@ -227,19 +227,18 @@ const toCliCommand = (
227
227
  ): CliCommand => {
228
228
  const { group, name } = parseTrailId(t.id);
229
229
  const fields = deriveFields(t.input, t.fields);
230
- const flags = buildFlags(fields, t.destructive, options);
230
+ const flags = buildFlags(fields, t.intent, options);
231
231
 
232
232
  return {
233
233
  args: [],
234
234
  description: t.description,
235
- destructive: t.destructive,
236
235
  execute: createExecute(t, fields, flags, options),
237
236
  flags,
238
237
  group,
239
238
  idempotent: t.idempotent,
239
+ intent: t.intent,
240
240
  layers: options?.layers,
241
241
  name,
242
- readOnly: t.readOnly,
243
242
  trail: t,
244
243
  };
245
244
  };
@@ -251,13 +250,13 @@ export const buildCliCommands = (
251
250
  const commands: CliCommand[] = [];
252
251
 
253
252
  for (const item of app.list()) {
254
- if (item.kind !== 'trail' && item.kind !== 'hike') {
253
+ if (item.kind !== 'trail') {
255
254
  continue;
256
255
  }
257
256
 
258
257
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
259
258
  const t = item as AnyTrail;
260
- if (t.markers?.['internal'] === true) {
259
+ if (t.metadata?.['internal'] === true) {
261
260
  continue;
262
261
  }
263
262
  commands.push(toCliCommand(t, options));
package/src/command.ts CHANGED
@@ -61,8 +61,7 @@ export interface CliCommand {
61
61
  readonly args: CliArg[];
62
62
  readonly trail: AnyTrail;
63
63
  readonly layers?: Layer[] | undefined;
64
- readonly readOnly?: boolean | undefined;
65
- readonly destructive?: boolean | undefined;
64
+ readonly intent: 'read' | 'write' | 'destroy';
66
65
  readonly idempotent?: boolean | undefined;
67
66
 
68
67
  execute(