Skip to content

feat: compound boolean asserts in invariants (#101)#134

Merged
nerdsane merged 1 commit intomainfrom
track6-compound-asserts
Apr 16, 2026
Merged

feat: compound boolean asserts in invariants (#101)#134
nerdsane merged 1 commit intomainfrom
track6-compound-asserts

Conversation

@nerdsane
Copy link
Copy Markdown
Owner

Resolves #101.

Summary

  • Extend IOA invariant asserts with &&, ||, parens, and ! negation
  • migrations_ok && typecheck_ok && unit_tests_ok now works as a single-expression invariant, so safety properties spanning N gates no longer have to be replicated as per-transition guards

Details

  • Parser (crates/temper-spec/src/automaton/assert_parser.rs) rewritten as recursive-descent tokenizer + parser; adds ParsedAssert::BoolRequired{var,expect}, And(Vec), Or(Vec)
  • Runtime (temper-runtime/scheduler/{sim_handler,sim_actor_system}) adds matching SpecAssert variants and a recursive evaluate_spec_assert helper; new SimActorHandler::bool_field(var) trait accessor
  • Server (temper-server/entity_actor/sim_handler) translates new ParsedAssert variants and exposes booleans
  • Verify (temper-verify) adds InvariantKind::And/Or, updates BoolRequired to carry expect, recursively evaluates across proptest_gen, simulation, stateright_impl, and smt
  • Compound expressions referencing undeclared bools fall back to Unverifiable so model checking stays safe
  • SMT induction: And sound via per-part check; Or defers to runtime (joint encoding out of scope)

Test plan

  • cargo test -p temper-spec — 194 pass (26 parser tests including compound coverage)
  • cargo test -p temper-runtime --lib — 92 pass
  • cargo test -p temper-server --lib — 226 pass
  • cargo test -p temper-verify --lib — 76 pass + 3 new compound tests
  • Workspace cargo build clean
  • Code review (see code-reviewer agent findings — all green with low-severity follow-ups)

🤖 Generated with Claude Code

Extend the invariant assertion language with `&&`, `||`, parentheses,
and `!` negation, so safety properties can span multiple boolean gates
in a single expression (e.g. `migrations_ok && typecheck_ok && unit_tests_ok`).
Previously invariants could only check single-field assertions, forcing
authors to replicate the condition as per-transition guards — which catch
illegal transitions but not illegal states reached by any other path.

Changes:
- `temper-spec/assert_parser`: rewrite as recursive-descent tokenizer +
  parser; add `ParsedAssert::BoolRequired{var,expect}`, `And`, `Or`.
- `temper-runtime/sim_handler` + `sim_actor_system`: add matching
  `SpecAssert::BoolRequired/And/Or` variants with recursive evaluation;
  add `SimActorHandler::bool_field(var)` accessor.
- `temper-server/entity_actor/sim_handler`: map new `ParsedAssert`
  variants; expose booleans via the trait method.
- `temper-verify`: add `InvariantKind::And/Or`, update `BoolRequired`
  to carry `expect`, factor evaluators into recursive helpers across
  proptest_gen, simulation, stateright_impl, and smt. Compound
  expressions referencing undeclared booleans fall back to Unverifiable
  so model checking continues to behave safely.
- SMT induction for `And` is sound via per-part check; `Or` defers to
  runtime/simulation (joint encoding out of scope for this PR).

26 parser tests + 3 compound invariant tests pass. Full workspace
`cargo build` is clean; temper-spec/temper-runtime/temper-server/
temper-verify lib tests all green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@nerdsane nerdsane merged commit b73c421 into main Apr 16, 2026
1 of 3 checks passed
@nerdsane nerdsane deleted the track6-compound-asserts branch April 16, 2026 20:27
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.

feat: support compound boolean assertions in invariants

1 participant