Reaktor Work
Reaktor Work is an experimental durable execution substrate for applications and services. Meeseeks has been removed from the active module. The selected architecture integrates directly with Android WorkManager, iOS BGTaskScheduler, browser execution hosts, Cloudflare Workflows and Queues, and Spring-managed Quartz. GCP Pub/Sub participates through Reaktor Google and Bus.
The common contract describes accepted intent, authority, attempts and results. Each platform supplies its own execution capabilities. Media uploads, database archives and scheduled server transitions share identity and inspection conventions without acquiring identical lifetime or delivery guarantees. Coroutines and Cloudflare Workflows are components of this design. Compare the resulting execution profiles with other systems, rather than treating those components as competing products.
Current source status
Implementation progress
Started 5 October 2026. Progress follows the Surface migration format: dated notes state what changed, what was checked and what remains. A source change is not a qualified platform guarantee. The authenticated delivery ledger records task-level evidence and migration decisions.
| Milestone | Status | Done | Left |
|---|---|---|---|
| Inventory and migration | In progress | Vendor dependency/callers removed; two installed-device stores inspected and preserved | Wider cohorts, explicit dispositions for any discovered real legacy intent |
| Graph contract and storage | In progress | Scoped definitions, conditional admission, fenced claims, bounded attempts, journal/cursors and conformance checks | Indexed due discovery, quotas/retention, atomic domain/projection integration and complete scope policies |
| Typed DAG and durable coordinator | In progress | Request evaluator and static durable DAG v1; shared results, parallel joins, lazy branches and restart recovery | Durable waits/signals, dynamic expansion, compensation and evolution commands |
| Android / iOS / browser | In progress | Native bindings and headless bootstrap; Android WorkManager receipt/relaunch proof | iOS background opportunity, full mobile lifecycle matrix and browser realm/storage qualification |
| Cloudflare / Spring | In progress | Workflow/Queue, Pub/Sub and Quartz adapters; D1 workerd conformance | Deployed delivery/reconciliation, JDBC clustering and durable waits |
| Domain migrations and inspection | In progress | Scoped Hangar Work inspection, retained journal, persisted DAGs and authorized command receipts | Message/media/archive/push consumers, provider inspection endpoints and measured comparisons |
9 October 2026 — Hangar Cloud / Work inspection
- Stage 1 implemented: scoped metadata APIs, bounded pagination, retained journal history and the Cloud → Work subpane. Environment, application, tenant, principal, host, definition and state filters, selection and inspector state belong to the existing workbench graph. Reads require fresh authority; payloads and checkpoints have a separate permission.
- Stage 2 implemented: workflow runs and definition revisions render their actual durable manifest through the existing Blueprint canvas. Provider observations remain separate from WorkStore state. Stable trace, deployment and resource identifiers link to existing Hangar views when the matching scope is connected.
- Stage 3 implemented: cancellation, policy-gated retry and provider reconciliation use typed commands with host activation and record revision preconditions. Hangar reviews device commands through its existing fingerprinted approval and receipt ledger. Reconciliation requires a trusted provider reader and remains unsupported on the diagnostic mobile host.
- Checked: Work and DevTools JVM checks, the Work headless boundary, kernel checks and boundary, and Hangar navigation/render/graph checks pass. Coverage includes scope isolation, cursor drift, corrupt records, history beyond 64 transitions, actual DAG dependencies, late host responses and command receipts. A 1,000-record SQLite metadata probe returned 64-record pages with a mean of 16.2 ms and a maximum of 41.9 ms; this is a local directional measurement, not a capacity guarantee.
- Physical evidence: a data-preserving Android debug installation completed a real diagnostic through WorkManager. Hangar discovered the host directly from Cloud → Work, showed its
SUCCEEDEDrecord at revision 3/fence 1 and displayed the retainedQUEUED → RUNNING → SUCCEEDEDjournal. The MCP read rejected a different tenant and exported metadata without payloads or checkpoint values. - Left: deployed browser/Cloudflare inspection endpoints, provider status readers and production domain migration. The authenticated progress ledger retains installation and qualification evidence.
6 October 2026 — Worker boundary and caller qualification
- Changed: Cloudflare and Secrets use the small Auth Core bearer-header helper instead of loading the full Auth module. Existing Auth formatting/parsing APIs delegate to it, preserving their public interface. Cloudflare now has an enforced headless dependency boundary alongside Work and Auth Core.
- Checked: native D1 tests pass without the UI-asset workaround; Work, Cloudflare and Auth Core boundary checks pass; all 107 existing Auth JVM checks and two Auth Core checks pass. BestBuds callers compile on Android, iOS arm64, JVM and JS after the dependency change. The latest Android diagnostic also commits
SUCCEEDEDwith a persisted receipt. - Device gate: the iOS application builds and is installed with existing databases preserved. Startup verification is waiting for the iPhone to be unlocked; BGTaskScheduler execution remains a separate qualification gate.
- Left: production rollout, real domain consumers, durable graph operators and the platform/fault matrix described below. Pub/Sub's broader Google host dependencies and deployed broker behavior still require qualification.
6 October 2026 — retained delivery and platform evidence
- Changed: opted-in SQLite and D1 ObjectDatabase journals append record changes in the same statement transaction. Work consumers read ordered, bounded batches and acknowledge with a persistent conditional cursor. Admission, claims, checkpoints, handoffs and completion are retained beyond the 64-transition inspection window; restart or lost acknowledgement redelivers the same event identities. A generic SQL schema is shared by both backends.
- Checked: 13 JVM Work checks cover the existing runtime/DAG laws plus journal rollback and cursor recovery. The native D1 workerd/Miniflare profile verifies competing claims, host reconstruction, stale commits and retained cursor delivery. Android/iOS arm64/JS framework compilation and the Work headless boundary pass; Pub/Sub bindings compile on JVM/JS.
- Android evidence: a data-preserving installation admitted a diagnostic as
QUEUED; WorkManager committedSUCCEEDED, attempt/fence 1, with a real SQLite receipt and three journal entries. Force-stop/relaunch retained that receipt and attempt. The diagnostic uses an explicitly limited device service principal, not user credentials. Screen-navigation/lifecycle qualification remains separate. - Migration evidence: both connected-device backups passed SQLite integrity checking. Android had no legacy work stores; the iPhone's preserved Meeseeks
taskSpecandtaskLogEntitywere empty. This evidence applies to these devices only. - Left: due-work discovery still scans a scope. Journal retention, quota/backpressure, atomic projection/domain commits and broker publication are not production-qualified. Static durable plans remain limited to 64 nodes; durable waits/signals, dynamic fan-out, compensation, version migration and real send/media/archive/push effects remain pending. A local D1 test does not qualify deployed Workflows/Queues/Pub/Sub or Spring JDBC clustering.
5 October 2026 — vendor cutover and durable graph recovery
- Changed: removed the Meeseeks dependency, wrappers, vendor payloads and ten false-success workers. BestBuds boots a minimal diagnostic Work graph from Application; the diagnostic stores an idempotent receipt, and notification reconciliation reports
BLOCKEDwhile its domain handler is absent. iOS retains launch-compatible legacy IDs only to cancel/terminate old callbacks. Legacy stores are preserved. - Framework checks: 11 JVM conformance/integration checks pass, including competing SQLite connections, reopen, poison visibility, stale fences, fresh authority, host cancellation, request-DAG reuse, durable diamond/branch recovery, provider handoff fencing and an actual Quartz wake. Work's dependency check passes with no Meeseeks, Compose, Skiko or product dependency. Android, iOS arm64 and Kotlin/JS Work compilation pass; BestBuds caller compilation passed on Android/iOS/JVM/JS during cutover.
- Provider ownership:
HANDED_OFFrecords preserve a provider receipt and cannot be claimed for local replay. A matching, authorized completion reconciles that record. Cloudflare Workflows and Queues bindings compile against the current API shapes; deployed storage, result callbacks, redelivery/DLQ and Pub/Sub qualification remain pending. Quartz's test uses RAMJobStore and does not qualify Spring JDBC clustering. - Limits: durable graph v1 supports static plans of up to 64 nodes, typed joins and lazy branches; timers/signals, dynamic fan-out, compensation, evolution commands and retained execution journals remain pending. Scope discovery still scans stored records; the 64-transition window and local Flow are inspection aids, not retained history or durable cursors.
- Device migration evidence: the connected Android database backup passed SQLite integrity checking and contained no Work-like ObjectDatabase stores or a native WorkManager database before cutover. This is evidence about one device only. Native receipt/relaunch checks and iOS inventory remain pending.
5 October 2026 — first conformance gate passed
- Changed: atomic conditional writes in SQLite ObjectDatabase; scoped admission, fenced claims, lease renewal, checkpoints, cancellation and result receipts; graph-owned typed Work definitions and event-bound coroutine attempts. Request DAGs share results within a run, execute independent branches concurrently and keep unselected branches lazy. Direct WorkManager, BGTaskScheduler and browser wake bindings are in source.
- Checked: JVM framework checks with two competing SQLite connections and database reopen; stale attempts cannot acknowledge recovered work. Runtime checks cover fresh authority, tenant separation, schema quarantine and host cancellation. DAG checks cover diamond reuse, branch overlap and lazy selection. Android, iOS arm64 and Kotlin/JS compilation passed.
- Left: caller/vendor cutover, indexed/bounded discovery, retained journals/outboxes and durable cursors, durable graph coordination, real domain migrations and device/provider qualification. The store currently scans a scope and retains only a 64-transition inspection window. A live Flow is process-local. Native/browser bindings are source-complete, not qualified wakeup guarantees.
5 October 2026 — implementation begins
- First gate: atomic admission and conditional claims on the storage adapter, followed by graph-owned bounded attempts. A coroutine or actor mutex alone does not qualify shared ownership.
- Evidence: duplicate admission, concurrent claims, expired fences, cancellation, restart recovery, fresh authorization and the diamond DAG will be checked before their status changes to verified.
- Migration: the existing facade remains active until replacement callers and storage are qualified. No Meeseeks record is silently discarded and no installed-device migration is claimed from a local test.
Capability benchmark and selected execution profiles
Reviewed 5 October 2026. This is a source-backed capability benchmark, not a measured latency/throughput result. The new runner has JVM conformance checks, but no measured latency/throughput or production qualification yet. Provider documentation establishes what a provider can do; it does not establish that Reaktor's adapter already exposes or qualifies that capability. The measurement protocol defines the evidence needed for performance claims.
Implementation decision: Temporal, Restate, Conductor OSS, Twitter Nodes and Ray are comparison references only. Reaktor Work implements its own graph execution and durable coordination over Reaktor's modules and the selected native/platform mechanisms. Coroutines and Cloudflare Workflows remain included backends. No adapter, deployment or dependency on the reference engines is planned.
| System or composition | Dependency execution | Recovery boundary | Consequence for Reaktor Work |
|---|---|---|---|
| Retired Reaktor Work / Meeseeks 1.0.2 | Thin scheduling facade; ten placeholder handlers | No demonstrated domain-effect recovery in this module | Baseline is an experimental facade, not a durable DAG engine. Replace the vendor contract and prove a real consumer. |
| Reaktor graph + Kotlin coroutines — included local execution profile | Typed bindings plus a proposed ready-node evaluator; structured child tasks | Coroutine lifetime; persistence/recovery must be added for durable work | Preferred request-scoped profile. Keep pure calculations inexpensive; adding suspend does not persist decisions. Structured concurrency. |
| Reaktor graph + Cloudflare Workflows — included cloud profile | Lower a validated plan to awaited provider steps, parallel ready groups and durable waits | Provider step history and persisted outputs, with destination-side effect identity | Use the selected provider's durability. Shared plan lowering and Work handoff adapters remain to implement. Workflow rules. |
| Twitter Nodes | Typed asynchronous inputs/output, shared dependencies, optional dependencies, branching and service calls | Futures and results in a live graph instance | Reference for dependency ergonomics and per-run result reuse. A remote service call does not make its coordinating graph persistent. Nodes. |
| Temporal | Code-defined orchestration, activities and child workflows | Persisted execution history and deterministic workflow replay | Comparison standard for recovery, durable waits and upgrade compatibility; no Temporal adapter. History, workflow execution. |
| Restate | Durable service calls, keyed state and workflows | Journaled context actions, durable results/state and timers | Comparison standard for durable service composition and keyed ownership; no Restate adapter. Arbitrary external operations still need idempotency/reconciliation. Context actions, Java/Kotlin. |
| Conductor OSS | Explicit task definitions; fork/join, dynamic fanout, branches and subworkflows | Persistent orchestration/task state and external worker delivery | Comparison standard for authored task graphs; no Conductor OSS adapter. Reaktor tooling's similarly named Conductor is a separate existing subsystem. Operators. |
| Ray DAG | Lazy task/actor graphs for distributed computation | Task/actor execution and their configured recovery mechanisms | Comparison standard for compute placement; no Ray integration is selected. Its DAG API is not evidence of mobile wakeups or business-effect deduplication. Ray DAG. |
These systems solve different operating problems. Temporal is the durability reference, Conductor the explicit task-graph reference, Restate the durable-service reference, Twitter Nodes the asynchronous dependency reference, and Ray the distributed-compute reference. This selection is an architectural judgment, not a market-share ranking or evidence that Reaktor outperforms them.
| Reaktor profile | Selected mechanisms | Guarantee to qualify |
|---|---|---|
| Request-scoped DAG | Headless graph runtime + coroutines | Typed dependencies, bounded parallelism, result reuse and cancellation during the request lifetime |
| Device/browser durable operation | Authoritative WorkStore + coroutines + native/browser wakeups | Restart-safe intent, fenced attempts and reconciled effects; execution opportunity remains platform-dependent |
| Cloud durable workflow | Authoritative admission/outbox + Cloudflare Workflows + selected Queues/Pub/Sub delivery | Confirmed provider handoff, durable steps/waits and eventual result reconciliation under the provider's declared limits |
| Spring scheduled or queue-driven operation | Authoritative DB + Quartz + queue/Pub/Sub adapters | Durable occurrence identity, conditional claims, restart and redelivery recovery |
| Spring distributed workflow | Reaktor graph coordinator + authoritative WorkStore/journal + coroutines + Quartz + queue/Pub/Sub adapters | Long-lived waits, fanout/join recovery and worker/version compatibility; native coordinator implementation and qualification remain delivery gates |
Quartz schedules triggers; queues distribute messages. Reaktor's coordinator must supply the durable run/node state machine, readiness, joins, waits and recovery that those mechanisms do not supply. On Cloudflare, Workflows owns step history; on Spring, Reaktor's authoritative run journal owns workflow progress. The following comparison makes the feature requirements and gaps explicit.
Design and feature set compared with the reference systems
This compares the selected Reaktor design with documented reference features. It does not compare shipped implementations at equal maturity. In the Reaktor column, In source means an experimental implementation with the checks in progress; Designed means remaining specified behavior; Provider-backed means Cloudflare supplies the mechanism, with the Reaktor profile still to qualify; Gap means additional semantics or implementation are needed; Outside target means this design does not promise the reference feature. No comparison system becomes a runtime dependency.
Durable orchestration and service composition
| Feature | Proposed Reaktor Work | Temporal reference | Restate reference | Conductor OSS reference |
|---|---|---|---|---|
| Authoring and typed composition | In source: KMP definitions, typed provider ports and pinned static plans; Designed: full revisioned graph IR and operator vocabulary | Workflow code with SDK-typed activities/child workflows | Typed service, keyed-object and workflow handlers with context actions | JSON workflow/task definitions and code authoring; worker contracts and schema validation |
| Parallel branches, joins and child runs | In source: bounded request DAGs and static durable DAGs up to 64 nodes, shared outputs, joins and lazy branches; Gap: dynamic expansion and full operator qualification | SDK activities/child workflows and code-defined synchronization | Durable service/workflow calls composed through supported context APIs | Fork/join, dynamic fork and subworkflow operators |
| Recovery after coordinator/worker loss | In source: restore explicit static run state and committed child receipts, fenced attempts and retained Work changes; Provider-backed: Cloudflare step recovery | Deterministic workflow-code replay against persisted event history | Replay of journaled context actions/results | Persisted orchestration/task state and task lifecycle |
| Durable timers and external waits | Designed: persisted eligibility/wait state, authenticated correlated event admission and releasable attempt scopes; Provider-backed: Cloudflare sleep/events | Durable timers and workflow messages | Context sleeps and durable communication/wait mechanisms | WAIT and event/task-completion mechanisms |
| Retries, timeouts and cancellation | Designed: one effective retry owner, node/run budgets, fenced attempts and reconciled cancellation; Gap: complete cross-profile qualification | Workflow/activity policies and cancellation protocols | Runtime/context failure and retry behavior | Workflow/task retry, timeout and lifecycle policies |
| External effect correctness | Designed: immutable effect keys, destination receipts, unknown-outcome reconciliation and conditional commits | Activities still require effect-side idempotency | Journaled external steps still require effect-side idempotency | Worker/system-task effects require effect-side deduplication |
| Durable source-code replay | Outside target: no persistence of arbitrary Kotlin coroutine stacks. Explicit plan/state recovery is selected; Cloudflare retains its own provider execution history | Deterministic workflow-code replay | Compatible handler replay over recorded context actions | Explicit task-state orchestration rather than an arbitrary coroutine stack |
| Stateful per-key service ownership | Designed: graph/actor ownership backed by persistent claims and resource fences; Gap: durable mailbox/invocation sequencing where required | Workflow-local state and workflow identity | Virtual Objects with keyed persistent state | Workflow/task state; domain service ownership remains in workers |
| Versioning and migration of running work | Designed: pin plan/schema/handler revisions and migrate, retain compatible handlers or quarantine; Gap: full rollout/history compatibility protocol | Replay compatibility and worker/code versioning mechanisms | Handler/journal compatibility and deployment mechanisms | Versioned workflow definitions and compatible task workers |
| Compensation and bounded loops | Gap: explicit authorized compensation and bounded iteration/checkpoint semantics; finite DAGs alone do not supply them | Authored workflow logic and compensation activities | Authored durable service/workflow logic | Loop/subworkflow operators and authored compensation workflows |
| Operating and inspecting runs | Designed: graph queries join definitions, journal positions, scoped receipts, traces and provider evidence; Gap: Work inspector and repair commands | Workflow history/visibility and operational tooling | Invocation/state inspection and operational tooling | Workflow/task inspection, APIs and operational tooling |
Primary references: Temporal execution/history, timers, workflow messages and activity effects; Restate context actions; Conductor authoring, operators, waits and task lifecycle. Deployment and SDK profiles affect reference behavior. The table describes the core execution models; it does not assume every integration or commercial feature belongs to every edition.
Request DAGs, distributed computation and platform reach
| Feature | Proposed Reaktor Work | Twitter Nodes reference | Ray DAG reference |
|---|---|---|---|
| Typed dependent results | Designed: typed ports/outcomes and per-run shared-result reuse | Typed asynchronous node outputs, required/optional dependencies and reuse within the node instance | Bound task/actor dependencies and distributed result references |
| Demand, branching and parallelism | Designed: lazy branch selection and bounded readiness scheduling | Asynchronous dependency composition and branching | Lazy distributed task/actor graph execution |
| Business-workflow durability | Designed: journal/checkpoint recovery and destination receipts; Provider-backed: Cloudflare steps | In-memory dependency coordinator; remote calls do not persist the graph | Compute recovery mechanisms; not a substitute for a business-effect journal |
| Large distributed compute/resource scheduling | Outside target: no Ray-style object store, GPU cluster scheduler or distributed tensor pipeline is specified | Application-selected services/executors | Distributed task/actor and resource-placement model |
| Mobile/browser background execution | Designed: WorkManager, BGTaskScheduler/native transfers and qualified browser hosts/storage | App-specific lifecycle/storage integration remains outside the request graph library | App-specific lifecycle/storage integration remains outside the compute graph API |
| Shared application semantics across device and server | Designed: KMP handlers plus graph capability, authority, data and placement contracts | Java service dependency library | Distributed compute runtime with its own task/actor model |
References: Twitter Nodes, Ray DAG and Ray resource scheduling. Reaktor's platform integration is a broader design scope, not proof of stronger server durability or faster distributed computation.
Feature parity requirements and deliberate differences
For the finite durable-workflow use cases we intend to support, the required parity is behavioral: a committed run survives restart; a recovered join reuses committed child results; waits survive without retaining live coroutines; duplicate dispatch preserves effect identity; revocation/cancellation remains scoped; and a running definition cannot silently change after deployment. Cloudflare's provider covers part of this on its host. Reaktor must implement and qualify these laws itself for Spring and qualified local profiles.
The largest remaining gaps are the durable graph coordinator, persisted waits/events and child membership, distributed claim/reconciliation, version-compatible recovery, operator repair tooling and measured scale. Named compensation/loop consumers need explicit execution laws before support is claimed. Full deterministic replay of arbitrary Kotlin code and Ray-scale compute infrastructure are outside the current target. The source still contains the legacy facade and placeholders; none of these comparisons establishes delivered parity.
Reaktor's potential advantage is that graph authoring, AuthContext, data/file ownership, service contracts, native lifecycle adapters and human/agent inspection share one scoped model. The reference engines also support application integrations; their use of a separate execution model is not evidence that they lack security or observability. The integration map and measurement protocol define how to prove Reaktor's advantage rather than infer it from a feature checklist.
Planned design diagrams
These diagrams describe the target architecture. The progress ledger identifies the implemented subset and its qualification. Start with the core architecture and platform profiles, then follow the typed DAG and durable recovery diagrams. Select an image to open it at full size. Editable Mermaid sources accompany each image.
Graph-owned work
Diagram source. This shows the Reaktor-managed Work profile. Cloudflare's provider-owned step history is a distinct recovery authority, linked through explicit handoff receipts in the next diagram. Definition, run and attempt identities remain distinct.
One contract, qualified platform profiles
Diagram source. Each row names a selected profile, not a universal pipeline. Brokers can deliver ordinary work or a Workflow handoff; not every cloud task needs a Workflow. Android/iOS/browser wakeups remain host-controlled. Browser service-worker execution is conditional on storage and realm qualification. Distributed handoff needs explicit authority and data-placement checks; these are not five replicas racing over one global WorkStore.
Durable state, execution and wakeups
Schedulers create execution opportunities. The authoritative store owns accepted work. Commit intent before requesting a wakeup; recover committed-but-unscheduled work on subsequent eligible activation. Native scheduler databases remain provider bookkeeping, rather than a second business journal.
WorkStore owns durable admission and conditional state transitions. WorkRuntime claims bounded work and runs an attempt with structured coroutines. WorkScheduler arms, cancels and reconciles platform wakeups. Broker delivery state belongs to the broker; Cloudflare Workflow step history belongs to Workflows. Work records link those histories through stable receipts instead of copying them into a competing orchestration engine.
Graph ownership and the small contract
Definitions, required capabilities, typed ports, lifecycle and authority belong in headless reaktor-graph-runtime. Handlers can be ordinary suspend functions resolved through existing Provider/Consumer ports; neither every handler nor every execution row needs an active graph node. A service worker or OS callback activates a minimal authorized graph scope, with no Compose, DOM navigation or workbench dependency.
| Proposed role | Responsibility |
|---|---|
WorkDefinition<P> | Stable semantic ID/revision, payload codec/version, requirements and graph-resolved suspend handler |
WorkRecord | Operation/effect identity, immutable input fingerprint, environment/principal scope, eligibility, state and result references |
WorkStore | Atomic admission, indexed due queries, fenced claims, checkpoint/result commits, cancellation and observation |
WorkRuntime / WorkContext | Bounded drain and one attempt's authorized dependencies, deadline, claim token, progress and checkpoint access |
WorkScheduler | Backend wakeup reconciliation and capability reporting; no independent task payload authority |
These are design names, not available APIs. An indicative storage boundary is:
interface WorkStore {
suspend fun admit(intent: WorkRecord): Admission
suspend fun claimDue(scope: WorkScope, now: Instant, limit: Int): List<ClaimedWork>
suspend fun renew(claim: ClaimToken): ClaimToken?
suspend fun commit(claim: ClaimToken, outcome: AttemptOutcome): CommitDisposition
suspend fun requestCancel(scope: WorkScope, id: WorkId)
fun observe(id: WorkId): Flow<WorkRecord?>
}
The claim token carries the operation, owner, monotonic fence and expiry. Renewal and completion conditionally validate the current token. Owner strings or process-local mutexes cannot prevent a stale attempt from acknowledging after another executor reclaimed the operation. Resource-side fencing or idempotency still protects external effects.
Admission distinguishes rejection, durable acceptance and explicit handoff. Observation distinguishes waiting, OS-deferred, running, retry eligibility, blocked authority/capability, acknowledged success, cancellation requested, cancelled, unknown remote outcome and quarantined input. Scheduler registration is never displayed as business completion.
Typed DAGs and workflow execution
Exploit the existing graph for composition, dependency resolution, capabilities and inspection. Add execution semantics to the relevant edges; do not interpret every port binding, lifecycle relationship or visual edge as a scheduling dependency. Current binding direction is consumer → provider, while produced values can travel provider → consumer. The graph substrate proposal and unified system graph own semantic definitions and execution profiles. Their immutable IR/compiler plans remain proposed; today's editor GraphDocument is not already that compiler input.
The proposed workflow extension separates an immutable definition/validated plan, a scoped run, and individual attempts. The plan pins definition/schema revisions, dependency and control-flow semantics, requirements and target bindings. The run carries its identity, input fingerprint, scope and result references. Attempts retain the existing Work claim/effect laws. These are extensions of the graph and Work records, not a separate graph database or an active node for every historical attempt.
Diagram source. Arrows here explicitly mean execution/data dependencies. A port binding or an editor edge acquires that meaning only through its declared relation. Request runs reuse live results; durable runs reuse committed outcomes and recover interrupted attempts.
| Law | Request-scoped coroutine DAG | Durable workflow profile |
|---|---|---|
| Dependency readiness | Start demanded nodes when required inputs are available; bound independent concurrency | Recover readiness from committed results or provider history; dependencies do not mean sequential topological execution |
| Shared dependency | Reuse one result per semantic node invocation within a run | Reuse a committed output; an interrupted attempt can repeat. Reuse is not exactly-once external execution |
| Outcomes | Preserve typed success, absence, failure, timeout and cancellation; optional dependencies have explicit fallback policy | Persist outcome/disposition and exhaustion; optional failure must not accidentally cancel required siblings |
| Branches and joins | Evaluate only the selected branch; declare all/any/quorum join and loser cancellation policy | Record branch choice and accepted join membership/result so recovery does not choose a new path |
| Dynamic fanout | Bounded split/collect with stable item keys and explicit duplicate-item handling | Commit the expansion and child identities before dispatch; retries reuse children and prevent unbounded expansion |
| Effects and sinks | Required effects are awaited; best-effort work has a visible weaker contract | Required deferred effects use durable outbox/handoff receipts. Detached coroutines are not durable sinks |
| Deadline and cancellation | Structured lifetime with node/run budgets and declared failure propagation | Persist cancellation and reconcile in-flight providers; compensation is a separately authorized operation, not automatic rollback |
| Version changes | Run a compatible installed definition | Pin the plan/handler version; retain compatible workers or explicitly migrate/quarantine. Changing a title must not rename a durable step |
The minimal proof is a diamond: A → B, A → C, then B + C → D. A executes once per live invocation, B and C may run concurrently, and D waits for both. Durable execution additionally proves that a crash after B's receipt reuses B while recovering C. Count physical attempts separately from logical node results and destination effects. Twitter Nodes supplies the request-graph reference; durability is a separate qualification.
Coroutines own a request or execution attempt. Pure intermediate calculations need no database write per expression; only required durable decisions, outputs/checkpoints and effects cross a durable boundary. For Cloudflare, map those boundaries to stable step.do, wait and sleep operations and retain compact outputs/references. For the native Reaktor coordinator, persist explicit plan/node/wait transitions and restore committed outcomes. Recovery reconstructs a new bounded attempt; it does not resurrect an old coroutine stack.
A distributed plan references installed, versioned handlers and authorized durable inputs. Typed ports do not serialize live services or arbitrary Kotlin closures onto another host. Placement checks data locality, available capabilities, schema/version compatibility and authority before handoff. Reject cycles in the finite DAG profile. Actors, feedback/dataflow streams and bounded workflow loops have different execution semantics; a DAG evaluator does not turn the whole Reaktor graph into a DAG.
Use graph validation/traversal to diagnose missing providers and incompatible placement before starting effects. A future validated plan can prune undemanded pure nodes, reuse run-local inputs, batch calls whose Service contract permits batching and place computation near authorized data. Such transformations must preserve outcomes, effect identity/order, deadlines and recovery boundaries. Measure the benefit against the unoptimized plan; graph visibility alone is not a performance result.
Persistence and effect guarantees
Use Reaktor's data contracts and the actual resource authority. Local work uses qualified ObjectDatabase/SQLDelight storage; server mutations use their authoritative database and transactional outbox. WorkStore adds work-specific indexed claims over generic DB transaction/conditional-write primitives. DB does not depend back on Work.
Current ObjectDatabase offers serialization, individual operations, raw import/export and process-local events. It does not expose a portable durable claim or public transaction contract. Two ObjectStore.put calls and a Flow collector do not establish atomic admission. Qualify the missing boundary on the actual connection, publish cache/events after commit, and keep network effects outside storage transactions.
Intent, attempt metadata, checkpoint/progress and completion receipts are ordinary persistent Reaktor models. Keep them bounded and inspectable; no new private Meeseeks-style task database. A domain's existing outbox remains its authority, with WorkStore adapting it instead of duplicating its pending queue. A live Flow is an observation mechanism, not a durable completion cursor. Cursor replay and its handling result require persistent, redelivery-safe commits.
Design for repeated attempts and at-least-once delivery where the backend provides it. Durable acceptance preserves intent; it does not promise that a closed browser or mobile OS grants execution. One logical effect requires a stable key enforced or reconciled at the destination. Persist unknown outcomes when a provider may have committed before the response was lost. Cancellation prevents future eligible attempts after it takes effect; it cannot erase an already accepted external effect.
Retry has one effective owner and a bounded budget. Separate transport, broker, Workflow-step and domain retries so they do not multiply invisibly. Persist attempt count, retry reason, next eligibility, deadline and exhaustion. Unknown payload/definition versions, missing files and revoked authority have explicit dispositions.
Retained journals and replayable projections
The first implementation is an opt-in ObjectDatabase journal on SQLite and D1. Configure journalStorePrefix = WorkScope.STORE_PREFIX before admitting Work; a database without retained changes rejects the event API. WorkStore.readEvents(scope, consumerId, limit) returns a bounded ordered batch; acknowledgeEvents(batch) conditionally advances that consumer's persisted cursor after successful processing. Stale batches cannot advance a changed cursor. Event identity is the sequence within that database authority, not a global cross-provider position.
Record writes and journal appends are atomic; external projection/effect processing and cursor acknowledgement are separate commits, so consumers must deduplicate redelivery. Existing rows are not retroactively journaled. The current profile keeps full record snapshots and has no automatic retention/compaction or production quota policy. It does not yet provide an atomic domain outbox or projection transaction. These are explicit remaining gates, not guarantees supplied by the live Flow or the inspection window.
Kleppmann's Craft talk and edited transcript explain why independent writes can diverge and how ordered durable records let consumers recover and build derived views. Ordering is per declared partition, and asynchronous views can lag. Our application of that model is a proposed Work protocol, aligned with data transactions and Bus:
Diagram source. The recovery exchange is an alternative path after interruption. It first acquires a new current claim; it does not blindly repeat a completed operation. A remote effect and its local acknowledgement are separate commits. Projection replay rebuilds views without executing those effects again.
Select one authority for each transition. Where a DB owns the domain, commit its state change, work transition and outbox/journal entry in the same transaction; publish after commit. A retained journal may also be the authority under an explicitly qualified log-first profile. WorkStore adapts that choice. There is no independent “write DB, send Queue, update dashboard” success path and no requirement to install Kafka for a local app.
Persist bounded, versioned records for admission, claims/attempts, checkpoint/result references, handoff decisions and cancellation/terminal transitions as required by the selected recovery contract. Records identify scope, operation/run/node invocation, event ID, sequence domain/epoch, definition/schema revision, causal parent and receipt reference. Timestamps describe time; they do not establish commit order. Serialize conflicting transitions within their declared aggregate/partition and fence writers. Independent partitions remain concurrent; no global scheduler or globally ordered log is implied.
Projection handlers commit their derived state and processed position atomically when colocated. Remote effects use inbox/deduplication and receipt reconciliation because a cursor transaction cannot include an arbitrary HTTP destination. Acknowledge a contiguous processed prefix, or track gaps explicitly when processing concurrently. Report each view's source position, lag and provenance; route read-your-writes requests to the authority or wait for the required position. An expired cursor requires a compatible snapshot plus gap-free change handoff, rather than guessed replay.
| Durable object | Owns | Does not establish |
|---|---|---|
| Domain journal/outbox | Accepted facts/commands and publication obligations | That a remote provider has already acted |
| Workflow provider history | Its durable steps, decisions, waits and outputs | A cross-database atomic commit or arbitrary external exactly-once effect |
| Queue/Pub/Sub subscription | Delivery, acknowledgement and configured retention/replay | An indefinitely retained ordered source log; the adapter must declare its actual profile |
| Projection/checkpoint | A derived view and the source position it has durably processed | That other projections or devices reached the same position |
| Trace/telemetry stream | Diagnostic observations with provenance | Authoritative admission or recovery history |
Build Hangar views, completion subscriptions and authorized agent queries from these records instead of creating another operational truth store. Retain provider mappings and terminal receipts needed beyond provider-history expiry; do not mirror an entire provider engine. Replay into a new projection must not resend media, notifications or payments. Re-executing an effect is a distinct authorized command using the original reconciliation protocol. Retention, snapshots, compaction, schema compatibility and deletion fences follow the data lifecycle, so old replay cannot resurrect erased state. Process-local Flow events are useful live notifications, not this retained journal.
Advantages to earn through Reaktor integration
The strongest potential advantage is an integrated definition, authority, data and inspection model across device, browser and server hosts. It is not a claim of a faster coroutine scheduler or better provider durability. Each row names an existing seam and the missing Work integration needed to earn the advantage.
Are we exploiting Reaktor properly?
Partly implemented. New Work definitions register as typed provider ports on a headless graph node. Attempts use those ports and their suspend interceptors, fresh Auth-core authorization and ObjectDatabase conditional writes. Feature.Work now points to this runtime and the BestBuds diagnostic callers have been cut over. The wider integrations below remain delivery gates. “Everything in Reaktor” means reuse the owner of each needed concern, not load every module into a background host.
| Reaktor seam | Work integration and practical advantage | Current boundary / required proof |
|---|---|---|
| Graph runtime, typed ports and capabilities | Reuse typed dependency bindings and interceptors; activate only the background operation's headless scope | Runtime/ports and Graph.shape() exist. Work installation, readiness evaluator and target capability validation remain proposed; no UI dependency in an OS/SW callback |
| Semantic graph definitions and plans | One revisioned definition supports code authoring, validation, target lowering and graph inspection | Portable IR/compiler is proposed. Validate data/control dependencies, cycles, codecs, placement and source maps before claiming cross-host execution |
| Data | Existing domain outbox, checkpoints, blobs and journal become one scoped recovery surface | Storage exists; portable atomic Work claims/journal/cursors are missing. Qualify each selected authority and browser realm |
| Service and Bus | Typed effect calls join operation IDs, publication obligations and provider receipts | HTTP/services and some broker adapters exist. ServiceTransport.WORKFLOW/QUEUE/PUBSUB enum entries are not complete executors; add qualified handoff/reconciliation |
| Auth | Resolve fresh scoped credentials at each attempt and gate, including delegated server execution | AuthContext/requirements and graph runtime exist. Work must enforce captured scope, current grants, revocation and authenticated human-gate resolution |
| Media and IO | Durable file references and native transfer receipts allow stage reuse without copying bytes into scheduler payloads | Current generic uploader uses ByteArray. File staging, resumable transport and background URLSession bridges need their own implementation/evidence |
| Actors and lifecycle | Reuse actor addressing, bounded mailboxes and supervision for local coordination; release attempt resources with the host scope | Current mailbox and actor timers are process-local. WorkStore owns durable waits and shared claims. Qualify explicit job parenting, process death, cancellation and overlapping executors |
| Tooling and operational evidence | Humans and agents inspect the same run and issue scoped retry/cancel proposals with receipts | Tooling and Fact/TruthClass seams exist; Work queries/commands, provider joins and redaction remain to wire. Source/inferred status is not live execution evidence |
| Telemetry and Performance | Reuse port interceptors, instrumentation visitors and report contracts; join definition/run/attempt/effect IDs across hosts | Instrumentation and harness/report models exist; Work correlation and measurements are absent. Report skipped/opaque boundaries and keep the bridge headless |
| FFI, FlexBuffers and Mesh | Reuse qualified language bridges/codecs and live progress delivery where the host needs them | These do not supply durable scheduling or arbitrary closure migration. Add them only for a demonstrated consumer and measure transfer/serialization overhead |
Required graph integration
- One definition and one admission path. Extend graph-owned operation contracts and handler bindings with the Work semantics they need. Human, API, timer, broker and agent entry points normalize and validate the same scoped command before admission. Reuse Service schema descriptors where applicable; do not create a second string-to-handler registry or treat a display label/random activation UUID as a durable definition ID. Portable plan compilation remains a delivery task.
- Explicit execution relations and placement. Reuse graph traversal and wiring diagnostics, then validate the declared data/control dependencies, outcome policies, codecs, effects and available target providers. Reuse a pure result only within its valid input/revision/authority scope. Never cache a mutable read or side effect merely because two paths reach the same node. Only installed, compatible handlers and durable authorized input references cross hosts.
- Headless activation with an attempt lifetime. Reuse
reaktor-graph-runtimeand its dependency-boundary check for the minimal operation scope. Keep background lifetime independent of a screen activation; closing a screen does not delete accepted work. An attempt's children must have explicit job parenting, deadline and host-expiration cancellation. The currentConcurrencyCapabilityImplcreates a freshSupervisorJob(); accepting a parent context alone is not proof of the required cancellation relationship. - Actors coordinate; storage arbitrates. A local actor can serialize admission/reconciliation for its owned partition. Persist run/node/wait decisions and fence distributed writers in the authority. Actor
send,ask,scheduleandeveryare useful live mechanisms, not durable cross-process mailboxes or timers. Enforce bounded admission, dispatch, parallelism and payload size, with a visible overload disposition. - Typed, authorized effects with shared receipts. Invoke existing Service/Data/Media ports under the captured environment, tenant and principal scope. Resolve fresh credentials and authorize the actual attempt/effect and human-gate command; a previous secured-port connection is not a lasting grant. Keep effect keys and provider receipts through retries, handoffs and reconciliation. Notification/analytics completion is a domain outcome; push or Pub/Sub delivery alone does not complete the work.
- One inspection and command surface. Extend graph queries, operation commands and port telemetry so tools, Hangar and agents can follow definition → run → attempt → effect → provider receipt. Preserve redaction, provenance, projection position and unknown coverage. Retry, cancel, migrate and replay-effects use validated, authorized commands with receipts; chart layout or an agent's proposed patch cannot change a live run implicitly.
These are acceptance requirements, not new implemented APIs. The smallest convincing proof is one real upload or archival flow: graph-validated dependencies, a headless host, atomic admission, stable effect identity, crash/revocation recovery, and the same truthful run visible through tooling. Then qualify the DAG and each selected platform profile. UI, navigation and workbench presentation remain optional consumers of the same model; FFI, codecs, Mesh and AI participate only where a concrete handler or authorized tool needs them.
Android WorkManager
Use a direct CoroutineWorker bridge into the same WorkRuntime, with an Application-owned registry and WorkerFactory that resolve a headless scope. Configure initialization and the merged manifest consistently; do not require an Activity to construct workers or recursively initialize WorkManager inside its own configuration. Follow custom initialization.
Coalesce wakeups per compatible scope/constraint profile, pass opaque references rather than file bytes, and reconcile the desired next wake after every bounded drain. Network, charging and battery policy map to native constraints. Unique work and native chains may coordinate wakeups, but WorkStore remains the source for business ordering and completed stages. Qualify enqueue-during-drain races rather than assuming a unique-work policy prevents lost wakeups.
Choose ordinary, expedited or long-running work according to the operation. Large user-initiated transfers may need native transfer jobs or a foreground service with visible progress; WorkManager is not an unlimited transfer window. Transfer options and long-running workers own platform restrictions. Process death, reboot and user force-stop are distinct qualification cases.
iOS BGTaskScheduler and transfers
Register app-owned refresh/processing identifiers during application launch, declare permitted identifiers and background modes, and reconstruct the minimal scope when a handler runs. BGAppRefreshTask supports a small refresh opportunity; BGProcessingTask supports eligible heavier work. These are OS-managed opportunities, not precise deadlines. BGTaskScheduler and the launch/expiration example are the native references.
Bind expiration to attempt cancellation, persist progress, close resources and call setTaskCompleted exactly once with the actual handler outcome. Reconcile pending eligibility and resubmit. A simulated callback tests the bridge; real-device OS-granted execution is separate evidence. Foreground reopening must recover accepted work even if no background window arrived.
reaktor-media/IO owns background URLSession transfers, persistent files and transfer delegate restoration when required. BGTaskScheduler itself does not continue arbitrary uploads through suspension. Background uploads use file-backed tasks, with a stable session identifier recreated on relaunch. Link native transfer IDs and remote receipts to the same operation; reconcile completion callbacks after relaunch. See background transfers.
Where the OS/SDK supports BGContinuedProcessingTask, expose a separate profile for a user-started foreground operation that may continue after backgrounding, such as media processing. Report native progress, honor user cancellation and qualify submission/resource policy; optional GPU work requires supported resources and the entitlement. This is distinct from later refresh/processing wakeups and can still be terminated. See Apple's continuous processing guidance.
Browser windows, workers and service workers
Build the service worker as a separate Kotlin/JS entrypoint over headless graph, DB and Work dependencies. The window owns UI and immediate interaction; a dedicated Web Worker hosts CPU work; a service worker handles browser-granted background events. JS coroutines organize asynchronous attempts but do not create parallel CPU threads. Kotlin JS dispatching describes the event-loop boundary.
| Wake source | Role |
|---|---|
| Enqueue, startup, visibility becoming visible | Drain or recover while an authorized page is available |
online, authenticated message to the service worker | Hint to recheck eligibility; not proof of network or authority |
| Background Sync | Optional retry opportunity where supported |
| Periodic Background Sync | Optional refresh; not a calendar or exact interval guarantee |
| Web Push | Permissioned server event, with the notification behavior required by the selected browser |
| Explicit server handoff | Execute remotely placeable work after durable, authorized provider admission |
Use a small stable wake-tag set per compatible profile, rather than one tag per record. Each wake queries due records. Feature-detect APIs and record the actual profile. Unsupported Background Sync or Periodic Sync leaves intent pending for foreground recovery; timers do not replace closed-page execution. Push is not an unrestricted silent scheduler.
Call event.waitUntil(promise) during the event callback. The promise covers bootstrap, bounded drain, checkpoint/result commit and cleanup. CoroutineScope.promise bridges suspend code; detached launch does not extend browser lifetime. waitUntil is the event contract, and background operations must still tolerate termination.
Use Web Locks for live same-origin coordination, alongside persistent claims and fences for termination recovery. Hold storage locks for bounded transactions, not across network transfers. Scope lock names without leaking account identity, and qualify overlapping tabs, worker versions and expiry.
Current browser storage
Current source selects WebSqliteObjectDatabase: SQLDelight over a dedicated SQLite/Wasm worker with OPFS and Web Locks, including legacy IndexedDB migration. The supplied proposal's assumption that browser ObjectDatabase lacks persistence is outdated; IndexedDB is no longer the selected default. The remaining question is which storage access works in each execution realm.
The current OPFS VFS uses synchronous access handles, restricted to dedicated workers. Importing the window database opener into a service worker does not establish closed-page access. OPFS handle restrictions are a qualification boundary.
Keep the SQLite profile for window/dedicated-worker execution. Before local service-worker draining, qualify a DB-owned realm-compatible access path to the same authority. IndexedDB is a possible explicitly selected headless profile because it is available in worker globals; choosing it requires coordinated domain storage, transactional claims and migration, not a hidden second queue beside SQLite. Use short IndexedDB transactions, without network awaits inside claims. Until that gate passes, expose local closed-page draining as unsupported and retain foreground recovery or explicit server handoff.
Eviction, quota denial, cleared site data, private browsing and migration need visible admission/recovery outcomes. Browser persistence requests are not unconditional retention guarantees.
Cloudflare Workflows, Queues and Pub/Sub
Use Cloudflare Workflows for durable multi-step execution and waits. Effects run inside awaited steps with deterministic IDs and compact returned receipts. Workflows owns step history/retries; Work links a scoped operation to a stable provider instance and reconciles its result. A repeated step still needs effect-side deduplication. Do not run a second local retry loop over handed-off work.
Use Cloudflare Queues for buffered competing delivery, bounded fanout and retry/dead-letter handling. Persist publication intent with the domain change. Acknowledge each message after durable effect commit or confirmed matching handoff; unknown dispatch outcomes remain recoverable. Queues does not provide ordered delivery or an end-to-end exactly-once effect.
The selected Pub/Sub profile uses existing GCP Pub/Sub, through reaktor-google and Bus. Workers can publish through authenticated REST or receive validated push ingress; a binding or Node compatibility flag alone does not establish a subscriber. Verify the signed token, expected service-account identity and audience, and persist admission before successful acknowledgement. Select push or pull delivery for the host and follow push authentication; never place service credentials in browser payloads.
Cron reconciles due work or starts bounded archive batches. DO alarms fit a DO-owned aggregate/due set. waitUntil extends an invocation; it is not durable admission. Do not add a second DO ledger when Postgres owns the mutation/outbox. Thin TypeScript hooks expose queue/Workflow lifecycle and call shared Kotlin logic. The cloud execution chapter owns provider handoff details and current implementation status.
Spring Quartz, queues and Pub/Sub
Integrate Quartz through Spring Boot's spring-boot-starter-quartz and managed scheduler lifecycle. Configure a persistent JDBC store for restart recovery and a shared cluster profile for replicated servers. RAM scheduling or per-pod SQLite is not a replicated durable backend. Use controlled schema migrations; startup scripts that drop tables are unsuitable for preserving schedules. Spring integration and Quartz clustering define those mechanisms.
Quartz triggers wake bounded drains or admit revisioned schedule occurrences. The authoritative server DB owns claims, effect keys and completion. Declare timezone, cron dialect, DST, overlap and misfire/catch-up policy; missed triggers must not create unlimited business effects. Clustering and per-JobKey exclusion do not replace resource claims or deduplication.
Queue consumers and GCP Pub/Sub pull/push adapters enter the same admission/completion contract. Broker ack deadlines, retry/DLQ and backpressure belong to the delivery adapter. Acknowledge durable processing or explicit handoff, and revalidate scope before execution. Shutdown stops new claims, drains bounded attempts and leaves recoverable ownership; Quartz jobs do not detach coroutines and report completion while effects continue.
Reaktor's own durable graph coordinator
For multi-host workflows, the selected design is Reaktor-owned orchestration using the existing headless graph/runtime, authoritative WorkStore/journal and Service/Bus contracts. Quartz supplies timing; queues/Pub/Sub supply delivery. Temporal, Restate and Conductor are comparison references only. Qualification follows the feature parity gates.
- Admit a scoped run with an immutable validated plan and input/schema/handler revisions. Persist demanded node invocations, dependency membership and the initial ready set against that run's authority.
- Conditionally advance run/node state using versions and fences. Commit required ready-node dispatch intent through the same authority's outbox. Workers claim a node invocation with the same stable identity on redelivery; no broker message becomes a second run authority.
- Execute bounded coroutine attempts through authorized service/data/file ports. Reconcile uncertain effects, then commit the node outcome and required run/join/dispatch transitions atomically within their declared authority. Network effects remain outside the transaction. Independent ready nodes can execute on different workers; their committed results determine further readiness.
- Persist branch choices, dynamic child membership and accepted join results. Recovery reads these decisions and outputs rather than generating new children or rerunning acknowledged effects. A run-level actor can coordinate local transitions, while shared conditional storage protects against replica/process overlap.
- Suspend durable waits by committing due eligibility or a correlated gate/event subscription, then releasing attempt resources. Quartz/reconciliation scans wake due state; authenticated event admission atomically records resolution and future dispatch intent. Handle duplicates, early events, timeout races and cancellation with explicit dispositions. Do not hold a sleeping coroutine across a restart.
- Reconcile committed-but-undispatched nodes, expired claims, missing wakes and unobserved results through bounded indexed scans. Persist retry/deadline/exhaustion and cancellation state. Declared timer lateness and recovery bounds depend on this deployed reconciliation path.
- Retain compatible plan/handler versions or perform an explicit migration/quarantine. Bound history and projection cursors, preserve deletion fences, and expose authorized run/node/wait inspection and repair receipts.
This is the Spring design to implement, not an existing coordinator. Durable waits, joins, replica recovery and version coexistence require their own proof; implementing Quartz and queue consumers alone does not establish them. Cloudflare runs continue to use Workflow-owned step history, with stable Reaktor admission/result mappings instead of a competing Spring coordinator draining the same run.
Media, archival and placement
For media: stage durable files, commit intent, upload to a stable authorized key/session, persist its receipt, send the domain command with the original key, reconcile and release resources. Checkpoints reuse completed stages; partial-byte resume requires transport and server support. Native/broker payloads contain references, not large byte arrays.
For archival: admit a run with dataset scope and consistency policy, checkpoint bounded pages/chunks, publish a verified manifest, then apply retention after confirmation. Define the snapshot boundary so concurrent writes do not yield a falsely consistent backup. Cron and Quartz trigger execution; archive receipts establish recovery. Backup/restore/erase authority remains with data lifecycle.
Placement validates required data, capabilities and current authority before acceptance. Device-local work stays local. Closing a browser does not automatically move uploads to the cloud: remote execution requires explicit authority, durable remote inputs, a matching handler version and a confirmed handoff receipt. Inspectors may synchronize authorized summaries; sensitive journals are not automatically replicated across accounts/devices.
Hangar inspection and control
Hangar Cloud has a Work subpane beside Resources, Operations, Deploy, Pipeline, Runs and Cost. Its three connected views cover work records, workflows/DAGs and retained execution history. Workflows contains both persisted runs and installed or retained definition revisions. The shared inspector shows revision, attempts, fence, lease, checkpoint/receipt presence and source activation. It does not export payloads, checkpoint values, domain receipt bodies or failure text.
WorkInspector is a graph-owned node attached to an existing WorkRuntime and its authoritative WorkStore. WorkSource identifies an exact host activation and WorkScope; every read resolves current authority and requires work.inspect.metadata. WorkQuery bounds a page to 1–128 entries and binds its cursor to the source, view and filters. Record/run pages reject revision drift. Journal pages advance by retained sequence without acknowledging execution consumers. Missing history before journal activation, unknown retention start and uninstalled graph definitions remain explicitly partial.
WorkInspectionSession supplies typed ports, subscriptions and cancellation. First pages refresh every 15 seconds; cursor pages are retained observations. Disconnection or host replacement invalidates the active read, and late responses cannot replace the new host's state. The pane distinguishes loading, live, stale, partial, disconnected, unsupported and failed observations. Filters and selection survive pane changes through Hangar's existing navigation and graph-owned pane state.
JVM hosts register an authorized inspector with the kernel. Connected debug devices advertise work.inspect through DevTools; discovery and reads verify the device descriptor's activation before and after a request. The mobile diagnostic scope grants metadata inspection and limited control only in developer builds. Browser and Cloudflare execution adapters exist, but their remote inspection endpoints are not connected. The kernel also exposes read-only work_hosts and work_inspect MCP tools using the same session and authorization path.
The DAG canvas uses the durable run's stored manifest, including the exact dependency edges and definition version. Installed definitions can be inspected before admission. Completed nodes and branch selections come from the durable run; execution history comes from the Work journal. Provider execution observations carry their own source and observation time and match the retained handoff identity. An observed provider completion does not rewrite WorkStore state.
WorkLinks preserves trace, deployment and Cloud resource identities on admission, including DAG child work. The inspector opens the existing telemetry trace filter, deployment receipt or Cloud resource only when the matching environment and identifier are present. Missing correlation remains unknown; the trace filter covers the telemetry observations currently retained in Hangar.
WorkControlCommand carries command identity, exact source activation, work identity, expected revision and action. The host independently authorizes work.control.cancel, work.control.retry or work.control.reconcile, checks the installed definition and applies a conditional store transition. Cancellation advances the fence; it cannot undo an external effect. Retry requires an explicit operatorRetry policy, remaining attempts and no unresolved handoff. Reconciliation accepts evidence from the host's trusted provider reader. Hangar uses its existing command approval and receipt mechanisms; capability advertisement alone grants no authority. Payload inspection remains a separately authorized work.inspect.payload API and is not exposed by the debug metadata transport.
Qualification and inspection
Prove real effects through commit-before-wake crashes, process/event termination, duplicate delivery, stale claims, lost responses, cancellation, account changes, definition upgrades and missing resources. Android/iOS verification uses connected physical devices. Browser gates include reload, multiple tabs, service-worker update/termination, unsupported APIs and storage loss. Server gates include replica restart, broker redelivery, Workflow retry, Quartz misfires and archive interruption.
Hangar, DevTools and agents query persistent records through authorized graph operations: definition/revision, operation, backend/profile, next eligibility, attempt/fence, checkpoint, result and causal trace. Desired, recorded, observed, stale, unknown and unsupported claims remain distinct. Redact payloads and bound queries. Proposed metrics cover admission, oldest pending age, attempts, blocked/quarantined work, handoffs and reconciliation; an idle inspector is not execution evidence.
Reproducible measurement protocol
Use reaktor-performance report/harness models. Measure adapter overhead and correctness first, then compare supported end-to-end profiles. Compare raw coroutines against Reaktor's request DAG on the same host, raw Cloudflare Workflows against the Reaktor profile in the same account/configuration, and Reaktor's native Spring coordinator against a direct implementation using the same DB, Quartz and brokers. The external systems remain capability references; numerical comparisons with them require equivalent reproducible reference data and do not make them dependencies or backends. No external engine is required to qualify Reaktor. A closed phone and a cloud server are separate availability profiles, not comparable latency samples.
| Workload / fault | Required evidence | Measurements |
|---|---|---|
| Chain, diamond and bounded wide DAG; required/optional failure and lazy branch | Correct typed outcomes; shared logical result reuse; measured overlap of ready siblings; rejected cycles | Scheduling/codec overhead, throughput, p50/p95/p99 critical-path latency, peak memory and active tasks |
| Durable fanout/join with duplicate or reordered delivery | Stable expansion/child IDs, bounded concurrency, committed-result reuse and no duplicate destination effects | Admission-to-completion latency, attempts/effects, queue age, storage/provider calls and cost per completed run |
| Kill after admission, claim, remote acceptance, result commit or cursor commit | Every accepted recoverable operation reaches a truthful disposition; stale writers cannot ACK | Time to recovery, lost accepted operations, uncertain outcomes and duplicate effect count |
| Human wait, authority revocation, cancellation and definition upgrade | Authenticated gate event bound to run/node/version; compatible worker or explicit blocked/migrated disposition | Wait/resume latency, retained bytes, history growth and reconciliation calls |
| Multi-tab/SW termination; Android/iOS process death and native transfer restoration | Qualified realm storage and event/native lifetime; supported foreground/background recovery reported separately | Drain/startup cost, checkpoint reuse, memory/disk use, wakeups and device energy under a named journey |
| Projection rebuild, consumer outage and retention expiry | Compatible snapshot/cursor handoff; zero replayed external effects; deletion fences honored | Replay throughput, lag, catch-up time, retained bytes and rebuild cost |
| Replica/broker restart, provider-history expiry and archive interruption | Scoped identity/fences, matching handoff receipts, manifest/snapshot correctness | Backlog clearance, retry amplification, recovery latency and resource cost |
Pin source/build revisions, provider/SDK configuration, worker count, payload/node sizes, concurrency, storage/region, retry budget and injected-fault positions. Record warm/cold runs separately, offered load and saturation, sample count/duration, failures and raw artifacts; do not discard timeouts to improve percentiles. Report the counterfactual baseline and budgets alongside results. Provider limits and retention are part of the profile; verify their current documentation when running the suite.
Admission latency starts before submission and ends at confirmed durable admission. Completion latency includes delivery and reconciliation; execution latency measures the handler interval separately. Report live logical nodes, physical attempts and destination effects as different counts. Workflows/providers with different recovery guarantees cannot be ranked by one throughput number. No numerical performance result or superiority claim is published by this design review.
Related contracts
- Delivery and removal roadmap — application migration and gates; sign-in required.
- Data, implementation evidence — authoritative state and atomic storage.
- Service, Bus, Cloudflare execution — effect and delivery boundaries.
- Lifecycle, capabilities — headless scope and placement.
- Module priorities — dependencies across modules.