A pure reducer advances closed Template syntax; a canonical application service handles commands, policy and persistence; a separate worker drives pending automatic work.
platform/runtime/src/application-service.ts pins a registered immutable execution definition
when starting a process. Domain field expansion and source compilation happened before
registration, not inside the runtime. Startup defaults are compiled expressions, evaluated with
explicit startup context. Sharing starts private unless the authorized application changes it.
The current compatibility policy checks the API's process-write permission; source
template.permissions, runInputs and startExpression are not newly activated start gates.
Do not treat a source-only field as an authorization guarantee.
Step updates address an occurrence id, not just an activity key. The service checks process, activity and field access, filters permitted updates, writes current memory and appends sparse field audit. Completion validates required fields and the compiled completion predicate. Past edits in loose mode do not replay completed effects. Reopen preserves history and creates a new visit.
platform/runtime/src/machine.ts reduces sequential composition, choice, iteration, failure
and recovery. It knows no Dune, Safe or application step tags. Integration/app authoring builds
those operations from generic syntax. A process suspends at an effect; the host executes only
its fixed generic schema under configured authority.
Waits record their chosen deadline. Host-dependent timestamp parsing is a journaled parse-time
effect; pure UTC calculations take explicit time input. A resumed recorded wait does not
recalculate its business schedule.
Known failures may enter the definition's recovery/backoff branch. An uncertain external outcome instead creates a reconciliation hold. Do not equate a transport exception with proof that the remote action did not occur. Automatic activities cannot be manually completed to skip their work.
applications/main/src/jobs/step-execution-job.ts exposes the scheduler assembled by application composition.
platform/runtime/src/application-scheduler.ts polls, skips terminal/held/human-waiting work,
bounds advances, and isolates each process's errors. Its in-process busy guard prevents overlapping
ticks; durable claims and revision checks protect effect occurrences across contenders.
The scheduler still scans stored aggregates rather than using an indexed work queue. Keep the supported deployment topology conservative—normally one worker per shared store—until the actual storage/lease and crash-recovery policy is verified. See storage and deployment bindings.
The machine distinguishes success, failure and pending execution. The public compatibility DTO
still uses running/completed plus error; records derive failure from the error. A hold is surfaced
as attention required, not a successful completion. Stored machine state and public presentation
are deliberately different contracts.
| Stage | Driver |
|---|---|
| Start | POST /api/process through the application service |
| Edit | PUT /api/process/{id}/steps/{stepId} |
| Complete an interaction | POST /api/process/{id}/steps/{stepId}/complete |
| Automatic effects and waits | Explicit worker entrypoint |
| Abandon/reopen/sharing | Authorized application-service commands |
Use npm run dev:all when local runs need both the web app and worker. The standalone API does
not silently launch a polling worker.
Transparent reconciliation, bounded product retry policies, retention/compaction and parallel join semantics remain follow-up work. Synthetic persistence and concurrency tests do not establish production hosting or live-provider guarantees.