@ultimat3/action 25.2.0 → 26.1.0

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/README.md CHANGED
@@ -256,7 +256,7 @@ Under the default style:
256
256
  | `checkout` (single word) | `POST /api/checkouts/invoke` | `checkout` |
257
257
 
258
258
  **One name, three surfaces** — `openapi.json`'s `x-ultimate.mcpTool`,
259
- `describeAction().mcp.tool` (what `x actions describe --json`, `x actions list --json`, the
259
+ `describeAction().mcp.tool` (what `x actions show --json`, `x actions list --json`, the
260
260
  `actions.describe` dev MCP tool and the `/_x` Routes panel show) and the catalog `@ultimat3/mcp`
261
261
  serves. It was two until 2026-08: a `toToolName()` here snake_cased the published ones to
262
262
  `publish_post` while the server answered only `publishPost`, so an agent that read the published
@@ -839,7 +839,7 @@ never a pass — the assertion says which code got in the way and names `input:`
839
839
  | `X_ACTION_POLICY_MISSING` | registration without `policy:` | add `policy: can('…')` |
840
840
  | `X_RATE_LIMIT_INVALID` | `rateLimit:` with a non-positive or non-finite half — `windowMs: 0` refills infinitely. Owned by `@ultimat3/http`, which owns the conversion | make both positive, or delete the block |
841
841
  | `X_ACTION_DEPRECATION_INVALID` | `deprecated:` with a `since`/`sunset` that is not a date | use an ISO-8601 instant |
842
- | `X_INPUT_INVALID` | input failed the Standard Schema. Carries the rejections **twice**: the flattened line in `cause`, and the structured list in `meta.issues` — one value rendered two ways, `As of 2026-08-24` | `x actions describe <name> --json` |
842
+ | `X_INPUT_INVALID` | input failed the Standard Schema. Carries the rejections **twice**: the flattened line in `cause`, and the structured list in `meta.issues` — one value rendered two ways, `As of 2026-08-24` | `x actions show <name> --json` |
843
843
  | `X_IDEMPOTENCY_CONFLICT` | key reused with a new payload / still in flight | new key, or retry later |
844
844
  | `X_IDEMPOTENCY_KEY_INVALID` | `Idempotency-Key:` sent blank (`Headers.get()` answers `''`, not `null`) or past 255 characters | send one unique value per request, or omit the header |
845
845
  | `X_IDEMPOTENCY_NOT_SHARED` | `configureIdempotency({ scope: 'shared' })` over a per-process (or scope-less) store | install `postgresIdempotencyStore({ executor, origin, reclaimAfterMs })` at boot |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultimat3/action",
3
- "version": "25.2.0",
3
+ "version": "26.1.0",
4
4
  "description": "The action primitive: one declaration projected to route, OpenAPI, client, MCP tool, job handle, tests",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -35,12 +35,12 @@
35
35
  "test": "bun test"
36
36
  },
37
37
  "dependencies": {
38
- "@ultimat3/cache": "25.2.0",
39
- "@ultimat3/core": "25.2.0",
40
- "@ultimat3/db": "25.2.0",
41
- "@ultimat3/entity": "25.2.0",
42
- "@ultimat3/http": "25.2.0",
43
- "@ultimat3/policy": "25.2.0",
44
- "@ultimat3/schema": "25.2.0"
38
+ "@ultimat3/cache": "26.1.0",
39
+ "@ultimat3/core": "26.1.0",
40
+ "@ultimat3/db": "26.1.0",
41
+ "@ultimat3/entity": "26.1.0",
42
+ "@ultimat3/http": "26.1.0",
43
+ "@ultimat3/policy": "26.1.0",
44
+ "@ultimat3/schema": "26.1.0"
45
45
  }
46
46
  }
package/src/action.ts CHANGED
@@ -348,7 +348,7 @@ export function describeAction(target: AnyAction): ActionDescriptor {
348
348
  // a first honest `expose: false` read as a withdrawn capability and demand a major bump.
349
349
  expose: isMcpExposed(mcp),
350
350
  // The export name verbatim, which is the only name `@ultimat3/mcp` will answer a
351
- // `tools/call` for. A derived one made every descriptor reader — `x actions describe
351
+ // `tools/call` for. A derived one made every descriptor reader — `x actions show
352
352
  // --json`, the `actions.describe` dev tool, the `/_x` panel — name a tool no surface
353
353
  // serves. `x.manifest.json` is not among them: it copies `expose` and `description` only.
354
354
  tool: name,
package/src/client.ts CHANGED
@@ -224,7 +224,7 @@ function toUltimateError(
224
224
  issues: issuesFromWire(body['issues']),
225
225
  meta: metaFromWire(body['meta']),
226
226
  cause: stringOr(body['cause'] ?? body['detail'], `${name} failed with ${status}`),
227
- fix: stringOr(body['fix'], `x actions describe ${name} --json`),
227
+ fix: stringOr(body['fix'], `x actions show ${name} --json`),
228
228
  // RFC-9457's `type` IS a documentation URI, so a server that sends no `docs` extension has
229
229
  // still offered one. Both travel, in preference order: `??` picked `docs` on presence alone,
230
230
  // so a `javascript:` one hid a perfectly good `type` behind it. `remoteDocs` takes the first
@@ -100,7 +100,7 @@ function assertDocumented(target: AnyAction, name: string): void {
100
100
  /**
101
101
  * The refusal when the published document does not name this action at its route. `name` is
102
102
  * whatever `.named()` was handed — nothing validates its alphabet — so it is screened where it
103
- * enters the `x actions describe` command (security audit of plan 101 sweep 1c).
103
+ * enters the `x actions show` command (security audit of plan 101 sweep 1c).
104
104
  */
105
105
  export function documentedDrift(
106
106
  path: string,
@@ -113,7 +113,7 @@ export function documentedDrift(
113
113
  : `OpenAPI document serves ${path} as ${owner}, so ${name} is not in the published contract`,
114
114
  owner === undefined
115
115
  ? 'x verify --json # the contract suite is a step of it'
116
- : `x actions describe ${renderFixShellArg(name, '<action>')} --json # then rename it, or pin its own route with http: { path } in the ${name} definition`,
116
+ : `x actions show ${renderFixShellArg(name, '<action>')} --json # then rename it, or pin its own route with http: { path } in the ${name} definition`,
117
117
  );
118
118
  }
119
119
 
@@ -138,7 +138,7 @@ function assertSampleable(target: AnyAction, name: string): void {
138
138
  const described = gaps.map((path) => describeSampleGap(target.input, path)).join(', ');
139
139
  throw new ContractDriftError(
140
140
  `${name}: no value can be synthesized for ${described}, so the denial would be unproven`,
141
- `contractTestsFor(${name}, { input: { … } }) # x actions describe ${name} --json prints the schema`,
141
+ `contractTestsFor(${name}, { input: { … } }) # x actions show ${name} --json prints the schema`,
142
142
  );
143
143
  }
144
144
 
@@ -196,7 +196,7 @@ async function expectDenied(
196
196
  if (error.code !== 'X_INPUT_INVALID') throw error;
197
197
  throw new ContractDriftError(
198
198
  `${name} failed with ${error.code} before its policy decided, so the denial is unproven`,
199
- `pass \`input:\` to contractTestsFor(${name}) — x actions describe ${name} --json prints the schema`,
199
+ `pass \`input:\` to contractTestsFor(${name}) — x actions show ${name} --json prints the schema`,
200
200
  );
201
201
  }
202
202
  throw new ContractDriftError(
@@ -185,7 +185,7 @@ export class IdempotentReplayRedactedError extends UltimateError {
185
185
  super({
186
186
  code: 'X_IDEMPOTENT_REPLAY_REDACTED',
187
187
  cause: `the answer stored for idempotency key "${key}" had a secret-named field redacted when it settled, so it cannot be replayed faithfully`,
188
- fix: "x actions describe '<action>' --json # the call already ran and showed its secret once — read its effect with a query; a new Idempotency-Key runs it again (a second credential)",
188
+ fix: "x actions show '<action>' --json # the call already ran and showed its secret once — read its effect with a query; a new Idempotency-Key runs it again (a second credential)",
189
189
  meta: { key, replayed: true },
190
190
  });
191
191
  }
package/src/errors.ts CHANGED
@@ -187,9 +187,9 @@ export class InputInvalidError extends UltimateError {
187
187
  super({
188
188
  code: 'X_INPUT_INVALID',
189
189
  cause: `input for ${subject} "${name}" failed validation: ${detail}`,
190
- fix: `x actions describe ${renderFixShellArg(name, '<action-name>')} --json # prints the expected input schema`,
190
+ fix: `x actions show ${renderFixShellArg(name, '<action-name>')} --json # prints the expected input schema`,
191
191
  // A remote caller holds the published schema — the MCP `inputSchema`, the OpenAPI request
192
- // body — and cannot run `x actions describe`.
192
+ // body — and cannot run `x actions show`.
193
193
  callerFix:
194
194
  'correct the fields named in cause to match the published input schema (the tool inputSchema, or the OpenAPI request body) and send again — the same input is refused the same way',
195
195
  ...(issues === undefined ? {} : { meta: { issues } }),
@@ -208,7 +208,7 @@ export class OutputInvalidError extends UltimateError {
208
208
  super({
209
209
  code: 'X_OUTPUT_INVALID',
210
210
  cause: `action "${name}" returned a value its output schema rejects: ${detail}`,
211
- fix: `x actions describe ${renderFixShellArg(name, '<action-name>')} --json # compare the handler's return against \`output:\``,
211
+ fix: `x actions show ${renderFixShellArg(name, '<action-name>')} --json # compare the handler's return against \`output:\``,
212
212
  });
213
213
  }
214
214
  }
@@ -353,7 +353,7 @@ export class RpcFailedError extends UltimateError {
353
353
  super({
354
354
  code: 'X_RPC_FAILED',
355
355
  cause: `${name} returned HTTP ${status} without a problem+json body`,
356
- fix: `check the gateway in front of the app, then: x actions describe ${renderFixShellArg(name, '<action-name>')} --json`,
356
+ fix: `check the gateway in front of the app, then: x actions show ${renderFixShellArg(name, '<action-name>')} --json`,
357
357
  retry: retryForStatus('X_RPC_FAILED', status),
358
358
  });
359
359
  }
package/src/mutator.ts CHANGED
@@ -226,7 +226,7 @@ function wrap<TInput extends StandardSchemaV1, TOutput extends StandardSchemaV1>
226
226
  return self;
227
227
  }
228
228
 
229
- /** The descriptor's name for a policy — the manifest and `x actions describe` print this. */
229
+ /** The descriptor's name for a policy — the manifest and `x actions show` print this. */
230
230
  function strategyOf(conflict: ConflictPolicy): MutatorDescriptor['conflict'] {
231
231
  return typeof conflict === 'string' ? conflict : conflict.kind;
232
232
  }