Changing the engine
Engine changes should enter through an existing abstraction whenever it matches the behavior: APL parser, dialect parser, canonical model, core command, repository or stable DTO. Avoid repository-wide refactoring for a local semantic change.
Mutation implementation pattern
Section titled “Mutation implementation pattern”flowchart LR
Controller[Controller or scheduler]
Command[Atomic command service]
Repo[Locking repositories]
Model[Canonical runtime model]
Persist[State, work, facts, history and outbox]
Controller --> Command
Command --> Repo
Repo --> Model
Model --> Persist
- Keep controllers responsible for HTTP translation, typed DTOs and response status—not repository state transitions.
- Mark the core mutation boundary with
@AtomicRuntimeCommandand load every mutable input inside it. - Lock the natural owner row before validating status or ownership.
- Advance only the canonical process model; never interpret vendor XML or untrusted model output during execution.
- Persist successor tokens/work, variables, terminal facts, history and outbox events before the transaction commits.
- Return a deterministic response suitable for idempotent replay.
Extending canonical behavior (APL and BPMN)
Section titled “Extending canonical behavior (APL and BPMN)”APL nodes and BPMN elements are two authoring surfaces over one canonical model. A new executable construct requires all of the following:
- an APL node shape in the spec and node reference, plus the BPMN dialect mapping (or a documented decision that the construct stays APL-only);
- a vendor-neutral canonical representation with unambiguous runtime semantics and persistence;
- deployment validation with stable machine-readable error codes for both schemas;
- successful, invalid-input, rollback and restart tests, with an APL fixture (and a BPMN fixture when the element exists there);
- Studio compiler/transpiler and round-trip coverage when the construct is authorable in the canvas;
- updates to the APL specification, BPMN support and runtime-semantics contracts in the same change.
When the engine’s kitchen-sink process is affected, keep the APL twin 1:1
with the BPMN original and run AplKitchenSinkTest plus the Studio
verify:kitchen-sink round-trip check.
Agent work stays on the worker boundary
Section titled “Agent work stays on the worker boundary”agentnodes compile to external tasks on the fixedabada:agenttopic. The engine never calls a model inside a command; changes that would add a synchronous model call to an@AtomicRuntimeCommandservice are rejected by design.- Attempt metadata flows in through the completion/failure commands and is persisted on the external-task row and history. Keep prompts, tokens, credentials and sensitive payloads out of both.
- Retry budgets, idempotency keys (task + attempt + operation) and lease
recovery are contract behavior — see the agent worker reference and
AgentWorkerResilienceTest.
Insight changes are contract changes
Section titled “Insight changes are contract changes”Facts are written in the command transaction; the analyzer runs out of band
under a durable lease and never holds workflow locks while calling a model.
Generated proposals are untrusted until AplParser validates them and policy
review approves them. Extending the loop means extending the durable data
model, thresholds and policies with PostgreSQL evidence — never an external
analytical dependency and never auto-apply.
Embedded execution
Section titled “Embedded execution”Scripts and embedded delegates execute synchronously inside the workflow transaction. They are suitable for deterministic local logic. Use an external task for remote calls, long-running work, LLM calls or effects that need independent retry and heartbeat behavior.
Definition caches
Section titled “Definition caches”Cache only immutable parsed definitions by deployment ID. Do not add a mutable “latest definition” alias or cache instances/tasks to reduce reads. Optimize queries with bounded projections, indexes and batch loading without changing the database-authority rule.