Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
6fe1611
docs: start the unified start API design (0.9)
unbalancedparentheses Nov 11, 2026
0f7e391
verification: Start.tla model of the unified start API
unbalancedparentheses Nov 11, 2026
cf66b03
verification: Start.tla models fallible init, continuations and spawn
unbalancedparentheses Nov 11, 2026
13dad2a
verification: split the continuation check into MCStartContinue
unbalancedparentheses Nov 11, 2026
72aa302
verification: Start negative controls in negative_checks.py
unbalancedparentheses Nov 11, 2026
296c347
verification: Start.tla models abandoned start calls
unbalancedparentheses Nov 11, 2026
ce136f5
verification: MCStart checks default placements only (explicit ones a…
unbalancedparentheses Nov 11, 2026
92ffa04
docs: unified start design, client mapping, model README and roadmap …
unbalancedparentheses Nov 11, 2026
49b565b
verification: MCStartDeep without messages (MCStartContinue covers them)
unbalancedparentheses Nov 11, 2026
b915c37
docs: MCStartDeep result
unbalancedparentheses Nov 11, 2026
8c88e1c
verification: Start.tla revision 2 (startup cell, atomic commit, D/pu…
unbalancedparentheses Nov 11, 2026
383ceb1
verification: smaller per-PR MCStart
unbalancedparentheses Nov 11, 2026
ed08307
verification: MCStartTimeout for the init-timer races
unbalancedparentheses Nov 11, 2026
1066ea1
docs: unified start revision 2 (review resolutions); MCStartScope wit…
unbalancedparentheses Nov 11, 2026
96ddf44
verification: revision-2 Start controls
unbalancedparentheses Nov 11, 2026
302153f
Merge origin/main; model-map entry for Start (TLC-only until implemen…
unbalancedparentheses Nov 11, 2026
32d5a99
verification: MCStartCap (capacity binds; release at publication; retry)
unbalancedparentheses Nov 11, 2026
5173fe5
docs: client mapping corrections (continuation guarantee, spawn failure)
unbalancedparentheses Nov 11, 2026
4e49d76
verification: MCStartCap with spawned children; README Start section …
unbalancedparentheses Nov 11, 2026
f3d9e59
verification: MCStartDeep is MCStart plus the timer and an unmanaged …
unbalancedparentheses Nov 11, 2026
630877e
docs: revision-2 model results, controls; ROADMAP rank 5h
unbalancedparentheses Nov 11, 2026
9938860
docs: MCStartDeep result (revision 2)
unbalancedparentheses Nov 11, 2026
1051e69
verification: Start.tla revision 3 (parent publication, pre-D reason,…
unbalancedparentheses Nov 11, 2026
0623c30
verification: MCStartCap with a parent that stays
unbalancedparentheses Nov 11, 2026
ef4457e
verification: NormalFailureSparesParent keys on the final reason
unbalancedparentheses Nov 11, 2026
5fd2d05
verification: MCStart without group closure (covered in Cap and Timeout)
unbalancedparentheses Nov 11, 2026
8fc94f7
verification: revision-3 Start controls
unbalancedparentheses Nov 11, 2026
1c91de3
verification: MCStart (one child) and MCStartNames per PR; the 30M in…
unbalancedparentheses Nov 11, 2026
6615aca
docs: revision 3 design sections, model section and TLA README
unbalancedparentheses Nov 11, 2026
6f6f868
verification: MCStartNames with group closure (makes SplitCommit non-…
unbalancedparentheses Nov 11, 2026
e086ae5
verification: CommitRest reuses the refusal rules; MCStartNames place…
unbalancedparentheses Nov 11, 2026
4322fae
docs: revision 3 controls table, planted bugs, CHANGELOG, ROADMAP
unbalancedparentheses Nov 11, 2026
b3976f1
docs: revision 3 TLC results (all with TLC's verdict)
unbalancedparentheses Nov 11, 2026
4825b38
fix(design): one rule for a pre-D kill vs the startup decision (round…
unbalancedparentheses Nov 11, 2026
16f2905
wip: release split and delivery step (model)
unbalancedparentheses Nov 11, 2026
226176f
fix(design): name and slot release are separate atomic points; delive…
unbalancedparentheses Nov 11, 2026
44f8a78
fix(design): generation completion waits for owned work, not publicat…
unbalancedparentheses Nov 11, 2026
999cc22
wip: owner gate history (model)
unbalancedparentheses Nov 11, 2026
0282763
fix(design): the parent's own exit refuses new starts but does not cl…
unbalancedparentheses Nov 11, 2026
85aca4b
docs(design): migration row for the stopped() change on a failed init…
unbalancedparentheses Nov 11, 2026
3315192
docs: round-three resolutions, control tables and counts
unbalancedparentheses Nov 11, 2026
c758db1
verification: AbandonedNoticeDelivered keys on a live parent (the dro…
unbalancedparentheses Nov 11, 2026
d1d086b
docs: round-three TLC results (every config with TLC's verdict)
unbalancedparentheses Nov 11, 2026
0b468ec
Merge remote-tracking branch 'origin/main' into design/unified-start
unbalancedparentheses Nov 12, 2026
c6eb5e8
Merge remote-tracking branch 'origin/main' into design/unified-start
unbalancedparentheses Nov 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/verification.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ jobs:
select: --only 'MCLifecycle*'
- leg: deferred
select: --only 'MCDeferred*'
- leg: start
select: --only 'MCStart*'
- leg: other
select: --exclude 'MCSupervision,MCLifecycle*,MCDeferred*'
select: --exclude 'MCSupervision,MCLifecycle*,MCDeferred*,MCStart*'
steps:
- uses: actions/checkout@v4
- uses: DeterminateSystems/nix-installer-action@v16
Expand Down Expand Up @@ -112,6 +114,7 @@ jobs:
- MCLifecycleWideDeep
- MCLifecycleLiveDeep
- MCLifecycleDeep
- MCStartDeep
steps:
- uses: actions/checkout@v4
- uses: DeterminateSystems/nix-installer-action@v16
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

## Unreleased

- Design (0.9, approved for implementation after round 3): a unified start API
(`docs/design/unified-start.md`, rank 5h). OTP's `start`, `start_link` and
`start_monitor` wait for `started()`, and `spawn` does not. All four take one
typed `StartOptions`. `started()` may fail, ignore or continue (`Init`), and a
failed init never runs `stopped()`, as OTP. Every instance has an immutable
startup commitment, and readiness is committed by the child, independently
of the waiter. Errors are answered after publication with the final exit
reason. One global lock order covers the commit, readiness and scope
admission. Linked children in the parent's system are owned by its scope,
with a polite Shutdown at the parent's publication and absolute,
composing deadlines. It replaces `start_on`, `start_with_backend`,
`ExecutionGroup::start` and `start_linked`. A new TLA+ model, `Start.tla`,
has eight configurations and 40 negative controls, and a client mapping
covers 51 sites.
- TESTING.md: how databases test (FoundationDB, TigerBeetle, SQLite, AWS,
Jepsen and others), how each technique maps to spawned, and the gaps.
- Tests: planted-bug follow-ups. New scenario-fuzzer oracles for restart
Expand Down
3 changes: 3 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ handlers and the existing default behavior. New policies are explicit and opt-in
release. Client ports are ready on the clients' `spawned-v0.8` branches.
- **Next feature:** dynamic supervisor (rank 12a), design and TLA+ model in
review (PR #245).
- **v0.9 design in review:** unified start API (rank 5h, PR #259,
[design](docs/design/unified-start.md)).
- **0.9 introspection (priority tier 2):** design and TLA+ model in review
(PR #256, [design](docs/design/introspection.md)): `process_info`-style
`info()` readable while a handler is wedged, `sys:get_state`/`get_status`
Expand Down Expand Up @@ -708,6 +710,7 @@ startup: OTP aborts `start_link` on any child start error, while Spawned retries
a Permanent or Transient child's failed factory, panic or startup timeout during
the first start (semantics §11; found reviewing #233). Behaviour change: extend the `Supervision`/`Cohorts` TLA+ models and their Apalache inductive checks (`BudgetBounded`) to the new rule, with a negative control for counting per child, and update the Kani restart-window proofs and the guide. |
| 5g | One exit reason when the runtime drops an actor (v0.8) | Tasks mode reports `Kill` when the runtime drops an actor; threads mode falls back to `Panic("unexpected framework panic")` for an actor that never finishes cleanup. Pick one documented reason for both modes and test it in both. |
| 5h | Unified start API (v0.9, design approved for implementation after three review rounds, PR #259) | [Design](docs/design/unified-start.md) with the `Start.tla` model (8 configurations, 40 negative controls; TLC-only until implemented) and a [client mapping](docs/design/unified-start-client-mapping.md). OTP's `start`, `start_link` and `start_monitor` wait for `started()` and answer `Started`, `Ignored` or an error after the child's publication (with the final exit reason); `spawn` does not wait. One typed `StartOptions`. `started()` may fail, ignore or continue (`Init`); a failed init never runs `stopped()`. An immutable startup commitment per instance; readiness committed by the child under the global lock order; the init timer and abandonment arbitrate through the commitment. Linked and monitored children inherit the parent's group or backend (API-review footgun 5.11); linked children in the parent's system are owned by its scope (polite Shutdown at the parent's publication, absolute composing deadlines). Supervisors keep the whole-attempt `startup_timeout`, and `ignore` keeps the spec as OTP. Shared result types with #245 and #256. Client impact: 51 mechanical sites, no behaviour change. |
| 6 | Test kit with `ActorRef::mock()` | **Phase A implemented** in [`spawned-test`](#testing-crate-spawned-test) (unreleased): closure-backed `Mock` actors that implement `Handler<M>` for every message, so `ActorRef<Mock>` satisfies any `#[protocol]` and replaces hand-stubbed protocol refs with no production change; recording `Probe<M>` recipients (`expect`, `expect_no_message`); bounded harness waits; fault injection (`faults::exit`, `restart_child`, mock delay/discard/crash). Unmocked messages fail loudly. **Remaining:** mocking a field typed as a concrete `ActorRef<B>` needs an `Envelope` hook that downcasts to the concrete message and yields message and reply sender (a core change, deferred); controllable time for timers; a generic idle check; core `ChildHandle::exit(reason)` would make injected exits exact (today `Panic` and `Kill` go through a linked helper, so a panic surfaces as `Panic("panic in handler: ...")`). **Client evidence:** hand-stubbed protocols in ethlambda tests (`RecordingChain` in `column_checks.rs`, also `envelope_checks.rs`, `verdict.rs`). **Research ([actor testing](docs/research/actor-testing.md)):** three gaps against Akka/Erlang kits. (1) A synchronous behavior test kit (Akka `BehaviorTestKit`): run one handler with a test `Context` and record its effects (sends, spawns, timers, stop) without a runtime; needs a core change. (2) Manual time (Akka `ManualTime`): document Tokio's `start_paused` for async actors; thread actors need the framework-owned clock, the same seam as the [simulation backend spike](#simulation-backend-spike) and `ctx.now()`, so build one clock, not two. (3) Concrete `ActorRef<B>` mocking stays deferred (actix's `Mocker` is the precedent); until then users hold protocol refs or `Recipient`s. Also: the idle check should report total deadlock Go-`checkdead` style (every actor idle, a request outstanding, no timer pending), and a replay-equivalence check for event-sourced actors ([event sourcing](docs/research/event-sourcing.md)). |
| 6b | Shared-state and abort lints in `#[actor]` | Zero runtime cost. The macro warns when an actor's fields hold shared mutable state (`Arc<Mutex<_>>`, `Arc<RwLock<_>>`, atomics behind `Arc`, `static mut`), with an opt-out attribute for deliberate cases, and a build script check warns when the profile uses `panic = "abort"`, under which a handler panic kills the process instead of one actor. Syntactic only (it cannot see sharing behind a type alias), but it catches the common pattern, including the one LLM-written code reaches for first. Erlang gap: memory isolation. |
| 7 | Request deadlock detection | **Client evidence:** requests awaited inside handlers exist (ethrex peer table), no cycle found; keep as a cheap safety net. `ActorError::WouldDeadlock` naming the cycle instead of a timeout. `ActorRef::request` takes only `&self`, so set a thread-local `CURRENT_ACTOR` only while the actor's own handler future is polled (and around the synchronous handler in thread mode); detached helpers create no edges. Keep a small wait set per actor for `join!`. Measure cost before enabling outside debug builds. **Approach chosen ([deadlock and stall detection](docs/research/deadlock-and-stall-detection.md)):** eager detection. Add a wait-for edge when a handler sends a request, walk the per-actor wait sets for a cycle, fail the request that would close it with `WouldDeadlock` naming the cycle, remove the edge on reply or timeout; a request to self fails at once (Erlang's `calling_self`). Waits on raw channels, locks or `spawn_blocking` create no edges, so it is a safety net, not a proof. Edges are exported to rank 30. |
Expand Down
7 changes: 7 additions & 0 deletions docs/design/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ Active design contracts. Usage is documented in the [guide](../GUIDE.md).
structured reports, the stall watchdog and the attachable remote console
(`spawned-ctl`). Model: `verification/tla/Introspection.tla`.

- **[unified-start.md](unified-start.md)** (rank 5h, 0.9, design in review,
not implemented): one start API as OTP's `start`, `start_link` and
`start_monitor` plus `spawn`, with `StartOptions`, placement inheritance,
fallible init, continuations and atomic names. Model:
`verification/tla/Start.tla`. Client rewrites:
[unified-start-client-mapping.md](unified-start-client-mapping.md).

Earlier designs (the v0.5 API redesign alternatives, the framework comparison
and superseded roadmap plans) are archived in
[`legacy/docs/design`](https://github.com/lambdaclass/spawned/tree/efba24340a01df82f872ec422b9dbaf48f897b04/legacy/docs/design).
Loading
Loading