Repository navigation
Releases
1.0.0-rc.11
The eleventh release candidate for 1.0.0. It migrates a database instead of re-cutting it, answers every child wait with one outcome type, reads a job's input and variables from outside the job, shows each definition's performance in the dashboard, and runs on .NET 11.
Upgrading from rc.10: apply the migration to every database an rc.10 build provisioned, before an rc.11 worker starts: <app> jobs migrate, {Provider}Migrations.ApplyAsync or the provider's schema script applies M20261112231452_index_lanes_by_namespace. It adds one index and changes no row, and an rc.10 worker runs on against the migrated database, so the deploy can roll. A database from rc.9 or earlier is dropped and provisioned again. The release notes list each change a consumer must make, with the old and the new spelling.
Highlights
- An rc.10 database is migrated where it stands, the first time a release candidate ships a migration.
- Every child ends in a
JobOutcome, with the child'sJobRef,Succeeded,TimedOutandThrowIfFailed(): whatExecuteChildAsyncanswers, and each member ofJoinAsync,ParallelAsyncandMapAsync.JoinAsyncwaits for the children you started, one or many. IJobs.GetInputAsync<T>(job)andIJobs.GetVariableOrDefaultAsync<T>(job, name)read a job's input and its variables as their types, for a screen of your own.- A definition's page in the dashboard shows how its executions perform: how many succeeded and failed, the failure rate, and the p50, p95 and p99 of their durations over the last hour, day, week or month, with a mark where a deployment changed the version.
- .NET 11 is a supported runtime for the
net10.0packages. RaiseSignalAsync(job, name, value, ct)takes the token in fourth place, and the dashboard's screens pass an accessibility scan in three themes.
Evidence: the Acta Verify release suite passed on PostgreSQL, SQL Server, and SQLite in one run in which no cell was rerun to pass: every correctness, fault, and chaos scenario, every trial's ledger checks, and every performance floor. Chaos ran 1,000,000 jobs on PostgreSQL and on SQL Server with a worker killed every 5 s. Four PostgreSQL workers held 15,000/s offered in three 30 s passes and completed 12,512 fully executed, durably completed jobs per second in the 120 s confirmation at 12,500/s, with p99 1.0 s; rerun the same morning, rc.10's tree held the 15,000 confirmation in one run of two on the same machine. SQL Server held 5,000 a second. The run's commit is 1bb9ec4e0.
Release notes: https://github.com/acta-dotnet/acta/blob/v1.0.0-rc.11/docs/release-notes.md
1.0.0-rc.10
The tenth release candidate for 1.0.0. It widens the job counters to 64 bits, removes the columns and codes that carried no information, makes a schedule any distance behind decidable, records operator actions at every level, and gives typed result reads a form that returns the result and a form that says whether one exists.
Upgrading from rc.9: drop and reprovision every database an rc.9 build provisioned: the baseline is re-cut, and nothing translates it. The release notes list each change a consumer must make, with the old and the new spelling.
Highlights
- An execution number and a version are 64-bit, in the tables, the API and the HTTP contract, so a long-lived permanent job no longer has a counter to wear out.
- A schedule that fell years behind is decided by a bounded search, and a schedule a build cannot read is left alone instead of stopping its namespace's admission.
- A suspended job wakes only for the signal or child it waits on, and a child that lands after its parent finished still records its outcome there.
- Pause, resume, restart, reschedule, a priority change, an input update and a caller's cancel are recorded at every recording level, and who did it is in
events.actor. - Retention walks one namespace's jobs at a time and deletes in its first pass; a job with an undelivered alert is kept until the alert settles.
GetResultAsync<T>returns the stored result and throws when there is none;TryGetResultAsync<T>answers(Found, Value). A handler starts a child by its generated call, andGetHandleAsync<T>rebuilds a typed handle from a ref.- A calendar definition has a published JSON Schema and a stated promise for 1.x.
- One alert channel that does not answer no longer holds up the others.
Evidence: the Acta Verify release suite passed on PostgreSQL, SQL Server, and SQLite in one run with no rerun: every correctness, fault, and chaos scenario, every trial's ledger checks, and every performance floor. Chaos ran 1,000,000 jobs on PostgreSQL and on SQL Server with a worker killed every 5 s. Four PostgreSQL workers completed 14,857 fully executed, durably completed jobs per second, held through three 30 s passes and a 120 s confirmation at 15,000/s offered with p99 1.6 s; SQL Server held 5,000 a second. The run's commit was d20e7c77e; its commit messages were reworded afterwards with no change to any file, and the commits after it change documentation, the site, two queries of one lab, test code (the connection timeout of the conformance suites' hosts, one skipped case, and two waits that no longer depend on the runner's speed), and the CI workflow. The report is docs/reference/benchmark.md.
Known limitation: on zone data that gives a zone negative daylight time, which is Europe/Dublin on Ubuntu 26.04, a cron in that zone stops at the spring clock change and skips the repeated hour in autumn, because .NET 10 misreports the zone's skipped and repeated hours (dotnet/runtime#120915). Declare such a schedule in Europe/London, which keeps the same clock.
Release notes: https://github.com/acta-dotnet/acta/blob/v1.0.0-rc.10/docs/release-notes.md
1.0.0-rc.9
The ninth release candidate for 1.0.0. It makes deploys explicit, moves the dashboard into its own package, gives operations and the HTTP contract one naming convention, and runs on SQL Server with READ_COMMITTED_SNAPSHOT off as well as on.
Upgrading from rc.8: drop and reprovision every database an rc.8 build provisioned: the baseline is re-cut, and nothing translates it. A worker start no longer writes definitions or schedules: run <app> jobs migrate (schema, then jobs) or <app> jobs deploy (jobs alone) once per release, before the new workers start; in development, MigrateOnStartup = true makes startup do both. The dashboard is the package Acta.Dashboard, so an app that calls MapActa adds it and using Acta.Dashboard;. Operations, responses, routes, and CLI JSON follow one naming convention, so regenerate an OpenAPI client. The release notes list every change a consumer makes.
Highlights
<app> jobs deploywrites a release's definitions and schedules in one transaction and records its version;<app> jobs migrateapplies the migrations from a deploy step, and each provider'sMigrations.ApplyAsyncdoes it from code.- A schedule can be finite, bounded to the occurrences between a start and an end, and a per-occurrence definition may declare a deadline.
ActaEndpointOptions.RequirePermissionsauthorizes every request against the host's policy for the operation's permission,GET /capabilitiesanswers the caller's permissions, and the dashboard shows only the controls the caller holds and stops on an ended session.- The OpenAPI document describes every property, schema, path parameter, and response, with one example request and answer per JSON body taken from the contract tests' host.
- A handler DI cannot build fails on its first attempt with
HandlerActivationExceptioninstead of retrying for days, a cancelled job's explanation gives the cancel's reason, and a job that failed for good resolves its retrying alerts. - SQL Server runs and is tested with READ_COMMITTED_SNAPSHOT on and off, and Acta switches it on only in a database its development flag has just created.
Evidence: the engine is certified on 096ea16e5; the commits after it change the site and how Acta Verify frames the site's benchmark page, so the certified commit is 7c4dae04c. Under the Acta Verify release suite on PostgreSQL, SQL Server, and SQLite, every correctness, fault, and chaos scenario passed and every trial's ledger passed the certification checks. Every performance floor held but one: sixteen SQL Server workers at 4,000/s missed in the run (p99 2.2 s against 2.0 s) and in the first of four reruns, then held in the three after it, each completing about 4,000 jobs a second; the known limitations name the short enqueue stalls behind it. The chaos certification ran 1,000,000 jobs on PostgreSQL and on SQL Server with a worker killed every 5 s, and every busy worker's work was reclaimed. Four PostgreSQL workers completed 12,527 fully executed, durably completed jobs per second with p99 1.0 s, one worker woken in process 7,500 with p99 49 ms, and eight workers drained a backlog of a million jobs at 73,864 a second. Report: docs/reference/benchmark.md and useacta.net/benchmark.
Release notes: https://github.com/acta-dotnet/acta/blob/v1.0.0-rc.9/docs/release-notes.md
1.0.0-rc.8
The eighth release candidate for 1.0.0. It fixes what the 1.0 readiness reviews found, queues each process's SQLite writes in order, stops Redis wakes reaching every process, and measures Acta Verify's trials as applications run them.
Upgrading from rc.7: drop and reprovision every database an rc.7 build provisioned: the baseline is re-cut, and nothing translates it. On PostgreSQL and SQLite, create a producer's outbox table again from its CreateScript(). A retired definition that a newer build registers again now resumes its schedules from now. The release notes list every change a consumer makes.
Highlights
- Schedules: an exhausted cursor is never written back, an admission checks every schedule it read against its declaration version, a namespace suspension fences admissions already planned and Run now, and a retire leaves a recurring job's slot inert until the definition comes back.
- The outbox staging table checks ids, priorities, delays, failure counts, and run instants, so one bad row can no longer stop a relay's claim batch.
- SQLite: writes to one file queue in the process and run in arrival order, so a flood of enqueues no longer starves the worker.
- Redis: a process publishes a namespace's wake at most once per 10 ms, and completion wakes reach only the processes waiting for that job, so sixteen workers woken through Redis no longer run slower than the same fleet polling.
- A metrics listener that throws no longer stops a worker,
explainreads one snapshot, and the rate-limit contract states what the meter enforces. - Acta Verify measures one-worker trials in the enqueuing process, names how each claim's workers learn of new work, adds Redis twins, and lists floors that held at four times under rates to raise.
Evidence: the engine is certified on 5043b81fa; the commits after it change only the docs, the site, the README, and three conformance specs' timing on a loaded CI runner. Under the Acta Verify release suite on PostgreSQL, SQL Server, and SQLite, every correctness, fault, and chaos scenario passed, every trial's ledger passed the certification checks, and every performance floor held. Two earlier release runs (a2b1f66a5, 63bd6946b) did not pass; the Redis fix and two Acta Verify fixes (d80d1c3a2, 04a2100e9) followed, and the whole suite ran again. The chaos certification ran 1,000,000 jobs on PostgreSQL and on SQL Server with 24 workers of 64 executors and a worker killed every 5 s, and every busy worker's work was reclaimed. Four PostgreSQL workers completed 12,438 fully executed, durably completed jobs per second with p99 1.0 s, one worker woken in process 7,500 with p99 72 ms, sixteen workers woken through Redis 12,800 with p99 787 ms, and eight workers drained a backlog of a million jobs at 73,211 a second. Report: docs/benchmark.md and useacta.net/benchmark.
Release notes: https://github.com/acta-dotnet/acta/blob/v1.0.0-rc.8/docs/release-notes.md
1.0.0-rc.7
The seventh release candidate for 1.0.0. It rebuilds scheduling around an admission engine, adds calendars and per-occurrence delivery, fixes what an external review of rc.6 found, renames Acta's log fields, and drops dependencies.
Upgrading from rc.6: drop and reprovision every database an rc.6 build provisioned: the baseline is re-cut, and nothing translates it. [JobSchedule] is [Schedule], LockScope and schedule overrides are gone, JobOutcome.TerminalStatus is Status, and every log field Acta writes carries the Acta prefix, so saved log queries must follow. The release notes list every change a consumer makes.
Highlights
- Scheduling is admission-driven: one admitter per worker namespace evaluates each schedule when it is due, admits one firing per slot, and moves the cursor at admission;
CatchUpLatest,CatchUpAll, and expiring occurrences join the misfire strategies. - Calendars, in code (
[Calendar]) or as a versioned catalog per namespace and shared, drive occurrences or limit a schedule to open hours. [Job(ScheduledDelivery = ScheduledDeliveryCode.PerOccurrence)]delivers each occurrence as a fresh root job, bounded byMaxOutstanding.- Fixes from the external review: a timed-out child's cancel is fenced to the attempt that holds its parent, a typed wait refuses another definition's result, an outbox command never replaces a planned one, and a wake never breaks its caller.
- Acta Verify 2: written scenario files, rate ladders, a report that answers first, and a published benchmark page.
Evidence: the engine is certified on e294a8b91; the commits after it change only Acta Verify and the docs. Under the Acta Verify release suite on PostgreSQL, SQL Server, and SQLite, no scenario failed safety or liveness, and every trial's ledger passed the certification checks; the four scenarios the release run could not judge, for reasons in Acta Verify, passed on a rerun against the same engine (54ddd670e). The chaos certification ran 1,000,000 jobs on PostgreSQL and on SQL Server with 24 workers of 64 executors and a worker killed every 5 s, and every busy worker's work was reclaimed. Four PostgreSQL workers completed 12,430 fully executed, durably completed jobs per second with p99 1.0 s, one worker 10,017 (rc.6: 7,680), and eight workers drained a backlog of a million jobs at 70,085 a second. Report: docs/benchmark.md and useacta.net/benchmark.
Release notes: https://github.com/acta-dotnet/acta/blob/v1.0.0-rc.7/docs/release-notes.md
1.0.0-rc.6
The sixth release candidate for 1.0.0. It renames the data model into one vocabulary, makes enqueue answer a handle you can wait on, narrows payloads to JSON or bytes, and fences every handler write to the attempt that holds its job.
Upgrading from rc.5: drop and reprovision every database an rc.5 build provisioned: the baseline is re-cut, and nothing translates it. Tables, columns, views, wire fields, and several .NET members are renamed; a manifest's job members are factories (jobs.EnqueueAsync(ShippingJobs.ShipOrder(order))); the text payload format is gone. The release notes list every change a consumer makes.
Highlights
- Typed enqueue answers
JobHandle, withWaitAsync,GetResultAsync,CancelAsync, andExplainAsync;ScheduleAsyncenqueues one job for later. - A handler may take several input parameters; they travel as one generated record.
- A handler write from an attempt that no longer holds its job changes nothing: checkpoints, waits, timers, steps, notes, and child starts check the executing attempt under a row lock.
- Fixes from the external review: the outbox relay's stale passes and crash replays, two SQL Server deadlocks (rate meters, completion batches), and a SQLite step that could run past its retry budget.
- A job stores one result, and events are a compact ledger clustered by worker.
Evidence: the engine is certified on 599e28e8; the commits after it change only the benchmark tool and the docs. Under the Acta Bench full profile on SQLite, PostgreSQL, and SQL Server, no case failed safety or liveness, and every trial's ledger passed the certification checks. The chaos certification ran 1,000,000 jobs on PostgreSQL and on SQL Server with 24 workers of 64 executors and a worker killed every 5 s. One PostgreSQL worker validated at 7,680 fully executed, durably completed jobs per second; a few capacity rows stay INCONCLUSIVE. Report: docs/benchmark.md.
Release notes: https://github.com/acta-dotnet/acta/blob/v1.0.0-rc.6/docs/release-notes.md
1.0.0-rc.5
The last release candidate before 1.0.0. It rebuilds the execution engine around one path, cuts the API and the schema down to what 1.0 will freeze, and re-cuts the schema baseline.
Upgrading from rc.4: drop and reprovision every database, including one an earlier rc.5 build provisioned: the migrations table changed shape and nothing translates it. Acta.Relational and Acta.Runtime are gone (their code ships in Acta), each package has one namespace, and several types and views are renamed. The release notes list every change a consumer makes.
Highlights
- One execution path: a claim moves rows straight to Executing, one finalizer lands up to 128 completions in one call, and crash recovery runs on the workers' heartbeat. Execution profiles are gone.
- Drain against rc.4's best profile on the same machine: 66.4K jobs/s on PostgreSQL (was 29.0K), 25.3K on SQL Server (12.3K), 5.6K on SQLite (1.0K).
- Fixes found by the release reviews: a scope that throws while disposing no longer strands its job, control verbs inside a step decide the job, a non-retryable failure rolls a recurring job over instead of ending its schedule, and an uncaught exhausted step fails the job at once.
- A job's rows carry no foreign key to the job; purge and retention delete them with it.
Known gap: on Windows, SQLite picks up one job at a time in about 20 ms where rc.4 took 2: its busy wait sleeps a whole timer tick. The fix lands in 1.0.0.
Evidence: certified on ba12ef95, which the tagged commit follows with test fixes and docs only: the three standard gates, the PostgreSQL ensemble, and both million-job runs (1,005,000 jobs, 24 workers of 64 executors) on PostgreSQL and SQL Server passed, with worker kills in flight in every work shape. The benchmark round on the same commit is docs/reference/benchmark.md.
Release notes: https://github.com/acta-dotnet/acta/blob/v1.0.0-rc.5/docs/release-notes.md
1.0.0-rc.4
A release candidate on the 1.0 baseline. rc.5 comes next, a reorganisation of the source so it can be maintained by hand again, and 1.0.0 after it. The data model is the rc.3 model with four counters widened to 32-bit integers and one new feature, lanes. What changed since rc.3 answers the external reviews of it: the execution and alerting paths, the installed routines, and what a release has to prove.
Upgrade: reprovision every release-candidate database, on every provider. The baseline is cut once more: runtimes.failure_count, steps.attempt_number, definitions.max_attempts (with its override and effective columns), and alerts.retry_count widen to 32-bit integers, and startup refuses a database an earlier release candidate provisioned, naming the mismatch. Reprovisioning drops Acta's schema and installs it from docs/reference/schema-<provider>.sql, so drain or export what you need first. Recreate an outbox table created before this release from the DDL API. A new job status, Blocked (15), marks a laned job waiting behind its lane's head. IDefinitions.UpdateOverridesAsync and RetireAsync take the reason before the actor, control bodies refuse members the endpoint does not take, and the local-only guard also requires the host to be named localhost or an IP address. The release notes list every change a consumer must make.
Highlights
- Lanes.
.Lane("customer-42")on an enqueue, or[Job("...", Lane = "...")]on a definition, runs a lane's jobs one at a time in enqueue order, across the whole fleet. Only the head is claimable; the rest waitBlockedand are promoted as the head settles, so a deep lane costs no claim work. The outbox keeps a lane's staging order. - The claim seeks each priority band. On SQL Server the stuck-job reclaim locks only its own rows and a lane's members are found by seek instead of walking the job table, and alerts take their job's lock first everywhere.
- Completion and start writes repeat until they land, and a lost answer is reconciled against the row instead of re-run. A claim whose answer was lost goes back to Ready through the heartbeat, a Bulk completion stays owned until it settles, and recovery runs on capacity the executors cannot exhaust.
- Workers' lifecycle states hold through outages and drains: a worker killed mid-drain is marked Dead, and a worker marked Dead through a database outage is Active again when it heartbeats.
- Installed objects carry a version that startup checks; PostgreSQL routines and views are replaced in place, and an older release never overwrites a database a newer one upgraded.
- Alerting: an incident at
AuditLevel.Failurescloses on its own. - Retention keeps a completed child while its parent is live.
- Scheduling: an operator's pause holds until an operator resumes it, and a timed pause ends by the schedule's misfire policy.
- Dashboard and HTTP API: per-route authorizer verbs, exact control bodies, the outbox family authorized like the others, and schedule overrides and alert notes saved again.
Evidence
- Six chaos-certification seals on the certified commit
d616c72b, all PASS with real chaos, underdocs/certification/: PostgreSQL and SQL Server at 10,000 jobs and 64 slots, SQLite reduced at 48 slots, the three-participant ensemble, and a million jobs each on PostgreSQL and SQL Server through 1,536 concurrent slots with a worker killed every five seconds. Lanes held their order and drained on every provider while their heads' workers were killed, every rate meter stayed inside its budget, and no step was recorded twice. AtMostOnce charges a kill interrupted inside their guarded step ended Failed, as the contract requires. - The benchmark round in
docs/benchmarks/rc4-release-round-20261002.md: level with rc.3 on drain, enqueue, and latency at thereleasepreset, except SQL Server's one-worker drain and Direct drain at sixteen workers and the job list query; SQLite pays about an eighth for lanes. At full scale, PostgreSQL's Bulk drain at sixteen workers reads about 13 percent below rc.3, cause not yet found.
Install with --prerelease: dotnet add package Acta.Sqlite --prerelease.
Full notes: docs/release-notes.md.
1.0.0-rc.3
The last re-cut of the baseline before 1.0.0. Two features the data model was missing land on the existing lock store, the persisted model gains the row-shape constraints it lacked, the claim seeks on PostgreSQL instead of sorting, five defects on the recovery and completion paths are fixed, and rolling deploys become a documented shape. An alerting redesign is deferred, with its design written down.
Upgrade: drop and reprovision the Acta database, on every provider. M001 is re-cut: definitions gains the concurrency and rate policy columns, jobs.exclusive_key is renamed to concurrency_key, five CHECK constraints are added and one tightened, and two SQL Server indexes gain a physical option. The baseline stamp is now a content hash of each provider's emitted M001; a database from any earlier build refuses to start with a message naming both stamps. There is no upgrade path between baseline generations before 1.0.0.
Highlights
- Concurrency limits.
[Job(ConcurrencyLimit = N)]bounds how many jobs of a definition run at once, admitted through slot rows in the lock store; the exclusive key becomes the concurrency key, one name everywhere. - Rate limits.
[Job(RateLimit = "600/m")]meters a definition through reservations: an idle meter admits one second's worth of the rate at once and then one per interval, every early job books a turn it returns to, a booked turn stays valid for a second, and an executor sleeps out a turn under a quarter second in process. The contract is the upper envelope,R*(T+W)+Badmissions in any window of T seconds. - Rolling deploys as three rules and no schema change. Registration never retires a definition the manifest omits, so the old fleet finishes its work and a rollback finds nothing missing. A worker that claims a job it has no handler for hands it back budget-neutral and excludes that definition from its own claims for the rest of its process. Retiring a definition and cancelling its queue is an operator verb:
IActaOperations.Definitions.RetireAsync,POST /definitions/{ns}/{name}/retire, and a confirmed button on the dashboard. - The claim seeks on PostgreSQL. A Ready row always carries its due instant, so the claim reads
ix_runtimes_claim_readyin index order instead of sorting; the full matrix reads 24% to 45% more Bulk throughput than rc.2 on PostgreSQL. - Durable state is bound to CHECK constraints on every provider, and two step routines they exposed are fixed.
- Five recovery and completion defects. A claim the worker has no handler for is released instead of held under a renewed lease; the completion write and the start write retry on a provider error; a committed-then-lost start is reconciled through the completion; the alerts projector cursors by
(created_at_utc, id)so an inverted event is never skipped; recovery runs through one pass, and every worker checks the recovery slot every seven minutes. - SQL Server: page-latch waits attributed per index, and the two insert convoys opted into sequential keys.
- The ensemble certification workload carries a metered shape, and every seal reports the rate contract beside the chaos figures.
Evidence
- Four chaos-certification gates on the certified commit, all PASS with real chaos, sealed under
docs/certification/: PostgreSQL and SQL Server at 10,000 jobs and 64 slots (576 and 574 orphaned attempts, 72 dead workers each), SQLite reduced at 48 slots (576 and 72), and the three-participant, two-namespace ensemble with 772 orphaned attempts across 162 killed workers. On every gate the rate meter admitted its 600/m shape at the declared rate, never past 21 in a second against a budget of 30. - A full-matrix benchmark round on all three providers against a same-hour rc.2 control from clean worktrees, recorded in
docs/benchmarks/rc3-full-matrix-20260921.md: no Direct, Bulk, drain, enqueue, or query cell regresses beyond the machine's own movement between two runs of the same tree; PostgreSQL and SQLite read ahead on most of them.
Full notes: docs/release-notes.md.
1.0.0-rc.2
A correctness round over the paths a release candidate has to get right before anyone leans on them: crash recovery, the audit trail, and the bounds on what an operator or an attribute can declare. Nothing here adds a feature to the execution model; most of it makes a guarantee the docs already claimed actually hold on every provider.
Upgrade: drop and reprovision the Acta database, on every provider. The M001 baseline was re-cut again and the stamp now names the day it was cut, baseline-20260910; the bootstrap refuses any history without this build's stamp row. There is no upgrade path between generations before 1.0. The re-cut carries a Unicode events.actor_key, three new check constraints, a re-keyed in-flight index, and expected_version on SQL Server's job_schedule_advance_batch table type.
Highlights
- A crash can no longer take a namespace's recovery down with it. The reclaim sweep ran only from the
sys.recoveryslot, and a worker could die holding it. Every worker now checks that one slot at startup and once an hour, with a single guarded statement that re-arms it only when its lease has lapsed; two workers checking at once commit one repair. The round that found this had 571 jobs queued behind a slot whose lease had expired 36 minutes earlier. - A recurring completion honours what happened to its schedules while it ran. A schedule the deployment removed stays orphaned, a schedule edited during the attempt keeps its edit, and the slot re-arms from the schedules as they stand. Each planned advance carries the schedule version it was read at.
- Restarting an unchanged build writes nothing to its schedules. Registration updates a slot or a schedule only when the declaration changed, so a fleet restart or a scale-out no longer bumps every version in the namespace.
- A host starting no longer cancels a slot another host is running. Re-registration skips a slot held under a live lease.
- SQL Server: no more table-lock escalation on
runtimes, and the heartbeat no longer deadlocks againststart_execution.FORCESEEKon four updates, and a heartbeat that locks in clustered order. The rc.1-era throughput sweep did not rise with executors because some cells compiled the escalating plan; every profile now rises monotonically, with 17 of 18 cells above that baseline. - The audit trail keeps an operator's name as typed.
actor_keyis Unicode on every provider; a job note files under the attempt that wrote it. - The job control verbs take an optional
expectedVersion. Cancel, pause, resume, restart, reschedule and reprioritize can be guarded against a row that moved; a conflict answersVersionConflictwith the current version and writes nothing. - Waits and clocks are anchored where they are read, and fractional retention and dead-worker windows round up rather than down.
Evidence
- Four chaos-certification gates on the release tree, all PASS, sealed under
docs/certification/: PostgreSQL and SQL Server at 10,000 jobs and 64 slots, SQLite reduced at 48 slots, and the three-participant, two-namespace ensemble with 830 orphaned attempts across 152 killed workers. - One idle benchmark round per provider against the rc.1-era matrix, recorded in
docs/benchmarks/rc2-benchmarks-20260910.md, with what a single round does and does not establish stated on the page. - Coverage baseline
coverage-baseline-rc2.md: 88.4% line, 70.7% branch, and the blind spot the round's own defect landed in still open.
Full notes: docs/release-notes.md.