# @sapiom/orchestration-core

## 0.15.7

### Patch Changes

- Updated dependencies [04ebfba]
  - @sapiom/tools@0.47.0
  - @sapiom/agent@0.14.11

## 0.15.6

### Patch Changes

- Updated dependencies [ffc2d22]
- Updated dependencies [16d9e39]
  - @sapiom/tools@0.46.0
  - @sapiom/agent@0.14.10

## 0.15.5

### Patch Changes

- 7741094: `run_local`: the tool description now states that a step paused on an `agents.launch`, `models.launch` or `models.coding.launch` handle resumes locally with that call's stubbed result (for `agents.launch`, the child's `AgentRunResultPayload`), and that only a pause on a signal no stubbed launch produced (a webhook, an approval) resumes with `{}`. It previously named only `models.coding.launch`, so authors of parent/child agents assumed the child result could not be exercised locally. `@sapiom/agent-core` adds regression tests for the `agents.launch` and `models.launch` resume paths; runtime behaviour is unchanged.
- Updated dependencies [bc61687]
- Updated dependencies [7741094]
- Updated dependencies [6714512]
  - @sapiom/tools@0.45.0
  - @sapiom/agent@0.14.9

## 0.15.4

### Patch Changes

- Updated dependencies [a7731b9]
- Updated dependencies [a893708]
  - @sapiom/tools@0.44.0
  - @sapiom/agent@0.14.8

## 0.15.3

### Patch Changes

- Updated dependencies [7f8c99e]
  - @sapiom/tools@0.43.0
  - @sapiom/agent@0.14.7

## 0.15.2

### Patch Changes

- Updated dependencies [687a69b]
- Updated dependencies [173ddce]
  - @sapiom/tools@0.42.0
  - @sapiom/agent@0.14.6

## 0.15.1

### Patch Changes

- 772f154: `@sapiom/tools`: new connectors. `connectors.slack` wraps the gateway's Slack methods
  (`postMessage`, `update`, `postEphemeral`, `addReaction`, `removeReaction`, `replies`,
  `userInfo`) on `POST /connectors/v1/slack/methods/<method>`. `connectors.mcp(slug)` is a
  client for the MCP relay at `POST /connectors/v1/<slug>/mcp` (`listTools()`,
  `callTool(name, args)`), with `connectors.linear` and `connectors.notion` for the default
  slugs; a JSON-RPC error throws `McpRelayError`. All are bound on `ctx.sapiom.connectors` and stubbed for `run_local`, overridable
  under `connectors.slack.<method>`, `connectors.<slug>.listTools|callTool`, or
  `connectors.mcp.listTools|callTool`. Without a `callTool` override, an MCP `callTool` succeeds
  only for a tool returned by the step's latest `listTools()` on that connector and otherwise
  answers `isError: true`, as the relay does. A
  malformed override adds a stub warning.

  `@sapiom/agent-core`: the authoring skill gains "Calling Slack, Linear, and Notion from a step".

- Updated dependencies [772f154]
  - @sapiom/tools@0.41.0
  - @sapiom/agent@0.14.5

## 0.15.0

### Minor Changes

- 5bb66c6: Emit custom events from the SDK, the CLI and the MCP — the start verb next to
  `signal`'s resume verb.

  `emitEvent({ type, payload, id? })` posts to `POST /v1/workflows/events`
  and returns the receipt verbatim: `{ receiptId, outcome, duplicate, fireIds }`.
  It fans out by type to every active `event` trigger the tenant armed and starts
  0..N new runs. `outcome: "unmatched"` is a success, not an error — nothing
  subscribes to that type. `id` is the sender's dedup identity, so reposting
  it returns the original receipt and starts nothing new; omit it and every call
  is a distinct event. `sapiom agents emit <type> --payload <json> [--event-id
<id>]` and `sapiom_dev_agents_emit_event` wrap it, and `parseEventPayload`
  rejects a payload that is not a JSON object, which the run-input fold would
  otherwise drop silently.

  Events start runs, signals resume them, so `signal()` stays the resume verb and
  now surfaces the server's `message` next to `matched` — `matched` counts the
  runs that actually resumed, so it under-reports a partial fanout and a `0` does
  not prove nothing was waiting.

### Patch Changes

- 89d91d4: The platform-rules stamp is now written into a project's `AGENTS.md` when it is scaffolded, from the release constants in `@sapiom/agent-core`, instead of being hard-coded in every template and gallery example. Scaffold output is unchanged: a new project still carries a concrete `<!-- sapiom-authoring-rules release=… digest=… -->` and `sapiom_dev_agents_check` still warns when it differs from the served copy. Gallery examples, `examples/AUTHORING.md` and the `@sapiom/tools` JSDoc keep the pointer to the served rules but no longer record a release, so a content release touches the two constants and the four skill copies only.
- 06adb78: `@sapiom/tools`: new `events` capability. A step emits a tenant event with its own run
  credential through `ctx.sapiom.events.emit({ type, payload, id? })` (also
  `import { events } from "@sapiom/tools"`), which calls the gateway's
  `POST /agents/v1/events` and resolves with the 202 receipt
  `{ receiptId, outcome, duplicate, fireIds }`. Pass a stable `id` to make a retry safe.
  The `run_local` stub answers `outcome: "unmatched"` unless overridden under `events.emit`.

  `@sapiom/agent-core`: the authoring skill's trigger section names `ctx.sapiom.events.emit`.

- Updated dependencies [3a22965]
- Updated dependencies [89d91d4]
- Updated dependencies [21f060b]
- Updated dependencies [0e4dce3]
- Updated dependencies [97c2c61]
- Updated dependencies [c4411a0]
- Updated dependencies [92ab6df]
- Updated dependencies [8a38f6d]
- Updated dependencies [06adb78]
  - @sapiom/tools@0.40.0
  - @sapiom/agent@0.14.4

## 0.14.3

### Patch Changes

- 0c6e945: Fix `agents.run`/`agents.launch` reporting a REFUSED DISPATCH — an unknown slug (404),
  input the engine's pre-gate rejects (400), a transport fault — by throwing an untyped
  error out of the calling step. Because a step throw feeds the engine's retry machinery,
  a coordinator dispatching several children by slug lost its whole run to one typo: the
  step retried a deterministic failure to `maxAttemptsPerStep` and then failed.

  The two entry points now report it according to what each returns:

  - **`run` resolves it as data** — `status: "rejected"`, `executionId: null`, and a
    structured `AgentRunError` (`{ code, message, status, details }`) whose `details`
    keeps the platform's own response body. Its result is already discriminated on
    `status`, and a coordinator treats "the child failed" and "the child never started"
    as one fact, so `if (result.status !== "completed")` stays the single branch and no
    try/catch is needed.

    `"rejected"` is deliberately narrow: it promises nothing is running, so it is used
    only when the platform's answer proves nothing was created (404, 400/422, 401/403).
    A 5xx, or a response lost after the platform accepted the request, may have created
    a child whose id never came back — those resolve `"unknown"` with a `null`
    `executionId`, so re-dispatch guidance stays safe.

  - **`launch` throws `AgentDispatchError`** (exported from the package root, with
    `.code`, `.status`, `.details`, and `.toRunError()`). It owes the caller a pausable
    handle, and a dispatch that created no child has none — a handle with a null
    `executionId` that cannot be paused on would misrepresent itself. Catch it and
    `fail()` the step. Uncaught it is an ordinary step throw, so it still retries to the
    cap; making it terminal-without-retry needs the engine's non-retryable error set to
    admit it, which is separate work. The error's `childMayExist` draws the same
    proven-vs-ambiguous distinction as the `"rejected"`/`"unknown"` split, so a `launch`
    caller can tell whether a retry is safe.

  `wait()` no longer throws. Hitting `timeoutMs` resolves `status: "timed_out"`; a status
  read the platform refuses, or one that keeps faulting, resolves `status: "unknown"`.
  Both keep `executionId`, because the run exists and can be checked on later. A
  transient 5xx, 408, 429 or transport fault is ridden out for a few consecutive polls
  before `"unknown"`, rather than spending the whole `timeoutMs` on doomed requests — and
  a single rate-limit answer no longer ends an hour-long wait.

  Of the three new statuses only `"rejected"` means nothing is running, so it is the only
  one on which re-dispatching is safe. `"unknown"` and `"timed_out"` name a child that may
  still be working — retry those with an `idempotencyKey` or not at all.

  **Breaking.** A refused dispatch used to throw out of `run`; it now resolves. If you
  branch on `status === "failed"`, change it to `status !== "completed"` — otherwise a
  rejected dispatch falls straight through that branch and feeds `output: null`
  downstream instead of failing loudly. The old surface documented `status` as
  `"completed" | "failed"`, so that spelling was the documented one. `launch` still
  throws, now with a typed error instead of a bare `Error`.

  Also breaking at the type level, and a no-op for code that already branches on
  `status !== "completed"`: `AgentRunResult.executionId` and `RunHandle.executionId` widen
  to `string | null` (a delayed `launch({ at })` handle now reports `null` rather than
  `""`), and `AgentRunResult.status` widens from `ExecutionStatus` to `AgentRunStatus`,
  adding `"rejected"`, `"unknown"` and `"timed_out"`. `RunHandle` still `extends
DispatchHandle`, so every handle you receive is pausable.

  `AgentRunSpec`, `AgentRunResult`, `AgentRunStatus`, `AgentRunError`, `AgentRunErrorCode`,
  `AgentRunHandle`, `AgentExecutionStatus` and `AgentDispatchError` are now exported from
  the package root, matching the `models` equivalents.

  In `createStubClient` (and so `run_local`), `agents.launch` resolves through the
  overrides — `agents.launch` then the shared `agents.run`, merged over the built-in
  defaults, matching `models.coding.launch`. It previously built a completed run
  unconditionally, so the try/catch the docs require was impossible to cover in a local
  test. A stubbed `{ status: "rejected" }` throws from `launch` and resolves from `run`,
  mirroring the real split; `{ status: "failed" }` covers a child that ran and failed, and
  the resume payload a paused step receives follows the stubbed status. A partial
  `{ status: "rejected" }` fills in a real `AgentRunError` (so `result.error.code` reads
  the same under the stub as in production), a function override returning a promise is
  awaited, and a delayed `launch({ at })` returns production's shape — `executionId: null`
  with a trigger correlation id.

- 85610db: Structured `llm.run` calls no longer fail silently when the token cap runs out before the answer (SAP-3280).

  Thinking tokens are spent out of `request.max_tokens`. A routed label may emit a `thinking` block before the forced tool call, so a cap sized for the answer alone can be exhausted mid-deliberation: the turn ends before the tool call is ever emitted, `structuredOf` correctly returns `undefined`, and the step throws a `TypeError` from destructuring it. Deliberation is longest on the hardest, most ambiguous inputs, so an under-sized cap passes every test and every easy case and then drops exactly the item that was worth the most.

  **`llm.run` now throws `LlmStructuredOutputTruncatedError`** when `output` was set and the turn stopped on `max_tokens` without a usable structured result — either no matching `tool_use` block came back (`reason: "no-tool-call"`) or the cap landed partway through the tool call, leaving an `input` missing a field the schema requires (`reason: "incomplete-input"`). The schema is walked to every depth — nested objects, array elements, `allOf` / `anyOf` / `oneOf` branches — so a cut inside `{ result: {} }` is caught, and `error.missingPath` names the first absent field as a path (`result.priority`, `items[1].score`); the message quotes it. An empty `input` is judged the same way: it throws when the schema requires anything and is returned when it requires nothing. The reason union is exported as `LlmTruncationReason`. The error names the tool, the cap the request carried, and the fix, and carries the verbatim `response`. It is exported from `@sapiom/tools`.

  Everything gated on that `stop_reason`, so nothing else changes: a truncated plain-text reply is still returned (it is readable, and bounding a reply on purpose is legitimate), an empty or partial structured result from a turn that ended any other way still reads as before, and a field the schema does not require is still the model's to omit.

  **Breaking:** if you already handled the empty structured result yourself, wrap the call and catch `LlmStructuredOutputTruncatedError` — `error.response` is the verbatim response you used to receive.

  **The examples now size the cap for thinking plus output.** The authoring skill's structured-output example and the `llm` JSDoc examples said `256` and `512`; every one now uses `4096` and says, next to the example, that thinking counts against the cap, that billing settles on the tokens actually produced, and that the cap is still not free — the gateway's admission weight scales with it. The skill also shows catching the error and `fail()`-ing the step, because the engine will otherwise retry the identical under-capped request.

- Updated dependencies [68c02c1]
- Updated dependencies [ccf480a]
- Updated dependencies [afa4569]
- Updated dependencies [0c6e945]
- Updated dependencies [85610db]
  - @sapiom/tools@0.39.0
  - @sapiom/agent@0.14.3

## 0.14.2

### Patch Changes

- Updated dependencies [e32eb67]
- Updated dependencies [ca1580c]
  - @sapiom/tools@0.38.0
  - @sapiom/agent@0.14.2

## 0.14.1

### Patch Changes

- f1ec121: Local `check` and runs now bundle with a `createRequire` banner, so dependencies that call `require()` at runtime (for example `googleapis` / `google-auth-library`) resolve at runtime instead of failing with esbuild's "Dynamic require not supported".
- Updated dependencies [6e5e2e1]
  - @sapiom/tools@0.37.0
  - @sapiom/agent@0.14.1

## 0.14.0

### Minor Changes

- 4c9bafb: Stop restating the platform rules in npm-shipped files; point at the served copy
  and stamp the pointer (SAP-3181).

  The rules that are true of Sapiom regardless of the installed SDK — one-off call
  vs agent, the capability catalog, database lifetime, trigger kinds, App Links,
  which capability calls an LLM, composing deployed agents, platform vocabulary —
  are served by the Sapiom API at `GET /v1/agents/authoring-rules`. Every copy
  this repo used to ship of them was frozen at publish or scaffold time and could
  never be corrected; that is how the 7-day database claim and the two-kind
  trigger list reached customers.

  - The `sapiom-agent-authoring` skill's platform chapters are now a short
    summary plus a pointer to the served section, bracketed by
    `<!-- section: … -->` markers so a Studio session can splice the served text
    in. The authoring mechanics (step model, directives, `ctx.shared`,
    pause/resume, stubs) are unchanged.
  - Every scaffolded `AGENTS.md` (both `@sapiom/agent-core` templates, the
    `@sapiom/cli` template and all gallery examples) and `examples/AUTHORING.md`
    carry a one-paragraph pointer and a stamp:
    `<!-- sapiom-authoring-rules release=… digest=… -->`.
  - `@sapiom/tools`' JSDoc on the `model` field of `llm.run`, `llm.submit`,
    `models.run` and `models.coding.run` points at the served rule instead of
    restating it.
  - `sapiom_dev_agents_check` reads the stamps in the project's `AGENTS.md` and
    skill, makes one best-effort anonymous read of the served endpoint's
    `X-Sapiom-Content-*` headers, and warns when a stamp differs from the served
    copy. No stamp means no request; unreachable means no warning. The wording is
    "differs from", never "older than" — digests do not order.
  - `@sapiom/agent-core` exports the stamp vocabulary
    (`AUTHORING_RULES_*`, `parseAuthoringRulesStamp`,
    `renderAuthoringRulesStamp`, `authoringRulesDriftWarning`), and
    `node scripts/authoring-rules-stamp.mjs --from-served` moves every stamp in
    the repo to the current release at once.

- 5d18ba3: Expose all four backend trigger kinds from the local authoring MCP (SAP-3174).
  `sapiom_dev_agents_schedule` now accepts `kind: "event"` (+ `eventType`) and
  `kind: "webhook"` alongside `schedule_cron` / `schedule_once`. A webhook create
  returns the public hook URL, the shown-once signing secret, and the signing
  scheme in the tool result (HMAC-SHA256 over `timestamp.eventId.rawBody`, sent as
  `X-Sapiom-Timestamp` / `X-Sapiom-Event-Id` / `X-Sapiom-Signature`), and the
  description says when a webhook trigger fits versus an App Link `/hook/*`
  receiver (third-party senders cannot produce our HMAC). `_schedule_inspect` and
  `_schedule_cancel` describe every kind; the new `sapiom_dev_agents_schedule_secret`
  tool rotates, completes a rotation of, or revokes a webhook secret.

  `@sapiom/agent-core` gains the matching `ScheduleKind` members, the webhook /
  event fields on `ScheduleSummary`, `CreateScheduleResult`, and
  `rotateScheduleSecret` / `completeScheduleSecretRotation` / `revokeScheduleSecret`.

  **Breaking (types only, `@sapiom/agent-core`):** `ScheduleFireRecord.scheduledFor`
  is now `string | null` — an event or webhook fire has no occurrence time, so code
  that did `new Date(fire.scheduledFor)` must guard for `null` (or read
  `fire.receiptId` for those kinds). `ScheduleSummary` gains five required fields
  (`eventType`, `publicId`, `secretVersion`, `graceUntil`, `revokedAt`, all
  nullable) that the server always returns; hand-built `ScheduleSummary` values
  (test fakes, adapters) must add them. `ScheduleKind` widens to include `"event"`
  and `"webhook"`, so an exhaustive `switch` over it needs the two new arms. No
  runtime behaviour changes for existing cron / one-off callers.

  The offline `AUTHORING_INSTRUCTIONS` fallback and the `sapiom-agent-authoring`
  skill gain a triggers paragraph teaching the same thing; the served-text change
  is version-gated on `@sapiom/mcp` >= 0.15 because older clients are never
  offered the new kinds.

### Patch Changes

- Updated dependencies [421439b]
- Updated dependencies [4c9bafb]
  - @sapiom/agent@0.14.0
  - @sapiom/agent-runtime@0.7.2
  - @sapiom/tools@0.36.1

## 0.13.5

### Patch Changes

- e690f7c: Re-sync the offline teaching fallbacks with the 2026-09 served-text release (SAP-3180), so a
  session whose startup fetch fails learns the same four things an online session does:

  - **Vault semantics** — secrets are set in the dashboard per deployed agent; agent code reads
    `ctx.sapiom.vault.get` and cannot write; a Sapiom-managed resource is used through its
    handle, never by copying its credentials into Vault.
  - **`ctx.sapiom.agents.launch`** — fire-and-forget dispatch of a deployed agent for any caller
    that must return fast (a webhook receiver); `agents.run` waits for the terminal state.
  - **Receipts and manual replay** of inbound events, pointed at the REST surface until a tool
    exists.
  - **App Link webhooks** — `/hook/*` forwarding, off by default behind `webhooksEnabled`, 60 s
    hold, byte-exact body so third-party signature schemes verify inside the app.

  `@sapiom/mcp`'s `AUTHORING_INSTRUCTIONS` (primer 2.9) and `@sapiom/harness`'s
  `DEFAULT_SYSTEM_PROMPT` (1.1) move with their digest pins; the 2.9 primer also drops the
  `deadlineMinutes` clause that offered a knob `llm.run` does not have. The
  `sapiom-agent-authoring` skill gains a pointer to where these are taught, not a restatement.

  Naming note: the 2.9 primer spells the receipts and replay routes with their real
  `/v1/workflows/` REST prefix, because no tool or docs page covers them yet and the routes
  are the only surface that exists. The primer's guard is therefore scoped to the per-step
  executions path it was written about. The Studio system prompt, which is Agent Studio
  visible text and subject to the terminology gate, names the same routes without the prefix
  and defers to the primer for the full paths.

- Updated dependencies [6ab81d9]
- Updated dependencies [7eb17c5]
  - @sapiom/tools@0.36.0
  - @sapiom/agent@0.13.2

## 0.13.4

### Patch Changes

- Updated dependencies [44d7f76]
- Updated dependencies [5808e8f]
  - @sapiom/tools@0.35.0
  - @sapiom/agent@0.13.1

## 0.13.3

### Patch Changes

- Updated dependencies [917c930]
- Updated dependencies [41ce013]
  - @sapiom/agent@0.13.0
  - @sapiom/tools@0.34.0
  - @sapiom/agent-runtime@0.7.1

## 0.13.2

### Patch Changes

- db81e32: Step code can now tell a local trace from a deployed run, and the stub Postgres DSN no longer points at a host that might answer.

  `AgentExecutionContext` gains `isLocalTrace?: boolean` — `true` under `run_local`, and set by nothing else. The deployed step runner does not set it, so `input.dryRun ?? ctx.isLocalTrace` reads as live in production; the name is qualified precisely because that absence is load-bearing.

  Use it for the I/O `run_local` cannot stub — a raw Postgres socket, third-party HTTP, any client holding its own connection. Resolve it once in the entry step and carry it in `ctx.shared`, since `input` downstream is the previous step's output:

  ```ts
  // entry step
  const dryRun = input.dryRun ?? ctx.isLocalTrace ?? false;
  ctx.shared.set("dryRun", dryRun);
  ```

  An explicit `{ "dryRun": false }` still forces the live path. Capability calls (`ctx.sapiom.*`) are already stubbed locally and need no guard.

  Separately, the stub `database.get` / `database.create` DSN now uses a host in the reserved `.invalid` TLD (RFC 6761) instead of `localhost`. A template that dialed the old DSN reached whatever Postgres happened to be listening on the author's own machine and failed with an opaque TLS error; it now fails at name resolution on any conforming resolver. Treat this as a backstop rather than a guard — a resolver that hijacks NXDOMAIN can still return an address — and gate the dial on `ctx.isLocalTrace`.

- 054f749: `sapiom-sandbox-preview` skill now teaches App Links. It says plainly that a
  sandbox preview URL is temporary (it dies with the resource's `ttl`, along with
  any bookmark or Slack message it was pasted into), and adds a "Make it durable /
  share it" section that routes "share this", "send this to my team", "a permanent
  link", "keep it alive", "my link died" to `sapiom_dev_app_publish` — with the
  five facts an agent otherwise gets wrong: wake-on-demand cold start, org-scoped
  by default (public needs `confirmPublic` + `dailySpendCapUsd`, so ask first),
  republish-in-place on the same slug, text-only bundles, and the ~10 MiB cap. The
  frontmatter `description` picks up the durability triggers so the skill fires on
  a "link that won't die" ask.
- Updated dependencies [db81e32]
- Updated dependencies [9165f18]
- Updated dependencies [6fb3273]
  - @sapiom/agent@0.12.2
  - @sapiom/tools@0.33.0

## 0.13.1

### Patch Changes

- Updated dependencies [065c9ca]
  - @sapiom/tools@0.32.0
  - @sapiom/agent@0.12.1

## 0.13.0

### Minor Changes

- 555475d: Make `ctx.shared.set()` on the SDK's `InMemoryContextStore` an atomic
  whole-snapshot quota gate. `runLocal` now constructs this store with step
  context; hosts that have not adopted this store version may enforce the contract
  only at execution boundaries during rollout. The store measures the complete
  candidate as compact JSON UTF-8 before committing it, so oversized writes throw
  `CTX_SHARED_SIZE_LIMIT_EXCEEDED` and retain the previous state.

  Publish the bounded `CTX_SHARED_SERIALIZATION_FAILED` terminal error contract
  for circular references, BigInt values, throwing `toJSON` methods, and other
  `JSON.stringify` failures. Completion serializers and runners recognize the
  new code through the closed platform-error registry and fail the step on its
  current attempt without retrying. Ordinary JSON omission and coercion semantics
  remain unchanged.

  **Breaking:** `InMemoryContextStore.set()` can now throw synchronously for an
  oversized or unserializable candidate. Existing local agents that wrote such
  state now fail non-retryably on attempt 0. Migrate bulk state to durable storage
  and keep only compact, JSON-compatible values or references in `ctx.shared`. If
  a store is seeded with legacy invalid state, replace an offending key with a
  value small enough to bring the complete candidate within the quota;
  `TypedContextStore` has no `delete()` operation.

### Patch Changes

- 52efab3: `sapiom-agent-authoring` skill + scaffold `AGENTS.md`: system-design teaching for multi-stage builds. New "Composing Deployed Agents" section — one agent per PROJECT; a multi-stage system is several small projects composed via `ctx.sapiom.agents.run`, with a worked coordinator example — and the scaffold's "keep exactly one `defineAgent` export" rule now says so inline, so it reads as a per-project rule rather than a design instruction to inline every stage. Also drops the "pass `smart` if you must pin" no-op from the label rule (omitting `model` is the recommendation; `smart` already is the default).
- Updated dependencies [555475d]
  - @sapiom/agent@0.12.0
  - @sapiom/agent-runtime@0.7.0

## 0.12.2

### Patch Changes

- 9afeda9: Add a closed, versioned retry-classification contract for platform-owned step
  errors. `CTX_SHARED_SIZE_LIMIT_EXCEEDED` and
  `STEP_INPUT_VALIDATION_FAILED` now settle executions terminally without
  consuming workflow retries; unknown, author, and capability errors keep the
  legacy retry behavior.

  `StepInputValidationError` now exposes a dedicated bounded wire payload with
  stable `code`, `version`, `stepName`, and `retryable: false` fields while its
  ordinary JSON representation continues carrying raw Zod issues for in-process
  callers. Hosts receive a normalizing `parseNonRetryableStepErrorPayload`
  registry plus `serializeStepCompletionError()` for completion reporters, and
  may implement the additive atomic active-dispatch failure capability required
  for terminal settlement. Older stores omit that capability and retain the
  legacy retry path.

- Updated dependencies [9afeda9]
  - @sapiom/agent@0.11.0
  - @sapiom/agent-runtime@0.6.0

## 0.12.1

### Patch Changes

- Updated dependencies [d7d480a]
  - @sapiom/tools@0.31.0
  - @sapiom/agent@0.10.2

## 0.12.0

### Minor Changes

- 00b8814: Adds `inspectStep(opts, client)` — fetches one step attempt's full-fidelity `input`/`output`/`error`/`logs` (`GET /executions/:id/steps/:stepId/io`), at a higher size cap than `inspect()`'s own `steps[]` bounds its aggregate read to. Reach for it when a step's fields on the execution projection look truncated.

  - New exported `inspectStep`, `InspectStepOptions`, `StepIoDetail`, and `decodeStepIoDetail` (the tolerant decoder, mirroring `decodeExecutionProjection`'s degradation posture).
  - `StepProjection` gains an optional `id` field (the step-attempt row id) — previously decoded from the wire but silently dropped; needed to call `inspectStep` from an `inspect()` read. `null` on a read from a server that doesn't report it — existing consumers are unaffected.

### Patch Changes

- 5a8eeea: `sapiom-agent-authoring` skill: teaches the LLM call-surface rule from step
  code (`llm.run` one-shot vs `models.run` platform-driven loop vs `agents.run`
  deployed-agent dispatch, with a worked example against the "reply with only
  JSON" + string-parsing mistake) and settles the platform's naming
  conventions (the overloaded "agent"/"run"/"task"/"session"/"dispatch" terms,
  and "label" as the author-facing term for a `model:` value). Synced across
  the canonical source, both scaffold templates, and the Claude Code plugin
  copy. `@sapiom/tools`: corrected stale `agent.run`/`agent.coding` naming in
  `models/index.ts`'s doc comments — the actual exported namespace is
  `models`.
- Updated dependencies [5a8eeea]
- Updated dependencies [5a8eeea]
  - @sapiom/tools@0.30.0
  - @sapiom/agent@0.10.1

## 0.11.4

### Patch Changes

- af764cd: Publish the authoritative 256 KiB `ctx.shared` whole-snapshot contract from
  `@sapiom/agent`: `CTX_SHARED_QUOTA_CONTRACT`,
  `MAX_SHARED_SNAPSHOT_BYTES`, `measureCtxSharedSnapshotBytes`,
  `findCtxSharedSizeViolation`, `CtxSharedSizeLimitExceededError`,
  `ctxSharedSizeLimitExceededPayloadSchema`, and
  `isCtxSharedSizeLimitExceededPayload`, plus the
  `CtxSharedSizeLimitPhase`, `CtxSharedSizeViolation`,
  `CtxSharedSizeLimitExceededPayload`, and
  `CtxSharedSizeLimitExceededErrorOptions` types.

  `@sapiom/agent-runtime` now publicly exports `stepCompletionErrorSchema`,
  preserves compatible structured quota payloads through protocol-1 parsing, and
  re-exports the canonical compatibility limit.

  Structured quota payloads include the reporting contract `version` and retain
  unknown non-empty future phases during mixed-version rollouts; current error
  construction remains limited to the three published enforcement phases.

  This release defines measurement and error contracts; it does not make
  `ctx.shared.set()` an atomic size gate or add local/final host-boundary
  enforcement by itself. Host versions must adopt the contract. Authoring skills,
  scaffolds, and MCP guidance now document compact ID/reference usage and that
  enforcement can vary during rollout.

- Updated dependencies [af764cd]
  - @sapiom/agent@0.10.0
  - @sapiom/agent-runtime@0.5.0

## 0.11.3

### Patch Changes

- 04b7df5: Expose structured `CodingRunHttpError` details for failed coding requests and clarify repository-handle usage.

  Add guidance for handling deterministic coding-repository failures.

- Updated dependencies [04b7df5]
  - @sapiom/tools@0.29.0
  - @sapiom/agent@0.9.6

## 0.11.2

### Patch Changes

- Updated dependencies [b768b18]
- Updated dependencies [beb0f6f]
  - @sapiom/tools@0.28.0
  - @sapiom/agent@0.9.5

## 0.11.1

### Patch Changes

- Updated dependencies [2b133e2]
- Updated dependencies [beb3139]
  - @sapiom/tools@0.27.0
  - @sapiom/agent@0.9.4

## 0.11.0

### Minor Changes

- b1d791b: Add an artifact-first Studio run workspace for local and cloud agents. Studio now
  collects schema-driven input, streams chronological attempt evidence, renders
  bounded outputs with Rendered and Raw views, and provides an isolated Focus mode
  for inspecting input, output, state, directives, logs, and recorded capability
  calls.

  Local agent execution now emits start and settled trace events with timing,
  directive, shared-state, log, and capability-call evidence. Desktop development
  launches rebuild Harness first so Electron always opens the current Studio UI.

## 0.10.7

### Patch Changes

- f21f6a6: Windows: sessions create and deliver their prompt, the canvas refreshes, and nothing pops a console window

  The desktop app was unusable on Windows — every `POST /api/sessions` answered
  `500 {"error":"internal error"}`, and when a session did start, its first
  prompt never reached the agent. Root-caused on a real machine and fixed
  end to end.

  - **Sessions.** Claude Code's own native auto-updater had renamed the running
    `claude.exe` to `claude.exe.old.<ts>` inside the app-managed npm prefix and
    never written the replacement, so every spawn failed while `doctor` (which
    shells `where`) still reported the agent present. Boot now verifies the
    agent actually spawns, repairs the managed install when it doesn't, and sets
    `DISABLE_AUTOUPDATER` for installs the app owns. The refusal itself names
    the situation instead of "target could not be determined".
  - **The first prompt.** It is held until the session reports ready, which only
    happens when the generated `SessionStart` hook POSTs back — and Claude Code
    runs hooks through Git Bash on Windows, which cannot resolve a `.cmd`, so
    the desktop's `node.cmd`-only shims meant the hook never ran. The host now
    ships npm's extensionless sh shim too, a 20s hook-timeout fallback rescues a
    session whose hook chain is broken (gated on Claude's blocking-prompt
    screens so it can never answer a trust dialog), `emit.cjs` gets budgets a
    cold loopback survives (SessionStart only — the other hooks block the
    agent), and multi-line prompts are paste-wrapped under ConPTY, which hides
    the bracketed-paste announcement.
  - **Console windows.** The `sapiom-dev` MCP server was launched via `npx`,
    whose `cmd.exe` sat on screen as a persistent blank window; closing it
    killed the server and every later tool call hung. The app now installs
    `@sapiom/mcp` into its own prefix and launches it through the app binary
    (GUI subsystem — no console can exist), and every `child_process` call
    across the harness, agent-core, the MCP and the desktop passes
    `windowsHide`.
  - **Canvas.** `fs.watch` reports native separators, so the watcher's
    POSIX-literal comparison never matched on Windows and `canvas.reload` was
    never published — every canvas hot-reload was silently dead there (the
    "Preparing your agent" placeholder outliving a finished install was the
    visible symptom).
  - **Diagnosis.** 500s now carry the real message (and errno) instead of
    "internal error", the desktop tees its main-process log to
    `<userData>/logs/main.log`, and spawn failures map to actionable 4xx.
  - **Also:** Git is provisioned from git-for-windows' checksum-pinned MinGit
    when a Windows machine has none (template clone and deploy shell out to a
    real `git`); client-supplied `cwd` is normalized server-side and the SPA's
    path helpers understand both separators; gateway requests time out instead
    of hanging an MCP tool call for minutes; and the updater falls back to
    HTTP/1.1, names a GitHub 429 for what it is, and bounds every path that can
    reach GitHub.

## 0.10.6

### Patch Changes

- 651c407: Anchor esbuild to the agent project in `check()`, local runs, and `bundleForDeploy()` (`absWorkingDir`). Given no working directory esbuild adopts the caller's cwd and enumerates that cwd's ancestor chain in addition to the project's — so for the Studio Canvas, whose caller is the harness package buried inside the app, a directory nowhere near the user's agent could fail the build: reported as `Cannot read directory "../../../../../../../..": result too large` followed by `Could not resolve <project>/index.ts` on a project that was readable, installed, and passed `check` from a terminal (where cwd _is_ the project). Diagnostics become legible as a side effect — paths print relative to the working directory, so a project error reads `index.ts` instead of `../../../../../Users/me/agents/x/index.ts`.

  Also report the real cause when a bundle fails because the project directory itself can't be read. `describeBundleFailure` probed only for a missing `node_modules`, which an unreadable or vanished project directory also answers — so a failure whose esbuild error was `Cannot read directory "…": permission denied` told the user to run `npm install` in a directory nothing could list. It now names the directory and the reason (permission denied, no longer exists, not a directory) and keeps the raw esbuild detail.

## 0.10.5

### Patch Changes

- 19b8bbb: Install a new agent's dependencies on scaffold, and turn the Canvas's "Could not resolve …" render error into an actionable "run npm install" hint

  The Canvas step-graph extraction (`check` / `loadDefinition`) esbuild-bundles a project's `index.ts` resolving its imports — `@sapiom/agent`, `zod`, … — from the project's own `node_modules`. A newly-scaffolded (or freshly-cloned) agent whose deps were never installed therefore failed its very first, unprompted Canvas render with a raw esbuild wall (`Could not resolve "@sapiom/agent" … Could not resolve "zod"`), which the failure panel relayed verbatim.

  Two fixes:

  - `scaffold()` gains an opt-in `installDependencies` flag (returned as `dependenciesInstalled`), and the `sapiom_dev_agents_scaffold` MCP tool — the Studio's create path — now passes it, so a new agent opens with a working Canvas. Best-effort and non-fatal: a missing/offline npm still yields a successful scaffold. The `installProjectDependencies` helper (previously demo-only inside the harness's example seed) now lives in `@sapiom/agent-core` and is shared by both.
  - `check` and `loadDefinition` now route bundle failures through `describeBundleFailure`, which detects the "no `node_modules` + unresolved import" case and returns `Dependencies are not installed. Run \`npm install\` in <dir>, then try again.` (preserving the raw esbuild detail). Every other bundle failure's message is unchanged.

## 0.10.4

### Patch Changes

- 0bf040f: Fix `check` / `sapiom_dev_agents_check` always failing with `TYPECHECK_FAILED` on Windows

  `runTypecheck` ran the project's compiler via the bare `node_modules/.bin/tsc` shim. On Windows that extensionless file is a POSIX sh script (npm ships the real launcher as `tsc.cmd`), which `execFileSync` cannot execute — it threw a spawn error with empty output, so the check reported `TYPECHECK_FAILED` with the generic "Run `tsc --noEmit` for details" hint even when the project's own `tsc --noEmit` passed cleanly. It now runs TypeScript's JS entry (`node_modules/typescript/bin/tsc`) under the current Node binary, which is platform-independent and avoids `.bin`/`.cmd`/PATHEXT/shell entirely.

## 0.10.3

### Patch Changes

- 1000510: Describe deploy as a synthesized bundle of current local source, distinguish
  account-free local validation from metered cloud builds and production runs,
  and make execution inspection's cost-agnostic evidence boundary explicit.
- 25fc26f: Make local agent runs parse step inputs through their Zod schemas like production, normalize relative check directories, stage and retry gallery clones across branch-propagation delays, and clarify that local validation stubs Sapiom capability traffic without sandboxing arbitrary author-code side effects.
- 9addb66: Keep Agent Studio workspace discovery consistent across scanning, live updates, and the folder picker; preserve Studio state when cloning gallery templates; and clarify bundled starter network requirements.
- Updated dependencies [1ac32ef]
  - @sapiom/tools@0.26.1

## 0.10.2

### Patch Changes

- 87636c1: Make bundled starters work from a fresh Agent Studio session by preserving Studio-owned state, writing the project discovery marker, and handing Claude the local scaffold MCP tool directly.
- Updated dependencies [cc1ac0c]
  - @sapiom/tools@0.26.0
  - @sapiom/agent@0.9.3

## 0.10.1

### Patch Changes

- Updated dependencies [27a1079]
  - @sapiom/tools@0.25.0
  - @sapiom/agent@0.9.2

## 0.10.0

### Minor Changes

- be2b81b: Studio feedback: `sendFeedback` SDK function + the `sapiom_send_feedback` MCP tool (SAP-2286).

  `@sapiom/agent-core` gains `sendFeedback({ message, context?, clientMeta? }, client)`, which POSTs
  to `/v1/studio-feedback` and returns the stored record's id. Because that route sits at the API host
  root rather than under `/v1/workflows`, `GatewayClient` gains one new public method,
  `postAtHostRoot(path, body?)` — a separate method rather than a special-cased path prefix, so a call
  site always declares which base its path is relative to. Every JSON request now funnels through a
  single private `send()` (`openStream` keeps its own handshake path); as a side effect a `NETWORK`
  error message now names the full URL instead of only the base.

  `@sapiom/mcp` registers `sapiom_send_feedback`, which relays a user's feedback along with
  client-side context it gathers itself (package version, platform, arch, node version, environment,
  timestamp) so the model never has to read that off the machine. Internal: `ok`/`fail`/`gatewayClient`
  moved from `tools/agents.ts` to a new `tools/shared.ts`, and `packageVersion()` from `analytics.ts`
  to a new `version.ts`.

### Patch Changes

- 40d1c64: Use Agent and Agent run terminology in scaffolded and published authoring assets.

## 0.9.13

### Patch Changes

- Updated dependencies [c8072cd]
  - @sapiom/agent@0.9.0
  - @sapiom/agent-runtime@0.4.3

## 0.9.12

### Patch Changes

- a1e0e4f: Update the scaffold offline `VERSION_FALLBACK` to the currently published versions (`@sapiom/agent@0.7.1`, `@sapiom/tools@0.23.0`). The previous values had drifted behind the last release, which failed the "fallback matches the workspace version" regression test in `scaffold.test.ts`. Keeping the fallback current means an offline / registry-hiccup scaffold resolves to a version that actually exists on npm instead of failing with a silent ETARGET.
- Updated dependencies [a1e0e4f]
- Updated dependencies [a1e0e4f]
  - @sapiom/tools@0.24.0
  - @sapiom/agent@0.8.0
  - @sapiom/agent-runtime@0.4.2

## 0.9.11

### Patch Changes

- Updated dependencies [55cde7f]
  - @sapiom/tools@0.23.0
  - @sapiom/agent@0.7.1

## 0.9.10

### Patch Changes

- Updated dependencies [3f96e37]
- Updated dependencies [5f875de]
  - @sapiom/agent@0.7.0
  - @sapiom/tools@0.22.1
  - @sapiom/agent-runtime@0.4.1

## 0.9.9

### Patch Changes

- b6b9d16: Harden deploy and local-run input handling:

  - Redact credentials from git error output, so a push URL's embedded token can never leak into an error hint or the deploy stream.
  - On an auth-class deploy-push failure, mint a fresh push credential and retry the push once.
  - Report a superseded build as a distinct, non-alarming outcome (a newer deploy replaced this build) instead of a generic build failure.
  - Default an absent local-run input to `{}`, so a step that reads its input behaves the same locally as it does in a production run.

## 0.9.8

### Patch Changes

- Updated dependencies [68d2352]
  - @sapiom/tools@0.22.0
  - @sapiom/agent@0.6.7

## 0.9.7

### Patch Changes

- Updated dependencies [d00b9e3]
  - @sapiom/tools@0.21.0
  - @sapiom/agent@0.6.6

## 0.9.6

### Patch Changes

- Updated dependencies [4cf0156]
  - @sapiom/tools@0.20.0
  - @sapiom/agent@0.6.5

## 0.9.5

### Patch Changes

- c8eecf0: fix(agent-core): refresh stale offline scaffold version fallback

  `VERSION_FALLBACK` drifted after the last version bump (agent `0.6.2` → `0.6.4`,
  tools `0.17.2` → `0.19.0`), so an offline/registry-hiccup scaffold would pin
  versions that no longer match what's published. Bumped to match the workspace
  package.json, which is what the regression test guards.

## 0.9.4

### Patch Changes

- Updated dependencies [e446a4a]
  - @sapiom/tools@0.19.0
  - @sapiom/agent@0.6.4

## 0.9.3

### Patch Changes

- 0c6bcb4: Fix `scaffold()`'s offline fallback versions (`@sapiom/agent@0.1.1`, `@sapiom/tools@0.1.1`) — neither exists on npm anymore (currently published: `agent@0.5.0`, `tools@0.16.0`). Any scaffold that fell back to these (no network, npm registry unreachable, corporate proxy, etc.) produced a project whose first `npm install` failed with `ETARGET`. Bumped to the current published versions and added a regression test that checks the fallback against the workspace's own package versions, so this can't silently drift again.
- Updated dependencies [afc77e3]
  - @sapiom/tools@0.18.0
  - @sapiom/agent@0.6.3

## 0.9.2

### Patch Changes

- 696f111: Ship the skills/ directory in the published package so the bundled sapiom-agent-authoring skill is available after a real install.
- 48fb35c: Correct stub capability path in template docs (models.coding.\*); refresh offline scaffold version fallback.

  - Replace stale `agent.coding.run` / `agent.coding.launch` references with the
    correct `models.coding.run` / `models.coding.launch` in all template docs
    (`templates/default/AGENTS.md`, `templates/coding-pause/AGENTS.md`,
    `templates/coding-pause/README.md`). The old path matched no stub, causing
    silent no-ops in local runs.
  - Bump `VERSION_FALLBACK` in `scaffold.ts` from `{ agent: "0.1.1", tools: "0.1.1" }`
    to `{ agent: "0.6.2", tools: "0.17.1" }` to match current package versions.
    Only affects offline scaffolds (the online path still resolves npm-latest).

- 58ec57f: Fix Sapiom skill registration in harness sessions. `@sapiom/agent-core` now
  exposes its `package.json` through the `exports` map so consumers can resolve
  its bundled `skills/` directory; previously `require.resolve` threw
  `ERR_PACKAGE_PATH_NOT_EXPORTED` and the skill silently never loaded. The harness
  skill-plugin resolver also gains a fallback that locates the skills directory by
  resolving the package's main entry when the `package.json` subpath isn't
  exported. Skills register under the `sapiom` plugin namespace, so the
  agent-authoring skill is available as `/sapiom:sapiom-agent-authoring`.
- Updated dependencies [95bfcd1]
- Updated dependencies [bf44229]
- Updated dependencies [dab6d44]
- Updated dependencies [ebfa0bc]
  - @sapiom/analytics-core@0.2.1

## 0.9.1

### Patch Changes

- 7fa17d1: Align agent run and schedule requests with the current API endpoints. This also fixes `@sapiom/tools` `schedules` operations (create/list/get/cancel), which were targeting an outdated endpoint. Public function signatures are unchanged.
- Updated dependencies [7fa17d1]
  - @sapiom/tools@0.17.1

## 0.9.0

### Minor Changes

- d661d57: Emit workflow lifecycle usage analytics from the agent package family via `@sapiom/analytics-core` (source `"agent"`).

  - `@sapiom/agent-core`: `link` / `deploy` / `run` emit one `workflow.link` / `workflow.deploy` / `workflow.run` event each, carrying metadata only — workflow name/id, duration, status, and a machine-readable error code on failure (never inputs, outputs, or error messages). The emitter is constructed lazily at the operation call boundary; `GatewayClient` stays env-free. `runLocal` emits the runtime's step lifecycle events flagged `local: true`.
  - `@sapiom/agent-runtime`: `AgentRunnerCore` accepts an optional `analytics` sink (new `RuntimeAnalytics` host interface — a structural `track()` method, no new dependency) and emits `step.start` / `step.complete` / `step.error` with step name, attempt, and timing. No sink → no events, byte-for-byte previous behavior.

  Telemetry ships dark: without a collector endpoint configured (`SAPIOM_ANALYTICS_ENDPOINT`) every `track` is a silent no-op — zero network calls, zero disk writes. Opt out any time with `SAPIOM_TELEMETRY_DISABLED=1` or `DO_NOT_TRACK=1`. Emission is synchronous enqueue-only and can never change an operation's behavior, results, or errors — collector outages included.

### Patch Changes

- Updated dependencies [3f25008]
- Updated dependencies [55462b3]
- Updated dependencies [d661d57]
- Updated dependencies [aee376a]
  - @sapiom/analytics-core@0.2.0
  - @sapiom/agent-runtime@0.4.0
  - @sapiom/tools@0.17.0
  - @sapiom/agent@0.6.2

## 0.8.0

### Minor Changes

- 3dfbd10: Ship the `sapiom-agent-authoring` skill with every scaffold, and finish the MCP
  instructions rename.

  - New canonical skill (`agent-core/skills/sapiom-agent-authoring/SKILL.md`) with a
    task-shape trigger ("automate a multi-step / scheduled / deployable task"), the full
    authoring guide (`defineAgent`, directives, pause/resume, stubs), and a bootstrap
    step for agents whose client doesn't have the sapiom-dev MCP yet.
  - Both scaffold templates ship it at `.claude/skills/sapiom-agent-authoring/` (auto-loads
    as a project skill in Claude Code) and `AGENTS.md` points to it, so every scaffolded
    project self-documents. A sync test keeps template copies identical to the canonical.
  - `@sapiom/mcp`'s bundled instructions fallback rewritten to the agents/models
    vocabulary (the rename left it on the old text), thinned to lifecycle + canonical
    rules + pointers — deep guidance lives in the skill/AGENTS.md/docs.

### Patch Changes

- 020139a: `check()` now recognizes workflow definitions authored against the pre-rename SDK: `@sapiom/agent` exports `isLegacyOrchestrationDefinition`/`LEGACY_ORCHESTRATION_DEFINITION_BRAND` (the `Symbol.for('sapiom.orchestration.definition')` brand the old `defineOrchestration` attached), and `@sapiom/agent-core`'s `check()` accepts either brand in its export detection — the definition shape is unchanged by the rename, so manifests build identically. `check()` also gains a `typecheck` option (default `true`): pass `typecheck: false` to skip the project's `tsc --noEmit` when only the manifest/graph is needed (esbuild still surfaces bundle-level breakage).
- Updated dependencies [020139a]
  - @sapiom/agent@0.6.1

## 0.7.0

### Minor Changes

- 7a9d57a: Rename the execution-context field `ctx.workflowName` → `ctx.agentName`.

  **Breaking:** a step that reads `ctx.workflowName` must now read `ctx.agentName`. The value is unchanged — the agent's name (slug).

### Patch Changes

- Updated dependencies [7a9d57a]
  - @sapiom/agent@0.6.0
  - @sapiom/agent-runtime@0.3.1

## 0.6.0

### Minor Changes

- cc1261e: Rename the composition SDK to **agents** and the coding/LLM capability to **models**.

  **Breaking — the package names changed. Install the new names; the old ones are deprecated.**

  - Packages: `@sapiom/orchestration` → `@sapiom/agent`, `@sapiom/orchestration-core` → `@sapiom/agent-core`, `@sapiom/orchestration-runtime` → `@sapiom/agent-runtime`. (`@sapiom/create-orchestration` is retired — scaffold with the CLI or the developer MCP.)
  - API: `defineOrchestration` → `defineAgent`; `Orchestration*` types/errors → `Agent*`.
  - `@sapiom/tools`: the `agent` capability namespace is now `models` (e.g. `sapiom.models.coding`); the `orchestrations` namespace is now `agents`.
  - CLI: `sapiom orchestrations …` → `sapiom agents …`.
  - Developer MCP tools: `sapiom_dev_orchestrations_*` → `sapiom_dev_agents_*`.

### Patch Changes

- Updated dependencies [cc1261e]
  - @sapiom/agent@0.5.0
  - @sapiom/agent-runtime@0.3.0
  - @sapiom/tools@0.16.0

## 0.5.0

### Minor Changes

- f2f4fec: Bring `inspect()` / `listExecutions()` to REST `ExecutionProjection` parity (tree + per-node cost + trace refs), replacing the flat inspection shape.

  **Breaking (return shapes):**

  - `inspect(opts, client)` now resolves the decoded `ExecutionProjection` **directly** (previously `{ execution }`). It carries the dispatch tree (`traceRoot`/`traceParent`/`traceId`/`spanId`, `parentExecutionId`/`rootExecutionId`, typed `children`), per-step `spanId`/`events`/`dispatch`, and a structured `StepError` (`trace` is now a `StepErrorTrace` of source-mapped frames, not a string).
  - `listExecutions(client)` now resolves `ExecutionRef[]` **directly** (previously `{ executions }`).
  - The flat `ExecutionDetail` / `StepRecord` types are removed; import the new projection types (`ExecutionProjection`, `StepProjection`, `CostNode`, `ExecutionRef`, `DispatchRef`, `StepError`, `StepEvent`) instead.

  **Cost is honest, never fabricated:** `cost` is `CostNode | null` at run and step granularity. The execution-detail read is cost-agnostic today (authoritative cost lives at `/executions/:id/spend`), so an absent cost decodes to `null`, not a misleading `$0`. `authorizedUsd`/`capturedUsd`/`settleState` are never collapsed when cost is present.

  The engine must emit the corresponding fields (per-node cost, list lineage, named child edges) for the projection to be fully populated; until then `inspect()`/`listExecutions()` degrade honestly rather than throwing. SDK pins move in lockstep with the engine.

## 0.4.5

### Patch Changes

- Updated dependencies [8fd3f71]
  - @sapiom/tools@0.15.0
  - @sapiom/orchestration@0.4.9

## 0.4.4

### Patch Changes

- Updated dependencies [aaf633c]
  - @sapiom/tools@0.14.0
  - @sapiom/orchestration@0.4.8

## 0.4.3

### Patch Changes

- Updated dependencies [cc2bde2]
  - @sapiom/tools@0.13.0
  - @sapiom/orchestration@0.4.7

## 0.4.2

### Patch Changes

- Updated dependencies [019ef30]
  - @sapiom/tools@0.12.0
  - @sapiom/orchestration@0.4.6

## 0.4.1

### Patch Changes

- Updated dependencies [84e44e2]
  - @sapiom/tools@0.11.0
  - @sapiom/orchestration@0.4.5

## 0.4.0

### Minor Changes

- ae1df3c: Scaffold honors `npm_config_registry` / `@scope:registry` when resolving the
  `@sapiom/*` versions to pin

  Version resolution previously hardcoded the public npm registry, so a scaffold
  always pinned public-npm `latest` even when the environment pointed at a
  different registry. It now resolves `latest` from the same registry a plain
  `npm install` would (a scoped `@<scope>:registry` wins over the global
  `npm_config_registry`, which wins over the public default). When that registry
  is non-default, the scaffolded project also gets a matching `.npmrc` so its
  pinned versions are installable. This makes a local registry dev loop work
  end-to-end with no manual pin edits; default scaffolds are unchanged.

### Patch Changes

- a85e665: Add schedules: run a deployed orchestration on a recurring cron schedule or once at a set time.

  - `@sapiom/orchestration-core`: `createSchedule`, `listSchedules`, `getSchedule`, `cancelSchedule`, and `previewCron`.
  - `@sapiom/tools`: a `schedules` namespace (`create`, `list`, `get`, `cancel`).
  - `@sapiom/cli`: `sapiom orchestrations schedule create | list | inspect | cancel | preview`.
  - `@sapiom/mcp`: schedule tools — create, inspect (list/detail + recent fires), cancel, and cron preview.

- Updated dependencies [a85e665]
  - @sapiom/tools@0.10.1

## 0.3.8

### Patch Changes

- Updated dependencies [6ebf569]
  - @sapiom/tools@0.10.0
  - @sapiom/orchestration@0.4.4

## 0.3.7

### Patch Changes

- 30bac1c: Improve the initial git + deploy experience for workflow authoring. Adds `bundleForDeploy` — a local, no-network bundler that inlines local/shared source and externalizes npm dependencies — and smooths first-time git init / deploy so a fresh workflow project deploys cleanly.

  ```ts
  import { bundleForDeploy } from "@sapiom/orchestration-core";

  const bundle = await bundleForDeploy(/* … */);
  ```

- Updated dependencies [30bac1c]
- Updated dependencies [30bac1c]
- Updated dependencies [0361fa7]
  - @sapiom/tools@0.9.0
  - @sapiom/orchestration@0.4.3

## 0.3.6

### Patch Changes

- Updated dependencies [2b94dff]
- Updated dependencies [ac71754]
- Updated dependencies [f078ed5]
  - @sapiom/tools@0.8.0
  - @sapiom/orchestration@0.4.2

## 0.3.5

### Patch Changes

- Updated dependencies [a3cc368]
  - @sapiom/tools@0.7.0
  - @sapiom/orchestration@0.4.1

## 0.3.4

### Patch Changes

- Updated dependencies [56fd77d]
  - @sapiom/orchestration@0.4.0
  - @sapiom/orchestration-runtime@0.2.2

## 0.3.3

### Patch Changes

- Updated dependencies [f41ab95]
  - @sapiom/orchestration@0.3.0
  - @sapiom/orchestration-runtime@0.2.1

## 0.3.2

### Patch Changes

- b2c5612: Move the orchestration authoring SDK onto zod 4 via the bare `zod` import (no
  more `zod/v4` subpath), so installing is just:

  ```sh
  npm install @sapiom/orchestration
  ```

  `zod` is now a regular dependency rather than a peer. Author your step schemas
  with your own `import { z } from "zod"` as usual; a compatibility re-export
  (`import { z } from "@sapiom/orchestration"`) is available for projects pinned
  to an incompatible zod. Scaffolded projects now pin zod 4.

- Updated dependencies [b2c5612]
- Updated dependencies [b2c5612]
  - @sapiom/orchestration@0.2.0
  - @sapiom/orchestration-runtime@0.2.0
  - @sapiom/tools@0.6.0

## 0.3.1

### Patch Changes

- Updated dependencies [5c974b1]
  - @sapiom/tools@0.5.0
  - @sapiom/orchestration@0.1.9

## 0.3.0

### Minor Changes

- e17b2d1: `scaffold` now initializes a git repository with an initial commit, so a freshly scaffolded project is immediately deployable (deploy requires a repo with at least one commit). Best-effort: if `git` is unavailable the project is left uninitialized. `ScaffoldResult` gains `gitInitialized`.

  Adds `waitForExecution` (and `isExecutionTerminal`) to poll an execution until it reaches a terminal state, settles on a pause that needs a signal, or a wait budget elapses — so callers don't hand-roll a poll loop. The `sapiom_dev_orchestrations_inspect` MCP tool gains opt-in `wait` / `maxWaitSeconds` options that use it and return `done` / `waiting` / `hint`; a non-blocking inspect of a still-running execution now also hints to use `wait`.

  Fixes `sapiom_dev_orchestrations_link`: omitting `name` no longer sends an empty name (which the gateway rejected). It now defaults to the orchestration's name read from `index.ts` (matching `defineOrchestration({ name })`), and returns a clear error if no name is available.

### Patch Changes

- e17b2d1: **BREAKING (`@sapiom/tools`):** align the coding-run resume payload with the shape a resumed step actually receives. `CodingResultPayload` now carries `executionEnvironment: { type, id } | null` instead of `sandbox: { name, workspaceRoot }`. Re-attach a resumed run's sandbox with `ctx.sapiom.sandboxes.attach(result.executionEnvironment.id)` (for a `blaxel_sandbox`).

  Adds `codingResultSchema` (runtime validation of the resume payload), `toResumePayload`, `ExecutionEnvironmentRef`, and `EXECUTION_ENVIRONMENT_BLAXEL_SANDBOX`. The stub client now emits the same payload shape a resumed step receives, so a step written against the local loop runs identically once deployed.

  The `coding-pause` template and its guidance are updated to the new shape.

- Updated dependencies [e17b2d1]
  - @sapiom/tools@0.4.0
  - @sapiom/orchestration@0.1.8

## 0.2.0

### Minor Changes

- 704c9ac: Make the local development loop (`run_local`) production-faithful and trustworthy for the dispatch/pause pattern (`agent.coding.launch` + `pauseUntilSignal`).

  - Stub capability handles now survive JSON serialization, so a paused/resumed coding workflow runs end-to-end locally instead of failing with an opaque `'sandbox.toJSON' is not a method or field` error.
  - The payload a paused step resumes with is delivered as plain JSON — the same shape production sends over the wire — so authors re-attach handles by name (`sandboxes.attach(...)`) locally exactly as they would in prod.
  - `@sapiom/tools` exports `CodingResultPayload`: the shape a step resumed from `pauseUntilSignal(codingHandle, …)` receives, so resumed steps can be annotated instead of hand-rolling the type.
  - Stubbing a handle-returning capability with plain JSON no longer strips the handle's instance methods (e.g. `repo.pushFromSandbox`), and `repositories.list` stubs are coerced and shape-checked.
  - A dispatched `launch()` accepts the `agent.coding.launch` stub key as well as the shared `agent.coding.run` (ordered candidate resolution), so the stub key matching the call the author wrote takes effect.
  - `run_local` now reports `unusedStubs` (a supplied key that matched no call) and `stubWarnings` (a key that matched but carried the wrong shape), surfacing stubs that silently didn't take effect; the MCP `run_local` also serializes its result defensively.
  - New `coding-pause` scaffold template for the launch + pause + resume pattern, and AGENTS docs documenting the resume-input contract, list stub item shape, failure-branch stubbing, and step determinism under replay.

### Patch Changes

- Updated dependencies [704c9ac]
  - @sapiom/tools@0.3.0
  - @sapiom/orchestration@0.1.7

## 0.1.1

### Patch Changes

- Updated dependencies [7f6859e]
  - @sapiom/tools@0.2.0
  - @sapiom/orchestration@0.1.6
