Releases: Ascending-AI/lash
Release list
v0.1.0-alpha.113
Breaking
Provider-file attachments now carry an optional media type, and Anthropic provider file ids require that hint so Lash can choose the image or document modality.
Internal
Documentation dependency pins now reference v0.1.0-alpha.112.
Fixed a turn-input ingress performance assertion that checked attachment position instead of survival, which had left nightly runtime performance budgets ungated.
Release tooling now bounds squash-merge notes, previews grouped output, and validates categorized entries before merge.
Right-size merge-gate CI jobs on Blacksmith runners and pair migrated jobs with Blacksmith's Rust cache.
Release automation now commits published documentation pins to main with bounded race retries.
Release automation now requires green target-SHA CI and full performance budgets on Blacksmith, removes the nightly perf cron, and moves sim-unit-perf-guards to Blacksmith.
Push and pull-request CI now exercises runtime and Lashlang performance measurement paths without enforcing release budgets.
What's Changed
- Pin published docs to alpha.112 by @SamGalanakis in #130
- Fix turn-input ingress perf assertion (attachment survival, not position) by @SamGalanakis in #128
- Fix release-note extraction, add PR validation and preview by @SamGalanakis in #129
- Right-size CI runners onto Blacksmith (FIG-518) by @SamGalanakis in #131
- Add agent working guidance (ticket style, PR style, way of working) by @SamGalanakis in #132
- Add MIME hints to provider-file attachments (FIG-616 item 2) by @SamGalanakis in #133
- Make release gates actually gate (FIG-617) by @SamGalanakis in #134
Full Changelog: v0.1.0-alpha.112...v0.1.0-alpha.113
v0.1.0-alpha.112
Three waves land in this release: the FIG-527 test-credibility program, typed durable queued-input application evidence (FIG-609), and a production recoverable-chat host reference with its conformance gate (FIG-610).
⚠️ Breaking changes
1. enqueue returns a durable acceptance receipt.
Turn-input enqueue APIs now return TurnInputAcceptanceReceipt instead of the mutable PendingTurnInput row. A successful receipt means the input is durably accepted — it does not mean it has been dispatched. Queued dispatch now proceeds asynchronously and retries transient wake failures on its own; a dispatch failure is never surfaced as an enqueue error.
Migration: treat a returned receipt as "durably accepted, will run". Retry a missing receipt using the same source_key — it is the idempotent retry identity, so a retry cannot duplicate work. Do not inspect dispatch state from the enqueue result.
2. Remote protocol v16 — typed queued-input application evidence.
Queued-input acceptance is no longer reported as an untyped RuntimeDiagnostic. Remote hosts receive a typed turn_input_applied observation carrying stable input/source, turn, committed-message and checkpoint identity, emitted for both active-turn checkpoint injection and idle queued-turn claims.
Migration: stop parsing RuntimeDiagnostic and stop synthesizing acceptance from a pending-input snapshot. Consume the typed event; after a lost live-replay window (gap, owner loss, or a fresh handle) reconcile with the durable read remote_turn_input_applications(), which returns settled application identity in commit order.
New
recoverable_chatobservation surface for snapshot-first chat hosts: an authoritative snapshot plus cursor, stable event identity, replay-gap snapshots, terminal replacement, and explicit observer-disconnect semantics. Dropping a subscription is observation lifecycle only — it never cancels server work.- agent-workbench is now a production-grade recoverable-chat reference, not a demo: the lash observation lane is separated from the durable product-event lane, redelivery is deduplicated, provisional state is replaced or retracted on attempt reset / replay gap / terminal settlement, subscriber lag triggers authoritative resync instead of an error, internal errors never reach the client, and a pluggable authorization seam is exposed and documented.
Fixed
- Durable turn replay no longer fails because of an advisory session lease. A busy, expired or lost session execution lease is now advisory; session-head CAS and claim-generation fencing remain the sole commit authority, so replay cannot diverge on live lease state.
- PostgreSQL claim completion is now correctly fenced. Claim ownership rows are locked through commit and a completion affecting no rows aborts the transaction as superseded — previously a superseded worker could commit stale graph/checkpoint state after its claim had been taken over.
- Recoverable-chat snapshots are lossless. A snapshot now pairs the committed read view with its exact observation cursor, so a terminal commit concurrent with snapshot capture can no longer be skipped. Replay-gap recovery discards pre-gap event identities before continuing, so a genuinely new event at a reused cursor is never suppressed.
- Queued-input wake recovery is bounded. It stops immediately on terminal errors, gives up after eight attempts on persistently transient ones, and shuts down with its driver instead of leaking immortal retry tasks.
Internal
- Confidence and performance artifacts retain attempt-specific failure evidence — a rerun can no longer overwrite the first failure — and test quarantines require owned, expiring RCA metadata.
- Replay-divergence coverage now enters real production paths: production
ToolAttemptemission is proven on replay, and a registry-derived tool × execution-context conformance matrix fails the build when a new tool or durability tier is left uncovered.
Known issue (resolved — no product impact)
The scheduled Performance lane is red with turn-input ingress active claim lost attachment bytes, first seen 2026-07-24 and therefore also present in v0.1.0-alpha.111. This has been diagnosed as a stale assertion in the performance harness, not a product defect — there is no attachment loss. The attachment is present and byte-identical; the harness checks the wrong list position (it asserts the attachment is the last item, but the measured claim aggregates many inputs, so it sits mid-list). Nothing in this release, or in alpha.111, loses attachment data. The harness assertion is being corrected; until then the nightly performance budgets are ungated.
v0.1.0-alpha.111
-
Removed simulation and conformance claims that could not detect production regressions.
-
Preserve host tracing parentage across lash-core task boundaries.
-
Breaking: OpenAI-compatible endpoints are no longer treated as local based on URL substrings; hosts must select OpenAiCompat::local() to suppress optional fields.
-
Breaking: Remove the unused OpenAiCompat.developer_role field; configurations that set it now fail deserialization.
-
All tool calls emitted in one batch now run concurrently; tool authors own any resource-level exclusion they require.
-
Removed the per-tool ToolScheduling API and remote scheduling field.
-
Breaking: Degenerate schemas such as null and non-object values now reject all inputs instead of accepting them, including persisted trigger payload_schema values.
-
Breaking: Tool and payload schemas now enforce previously ignored JSON Schema keywords such as allOf, pattern, not, if/then, multipleOf, tuple items, const, and uniqueItems; hosts should expect an increase in invalid_tool_args retries.
-
OAuth refresh failures now distinguish invalid grants from transient and ambiguous token endpoint errors without relying on response text.
-
Extended traces now include complete provider request bodies with byte lengths and SHA-256 hashes for prompt-shape diagnostics.
-
Bound extended provider request JSON payloads and strengthened cross-provider credential safety coverage.
-
Trace outgoing Codex SSE and WebSocket request bodies in extended provider traces.
-
Bound inline process execution per worker and release slots across dependent waits to prevent nested process starvation.
-
Session turns that lose their execution lease during renewal now report session_execution_lease_lost and release held ingress claims without masking previously sealed user cancellation evidence.
-
Add safe provider traffic recording and source-backed provider replay coverage.
-
Honor Google error-body retryDelay backoff, including 55-second throttle waits.
-
Treat Google and Anthropic hard-quota 4xx responses as non-retryable.
-
Map Chat Completions refusals to ContentFilter while preserving refusal text.
-
Accept empty responses under OutputLimit, ContentFilter, or Cancelled instead of returning empty_response_error.
-
Durable Restate journals now record the full canonical effect envelope
(including complete LLM request content) per effect instead of only its
hash, so replay mismatches are field-diagnosable. This roughly doubles
LLM-effect journal entry size; journal content class is unchanged (the
journal already holds the turn state envelopes derive from). Recorded
entries use the new shape; in-flight invocations ride ADR 0043 immutable
deployments across the change. -
Added the RuntimeEffectControllerError summary field with divergent-path
count and first paths for durable replay hash mismatches. -
Effect envelope mismatch diffs (with bounded value excerpts) are emitted
as trace events behind extended trace level plus a configured sink.
Breaking: TriggerSubscriptionDraft now requires subscription_key; keyless registrations derive stable owner-local keys from process, source type, and normalized source key; duplicate defaults in one artifact require explicit keys; registration conflicts on changed definitions instead of upserting; deletion tombstones subscriptions and preserves delivery history; stale trigger schemas are rejected and must be recreated; enable and disable require expected_revision for CAS, and enabling an already-enabled subscription succeeds without changing revision.
-
Custom RuntimeEffectController implementations must handle the new
mandatory PeekAwaitEvent command: every turn now journals a replayable
start-gate peek, and controllers without the arm fail every turn at start. -
Restate durable-wait key identity moved to the shared derivation: drain
in-flight durable waits before upgrading; previously issued external
completion keys no longer verify. -
Add durable await-event semantics and restart conformance for Restate-backed runtimes.
-
Attachment GC now reclaims aged intents only after durable owner-death proof; hosts must explicitly wire the process registry, and terminal process pruning removes process-owned session stores.
-
PostgreSQL stores from main schema version 14 must be recreated for attachment-owner schema version 15.
-
Pruned-attachment placeholder text in rolling history changed from
"[Image omitted...]" to "[Attachment omitted...]" (and "[Attachment]" when
rendered) — a small prompt-shape change for sessions with pruned media. -
Remote executors must share attachment-store access with the core: resolved
stored attachments are not serialized over the remote protocol, and an
unshared executor fails loudly with stored_attachment_not_resolved. -
BREAKING: MediaType is now a validated MIME string newtype; ImageMediaType and the closed MediaType::Image catalog are removed.
-
BREAKING: AttachmentMeta, AttachmentRef, and AttachmentCreateMeta move width and height into optional AttachmentTypeMetadata, changing their fields and constructors.
-
BREAKING: PartKind::Image, LlmContentBlock::Image, DirectPart::Image, and TraceContentBlock::Image are replaced by their generic Attachment forms.
-
BREAKING: LlmAttachment is removed; LlmRequest attachments now use AttachmentSource with Inline, Stored, ExternalUrl, and provider-scoped ProviderFile variants.
-
BREAKING: ToolValue::Attachment and ModelToolReturnPart::Attachment now carry AttachmentSource; tagged attachment JSON uses source instead of ref.
-
BREAKING: InputItem::ImageRef, TurnInput image blobs and image helpers are removed; turn ingress now carries AttachmentSource directly.
-
BREAKING: PluginMessage images are replaced by generic attachments.
-
BREAKING: remote protocol version 14 replaces ImageAttachment, RemoteLlmAttachment, ImageRef, and image_blobs_base64 with MIME-generic attachment sources, refs, metadata, and turn items; version 13 envelopes are not accepted.
-
BREAKING: unsupported provider MIME or source combinations fail during request materialization with code unsupported_attachment_capability and a provider, source, MIME, and accepting-provider diagnostic.
-
BREAKING: RuntimeHostConfig and tool dispatch contexts carry an AttachmentSourcePolicy; the default policy is open.
-
BREAKING: every McpServerConfig transport variant adds binary_content_attachments, defaulting to false.
-
BREAKING: RlmAttachmentRef now carries optional MIME plus explicit source and reference fields.
-
BREAKING: ToolAttemptLaunch::Done boxes its ToolCallRecord payload.
-
read_file keeps existing image, PDF extraction, and binary rejection defaults; attach_as explicitly opts a file into native attachment handling.
-
MCP keeps image persistence enabled by default; with_binary_content_attachments explicitly enables audio and binary resource persistence.
-
Stored Google uploads cache by provider, credential scope, Lash content id, and MIME; borrowed URLs and provider file ids never enter Lash storage or this cache.
Breaking: Lashlang artifacts and artifact stores now carry owner-current trigger key manifests; trigger listings add registrant and manifest_membership, triggers.prune explicitly tombstones reviewed owner-local subscriptions, and the remote protocol version advances to 15.
- SQLite effect databases now use schema version 2 and must be recreated; the new schema adds durable await-event promises, store-resident HMAC key material, and session revocation tombstones.
PostgreSQL storage schema version 16 adds durable AwaitEvent state and requires pre-16 databases to be recreated; AwaitEventResolver defaults now refuse all identities unless a host implements the surface explicitly.
Restate-hosted process cancellation is now delivered promptly through durable workflow signals and cannot silently complete successfully after a transient registry read failure.
Breaking: Remove lash_core::derived_subscription_key; linked Lashlang trigger registrations must carry materialized subscription keys.
SQLite effect replay schema version 3 and PostgreSQL storage schema version 17 persist canonical runtime-effect envelopes for structural replay diagnostics and require pre-3 SQLite effect databases and pre-17 PostgreSQL databases to be recreated.
What's Changed
- ratchet release pins to alpha.110 by @SamGalanakis in #94
- record that tests must be independent of what they test by @SamGalanakis in #92
- remove test claims that cannot fail by @SamGalanakis in #93
- record that hosts must register immutable deployments by @SamGalanakis in #91
- preserve tracing context across spawned tasks by @SamGalanakis in #95
- remove inferred local OpenAI compatibility by @SamGalanakis in #97
- remove per-tool ToolScheduling; run batched tool calls concurrently by @SamGalanakis in #96
- ci: run the three long jobs on Blacksmith runners by @SamGalanakis in #98
- record that services are stateless and substrates own continuation by @SamGalanakis in #99
- make simulation leases starvation-proof by @SamGalanakis in #100
- validate tool inputs with the jsonschema crate by @SamGalanakis in #101
- classify OAuth refresh failures structurally by @SamGalanakis in #102
- trace outgoing provider request bodies safely by @SamGalanakis in #103
- make agent instruction files untracked and local by @SamGalanakis in #104
- bound inline process execution concurrency by @...
v0.1.0-alpha.110
- (docs only; no runtime change)
What's Changed
- ratchet release pins to alpha.109 by @SamGalanakis in #80
- ci: run the five long CI jobs on Blacksmith by @SamGalanakis in #81
- openai: let hosts require parameter-honoring gateway routing by @SamGalanakis in #82
- Revert CI to GitHub-hosted runners by @SamGalanakis in #85
- journal every tool provider attempt by @SamGalanakis in #83
- ci: stop building the release cache on pull requests by @SamGalanakis in #89
- fix: stop classifying rate throttling as quota exhaustion by @SamGalanakis in #87
- fix: record attempt usage and evidence for every provider kind by @SamGalanakis in #88
Full Changelog: v0.1.0-alpha.109...v0.1.0-alpha.110
v0.1.0-alpha.109
-
The agent-workbench example fails fast at startup when its provider credential is missing and no dev provider scenario is active, and the dev runner reports startup failures instead of a false ready.
-
(docs only; no runtime change)
-
Durable waits on the Restate driver wake through a single causally-linked call; a failover-window race that could leave a resolved wait suspended until timeout is fixed, and a guard bug that could park an attempt forever behind an entry-scoped SDK error now fails the attempt for retry.
-
In-flight turns suspended in the old wait chain at upgrade time fail rather than recover once old workers drain; re-run affected workflows after upgrading.
What's Changed
- workbench fails loudly without provider credentials by @SamGalanakis in #76
- ratchet release pins to alpha.108 by @SamGalanakis in #77
- durable waits wake through one causally-linked call by @SamGalanakis in #78
Full Changelog: v0.1.0-alpha.108...v0.1.0-alpha.109
v0.1.0-alpha.108
Prevent completed RLM answers from appearing multiple times in later-turn history.
- test(rlm): satisfy multi-turn history lint
Use the standard integer divisibility helper in the deterministic few-shot provider.
Release-Notes: None.
- test(rlm): assert traced finish precedence
Pin the FIG-461 acceptance criterion against turn two's llm_call_started request message payload, in addition to the provider-visible request.
Release-Notes: None
- fix(runtime): commit active turn ingress at checkpoints
Materialize claimed active-turn input as normal committed user messages and defer inputs that miss the final checkpoint into the next turn. Remove the RLM transient projection append.
Release-Notes: Inject-now input is now committed to transcript history at its admitting checkpoint.
- test(ingress): require committed transcript delivery
Invert active-turn ingress gates across core, RLM prompt history, workbench HTTP and rendered streams. Byte-pin mid-turn, post-final-call, and queue-next request message shapes and update the turn-ingress runbook.
Release-Notes: Workbench inject-now messages now render as committed user transcript entries.
- test(ingress): scope queue prompt capture lock
Release the synchronous request log before awaiting the idle queue check so all-target clippy remains clean.
Release-Notes: None.
What's Changed
- docs: ratchet release pins to alpha.107 by @SamGalanakis in #74
- committed transcript precedence + checkpoint-committed ingress by @SamGalanakis in #75
Full Changelog: v0.1.0-alpha.107...v0.1.0-alpha.108
v0.1.0-alpha.107
- Tools can perform LLM completions (and any opaque effect) inside durable processes: tool attempts are the atomic durability unit, and llm_query now works identically in volatile and durable contexts as an ordinary tool. Attempt retries re-execute in-attempt effects (at-least-once).
- The durable_effects tool facade and DurableStep effect are removed; decompose multi-step durability into process steps. Previously-failed workflows hitting the old guard need a re-run after upgrade.
What's Changed
- docs: ratchet release pins to alpha.106 by @SamGalanakis in #73
- FIG-446: tool attempts are atomic — llm_query becomes an ordinary tool (fixes #69) by @SamGalanakis in #72
Full Changelog: v0.1.0-alpha.106...v0.1.0-alpha.107
v0.1.0-alpha.106
-
Nested child-session turns no longer grow the parent's poll stack: each child turn runs on its own task, removing the depth ceiling on child-session nesting in inline deployments.
-
The workbench busy indicator remains accurate while a trigger occurrence dispatches during an active foreground turn.
-
None.
-
Mid-stream provider retries no longer duplicate assistant prose in committed conversation history or pollute the retry's parse; observers, reloads, and later turns all see the surviving attempt's output exactly once.
-
Substantial runtime performance improvements: streamed tokens no longer deep-clone through the observation chain, tool-loop checkpoints and turn starts make fewer store round-trips, Restate wait-index state scales linearly, and trigger delivery batches to constant statements.
-
Workbench SSE fan-out is keyed per session.
What's Changed
- docs: ratchet release pins to alpha.105 by @SamGalanakis in #65
- Isolate child-turn stacks: spawn boundary + canonical growth seams (ADR 0041) by @SamGalanakis in #67
- Fleet findings batch: admin-URL wiring, truthful busy pill, runbook gate corrections by @SamGalanakis in #66
- Refresh performance/stack profiling to cover the composed turn geometry by @SamGalanakis in #68
- Retry attempts no longer pollute committed history or the parser by @SamGalanakis in #70
- Perf wave: measured wins across streaming, store round-trips, wait-index, and the turn hot path by @SamGalanakis in #71
Full Changelog: v0.1.0-alpha.105...v0.1.0-alpha.106
v0.1.0-alpha.105
- Trigger subscriptions support enable/disable/delete as a first-party store contract on all backends; trigger occurrences can be session-scoped (remote protocol v13).
- The workbench example demonstrates attachments (upload/reference/persist), a session usage ledger, a trigger rail, session-scoped SSE, honest provider-failure terminals, and failed-process rendering.
- Deterministic dev failure providers are available opt-in for host testing.
What's Changed
- docs: ratchet release pins to alpha.104 by @SamGalanakis in #63
- FIG-425 wave 3: editor authoring, trigger lifecycle, failure paths, break-glass, attachments, usage, isolation by @SamGalanakis in #64
Full Changelog: v0.1.0-alpha.104...v0.1.0-alpha.105
v0.1.0-alpha.104
-
Provider retries now publish a ModelAttemptReset activity retracting the aborted attempt's streamed prose/reasoning by correlation id; observers render single-copy live and on replay.
-
Remote protocol v12 adds the model_attempt_reset event (strict version negotiation).
-
Cancelling a turn parked in a suspended durable wait (sleep or await-event) now settles promptly: cancel resolution wakes the suspended invocation through a journaled awakeable on both inline-registered and engine-restart-recovered turns.
-
Workbench Stop retains turn routing while the engine still runs the turn and renders cancellation evidence when the terminal eventually commits.
What's Changed
- docs: ratchet release pins to alpha.103 by @SamGalanakis in #59
- fix(workbench): boot default sqlite mode and stoppable engine container by @SamGalanakis in #60
- FIG-423: retried model attempts retract their streamed output by @SamGalanakis in #61
- Wake suspended durable waits on turn cancellation by @SamGalanakis in #62
Full Changelog: v0.1.0-alpha.103...v0.1.0-alpha.104