Skip to content

Actions model: wake-ups from the events contract; mutant: events only - #51

Closed
calvin-archastro wants to merge 2 commits into
mainfrom
feat/events-actions-sync-2
Closed

calvin-archastro wants to merge 2 commits into
mainfrom
feat/events-actions-sync-2

Conversation

@calvin-archastro

Copy link
Copy Markdown
Contributor

Merge order: #50 → this.

Replaces #49 (replayed onto #50; package.json conflict resolved by keeping both).

What

The Actions orchestrator will run pail events --branch '*' --prefix actions/ --cursor <in the area> beside each replica and tick on each event. This makes verify/actions/actions.qnt say so, instead of letting a replica read at any time.

  1. A replica ticks (read) only when woken (woken).
  2. Every write to _actions, _checks or an object of the area is announced to all replicas (announced). A wake is a flag, so a repeated or reordered announcement changes nothing; lose drops one.
  3. wake is the safety poll (and the start-up diff against the cursor): it wakes a replica whatever it was told. This is the events model's contract: cursor resume plus safety poll, so a lost notification only delays a tick.
  4. Time passing announces nothing: a lease that lapses is found only by the poll.
  5. A write that conflicts sends its replica back to read.
  6. noStranded now needs some replica to tick (willTick: woken, mid-commit, or the safety poll will come).
  7. New switch SAFETY_POLL: off = "the orchestrator relies on events only". The sim finds a stranded job (noStranded); it is in mutate_actions.sh with the other 13.
  8. New scenario safetyPollSweepsRun (runner dies, announcements lost, lease lapses in silence, only the poll wakes a replica, which sweeps); witnesses neverLostWake, neverPolled.

Verification

  • npm test: 19 scenarios (18 existing, unchanged, plus the new one) pass.
  • simulate:actions (60k runs, simSafety): no violation. witness:actions: all 7 reached. mutate:actions: all 13 existing switches, CAS+FENCE, and the new SAFETY_POLL are caught.
  • No Rust or generated-artifact change (the actions model has no refinement harness yet).

🤖 Generated with Claude Code

calvin-archastro and others added 2 commits October 31, 2026 12:40
…nts, and a Quint model

A notification is a hint; truth is re-reading the key. The consumer is idempotent,
delivery is at-least-once, and a dropped notification costs latency, never correctness.

- `--cursor FILE|bucket:AREA/KEY`: on start, diff every watched key against the cursor
  (deletions too), emit with source "resume", then stream. Per key the cursor records the
  intent (dirty), the line is written, then the cursor takes the state and clears the mark:
  a crash may repeat a line, never skip one. File cursors are written by temp file and
  rename; bucket cursors by CAS (one consumer per cursor).
- `--safety-poll SECS` (default 60): with Pub/Sub, re-list everything every SECS.
- `--prefix AREA/PREFIX`: object events ({key, version, old, op, source, at}) for the
  repo's sibling area <repo>.AREA/, same nudge-then-re-list rule and cursor.
- `events::Watcher` (observe, scan, mark, emit, save), `HintSource` (injectable hints).
- verify/events: model, simulation, witnesses, mutation script (6 switches), scenarios;
  tests/events_refinement.rs refines the real Watcher against it (refs with a cursor file,
  objects with a bucket cursor). The model found that a cursor written only after the line
  loses a deletion (or a ref reset) after a crash: hence the write-ahead mark.
- pail-ci keeps a cursor; docs and CLI help updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…: events only

An orchestrator replica ticks (`read`) only when woken. Every write to a branch or an
object of the area is announced to all replicas; an announcement may be lost, repeated
or reordered (a wake is a flag), and the safety poll and the start-up diff against the
cursor (verify/events/events.qnt) wake a replica whatever it was told. Time passing
announces nothing, so a lease that lapses is found only by the poll.

- State `woken`; actions `wake` (safety poll / resume) and `lose` (announcement lost).
- `noStranded` now also needs some replica to tick (`willTick`).
- New switch SAFETY_POLL: off is "the orchestrator relies on events only"; the sim finds
  a stranded job (noStranded). mutate_actions.sh runs it with the other switches.
- Scenario safetyPollSweepsRun; witnesses neverLostWake, neverPolled.
- All earlier properties, witnesses, mutants and the 18 scenarios still pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@calvin-archastro

Copy link
Copy Markdown
Contributor Author

Replaced by the replay onto main after #50.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant