Conversation
A receiving agent's input processor is not a complete signal boundary: Mastra can drain queued signals after the initiating processor has run. Breakwater now exposes createContentPolicyGate(), the same ordered, fail-closed evaluator loop PolicyEngine uses, for host code outside the processor chain; FlowSafe's thread signal routes accept a structural contentPolicy callback and apply it at the one Durable Object boundary every lane converges on, over Mastra's canonical escaped XML, before delivery, persistence, wake, or run start. Denial is terminal and evaluator failure stays recoverable, per lane: direct routes answer 422 and 503; a schedule settles a discard receipt or leaves its lease for a later tick; a notification is discarded or deferred with backoff. Neither outcome exposes policy names, reasons, content, or causes. Notification ingress is authoritative rather than a preview — core delivers an urgent notification, and an idle-thread high or medium one, straight out of sendNotificationSignal — so it inspects both renderings core can choose between. Two pre-existing defects surfaced by that rendering are fixed with it. Signal attributes whose keys are not XML names are dropped at ingest, and a schedule whose stored target cannot be rendered settles terminally, instead of throwing inside the agent turn or handing the same broken target to every later tick. Provider deliveries now separate a terminal refusal from one the deployment could not decide. An undecided webhook answers 5xx so the sender redelivers, under a dedupe key derived from the signed bytes and the subscription, rather than dropping an authentic event during a policy outage; a provider bug stays contained and non-retryable. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The O2 "scheduled agent principal" check was flaky because an earlier probe left a `* * * * *` schedule active and `/sched/agent`'s tick claimed every due row, so a minute boundary produced `due:2, fired:2`. Every `/sched/*` probe now pauses prior probe schedules at its entry (one call site; the barrier's inline loop is gone), the route set is decided before the store is constructed, and the workflow-start seam throws as a tripwire. O2 asserts `due === 1`, exactly one trigger row, the seam and D1 run ids agree, and the outcome is `succeeded`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0119A2ucLjbpmXKEe5GLXxTB
Webhook and poll deliveries that a thread Durable Object refuses were logged as `*-delivery-error` without saying whether redelivery could change the outcome. Every such event now carries `terminal`, computed by one shared predicate next to the delivery classifiers: `denied` and `failed` cannot change on redelivery, `deferred` can. The two by-construction `failed` lanes carry the literal; the rejected lanes use the predicate instead of an inline comparison. Tests assert the flag per lane on the exact logged event. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0119A2ucLjbpmXKEe5GLXxTB
Every @mastra/core release from 1.54.0 through 1.61.0-alpha.1 ships literal
`import("execa")` / `import("@ast-grep/napi")` specifiers (mastra-ai/mastra
#20638) that break the flowsafe workerd bundle and the showcase build, so
the supported peer moves to exactly 1.53.0 in all six manifests; the D1
adapter stays at 1.1.1. Flowsafe's breakwater peer floor rises to
`>=0.13.0 <1.0.0`, three stale age-gate exclusions are dropped, and the
packed-manifest tripwires now derive their expectations from the source
manifests and assert the packed core peer is an exact version.
1.53.0 added recovery entries to DurableAgent and made `resume()` rehydrate
a run from snapshot storage below `executeWorkflow`, outside RunnerRuntime
and the approval-decision path. FlowsafeDurableAgent now refuses nineteen
inherited entry points from a single reason table (`BLOCKED_RUN_ENTRIES`,
kept off the public subpath), and a prototype-surface tripwire partitions
every DurableAgent and Agent member so the next core bump surfaces new
members mechanically. Breakwater's inventory loses a member 1.53.0 removed
and gains a self-expiring allowlist for the newest-core canary. The
`mastra-compat` job bundles the spike Worker against newest core and
reports the outcome on the run summary.
Docs record the residual this work surfaced: on an idle thread the queue,
state and notification routes — and Mastra's completion drains — start
runs under Mastra-minted ids FlowSafe does not own. That behaviour is
byte-identical at 1.50.0 and is left for its own change.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0119A2ucLjbpmXKEe5GLXxTB
Text-only follow-up to the @mastra/core 1.53.0 closeout; no behavior change. - docs/durable-agents.md: the wake-path sentence now partitions the five thread channels (message/signal wake through Flowsafe's seam; queue/state/ notification do not) and names schedule and notification-dispatch as routes outside the channel table; blocked-entry ground 4 reads "mints a run id below the caller" to match BLOCKED_RUN_ENTRIES. - durable-agent-runner.ts: section rules say "unless another chunk or file is named" (the Corroboration paragraph cites repo-file offsets); the five-senders block scopes its offset rule to the paragraph, uses one form per file name, and is re-flowed to the file's comment width. - durable-agent-surface.test.ts: gloss names the RunnerRuntime boundary and the unreachable model by its helper name. - agent.test.ts: the allowlist comment points below to the comparison it governs and no longer hard-codes the live-name count. - host-do.test.ts: the it.each column is `scenario` (not the reserved `case`) and the provider id is one hoisted const. - packages/breakwater/src/agent/CLAUDE.md: route maintainers to the forwardClassified allowlist before any @mastra/core bump. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RA71awFou9Yr5VNpETGhjr
…n routes Closes the pre-existing (Track C) residual where three thread-DO signal routes let @mastra/core mint a run id and start a run outside RunnerRuntime, and where core's completion drains replayed leftover signals under fresh ids with the previous run's trusted context. Runner (durable-agent-runner.ts): - A run the host seam (streamUntilPersisted) did not register is failed terminally inside executeWorkflow: its input is persisted best-effort (bounded, skipped for read-only or missing threads, and for deliveries marked as non-owner), a terminal ERROR is published through core's own channel so core's completion watcher heals the thread (maps, lease, renewal timer), registries are cleaned in finally, and RunnerRuntime.start is never reached. Direct stream() resolves to a failed output; direct generate() rejects. - One live-id guard (#assertRunIdNotLive) refuses stream/generate/prepare and a second host start for any id still live in the requester map, the persistence waiters, core's TTL run registry or the runner's internal registry; the host's own first start carries a single-shot private ticket. streamUntilPersisted refuses untilIdle. - Terminal-error publication is one-attempt/never-throws; the terminal path retries once and throws after cleanup, the resume path publishes best-effort before cleanup and keeps its original semantics. Routes (thread-do-routes.ts): - /signal/queue persists in both thread states (sendMessage with ifActive/ifIdle persist); the active-thread auto-drain is gone. - /signal/state gains the owner gates /signal/queue has, persists on idle, and awaits the write. - /signal/notification stays the provider lane: no owner refusals; owners persist on idle; non-owners are record-only through resolveNotificationsStorage with deliverAt now and are delivered by the host's notification dispatch tick; 409 without the storage seam. - Every deliverActive fall-through persists only when memory is available and the principal may persist; a non-owner's requested ifActive persist is degraded; signals sent under a non-owner principal carry a non-rendered metadata marker the terminal persist honours. - memory-unavailable is answered only where a memory write would otherwise be silently dropped, after the content gate; wake-start, active delivery and the notification inbox record need no memory. The schedule route settles a canonical discard receipt in that case. - Unbranded agents degrade to persist-only with a typed `degraded` marker. Tests: a real guarded durable agent driven through the real routes proves the DENY direction, the completion-drain heal (maps, lease, no run row), the direct-sender matrix, the suspended-run collision window and the non-owner record-only path; unit rows cover every gate and order. Docs and the flowsafe minor changeset call out every contract that moved, the memory prerequisite the shipped starter host does not yet satisfy (follow-up: wire agent memory), and the two declared residuals. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RA71awFou9Yr5VNpETGhjr
…-check
Four hardening follow-ups the 1.53.0 closeout recorded:
- scripts/github-yaml-check.mjs (+ test, `github:check` / `github:check:test`,
a lint-staged entry for .github/**/*.{yml,yaml}, and two `verify` steps
before Lint) parses every .github YAML file with yaml@2.9.0's
parseDocument, fails closed on parse errors, unresolved aliases,
multi-document files, empty or non-mapping documents, zero files,
forbidden characters (C0/C1 controls, DEL, U+FFFE/U+FFFF), invalid
UTF-8, symlinked entries or a symlinked root, and a missing or
non-directory .github. A plain-scalar `": "` error in ci.yml was
previously invisible to every local gate, and sibling workflows and
issue templates are never trigger-checked on a PR. yaml@2.9.0 is pinned
exactly as a root devDependency; it was already resolved at that version.
- scripts/publish-ordered.mjs checks each prerequisite's peer floor against
the version being published, as a required first hook of publishRelease
(release time only: between a floor raise and the Version Packages PR the
source tree legitimately fails it); publish-invocation-check.mjs asserts
the floor grammar on every PR and names the manifest that owns each
violation. The two packed-consumer tests assert that breakwater and
flowsafe pin the same @mastra/core peer.
- docs-check gains checkMastraCoreAgreement: every packages/*/package.json
@mastra/core declaration must carry one value, and each library's
devDependency must equal its peer.
- pnpm override js-yaml@4 -> 4.3.1 (CVE-2026-59870 on the changesets
transitive), mirroring the existing js-yaml@3 override.
The CONTRIBUTING and maintainer-guide gate lists now mirror the verify job
in order.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: ba9217b9-818b-4144-9baa-1336c3de16da
release: version packages
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
anchorage-showcase-single-tenant | c07693d | Aug 22 2026, 01:29 PM |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Promotes the versioned dev state to main. Version Packages PR #99 is merged, the full verify job passed on dev commit c07693d, and no pending changesets remain. The non-blocking Mastra 1.61.0 canary was investigated: it reaches the compatibility tests and flags new upstream prototype members; the supported release peer remains exact 1.53.0.