tla-checker 0.9.0 → 0.24.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,71 +1,77 @@
1
- # tla-rs
1
+ # WebAssembly
2
2
 
3
- A TLA+ model checker and interactive exploration tool written in Rust.
3
+ The core library compiles to WASM for browser embedding. Every [GitHub release](https://github.com/fabracht/tla-rs/releases/latest) ships the built engine as `tla_checker.js` and `tla_checker_bg.wasm`, and publishes it to npm as [`tla-checker`](https://www.npmjs.com/package/tla-checker), with TypeScript declarations:
4
4
 
5
- tla-rs verifies TLA+ specifications by exploring all reachable states, checking invariants, and reporting counterexamples. Beyond pass/fail checking it offers an interactive TUI for stepping through state spaces, scenario-driven exploration, property-satisfaction analytics, parameter sweeps, tested demo walkthroughs (with an optional in-browser explorer), and an MCP server for agentic clients. The core library compiles to WebAssembly for browser embedding. It's a lightweight alternative to the official TLC model checker for specs that fit its supported subset.
5
+ ```bash
6
+ npm install tla-checker
7
+ ```
8
+
9
+ ```js
10
+ import init, { check_spec } from "tla-checker";
11
+ await init();
12
+ ```
6
13
 
7
- ## Installation
14
+ To build it from a working copy (needs [cargo-make](https://github.com/sagiegurari/cargo-make) and the `wasm32-unknown-unknown` target; a `wasm-bindgen-cli` matching `Cargo.lock` is installed into `.wasm-tools/` when missing):
8
15
 
9
16
  ```bash
10
- cargo build --release
17
+ cargo make wasm
11
18
  ```
12
19
 
13
- The binary will be at `target/release/tla`. Prebuilt binaries and the `tla-mcp` server are available via Homebrew, an install script, or GitHub releases — see the [MCP Server guide](MCP.md#install).
20
+ This produces a `pkg/` directory with `tla_checker_bg.wasm`, the `tla_checker.js` bindings, and TypeScript declarations. The bindings are generated with `wasm-bindgen --target web`, so the module must be initialized before any binding is called: `await init()` (the default export, which fetches `tla_checker_bg.wasm` next to the JS file) or `initSync({ module: bytes })` with the wasm bytes.
14
21
 
15
- ## Quick Start
22
+ ```js
23
+ import init, { check_spec_with_options } from "./tla_checker.js";
24
+ await init();
25
+ ```
16
26
 
17
- ```bash
18
- tla spec.tla
19
- tla spec.tla -c 'N=5' -c 'Procs={"p1","p2","p3"}'
20
- tla spec.tla -c 'Proc={a,b,c}' --symmetry Proc
21
- tla spec.tla --config model.cfg
22
- tla spec.tla --quick # limit to 10,000 states
23
- tla spec.tla -i # interactive TUI
27
+ The WASM API provides four checking bindings, each taking the spec source and returning a JSON string:
28
+
29
+ | Binding | Arguments |
30
+ |---------|-----------|
31
+ | `check_spec(spec, constants_json)` | Default limits (1,000,000 states, depth 100). |
32
+ | `check_spec_with_config(spec, constants_json, max_states, max_depth, allow_deadlock, export_dot)` | Explicit limits. |
33
+ | `check_spec_with_cfg(spec, cfg_source, constants_json, max_states, max_depth, allow_deadlock, export_dot)` | A TLC-style cfg plus explicit limits. |
34
+ | `check_spec_with_options(spec, options_json)` | A JSON options object (below). |
35
+
36
+ The result has `success`, `error_type` and `error_message` (`null` on success), `states_explored`, `trace` (the counterexample as an array of strings, one formatted state each, or `null`), `dot` (the DOT graph when requested, or `null`), and `warnings`.
37
+
38
+ The `check_spec_with_options` API accepts a JSON options object:
39
+
40
+ ```js
41
+ const result = JSON.parse(check_spec_with_options(specSource, JSON.stringify({
42
+ constants: { N: 3 },
43
+ max_states: 10000,
44
+ max_depth: 50,
45
+ allow_deadlock: true,
46
+ export_dot: true,
47
+ dot_mode: "choices", // "full", "trace", "clean" (default), "choices"
48
+ cfg_source: "INIT Init\nNEXT Next\n"
49
+ })));
50
+
51
+ if (result.dot) {
52
+ // DOT graph string: "digraph StateGraph { ... }"
53
+ }
24
54
  ```
25
55
 
26
- Constants accept integers (`42`), booleans (`TRUE`), quoted strings (`"hello"`), sets (`{1,2,3}`), tuples (`<<1,2>>`), records (`[hp |-> 100]`), and functions (`a :> 1 @@ b :> 2`).
27
-
28
- A bare identifier is a **model value** — an uninterpreted, pairwise-distinct atom, matching TLC. `n1` is not equal to the string `"n1"`, so `-c 'Proc={a,b,c}'` yields three model values, not three strings. Symmetry reduction requires a set of model values (`--symmetry` rejects a set of quoted strings, as TLC does).
29
-
30
- ## Options
31
-
32
- | Option | Description |
33
- |--------|-------------|
34
- | `-c NAME=VALUE` | Set a constant value |
35
- | `-s CONST` | Enable symmetry reduction for a constant |
36
- | `--config PATH` | Load TLC-style cfg file (auto-discovers `Spec.cfg` next to `Spec.tla`) |
37
- | `--max-states N` | Maximum states to explore (default: 1000000) |
38
- | `--max-depth N` | Maximum trace depth (default: 100) |
39
- | `-q` | Quick exploration (limit: 10,000 states) |
40
- | `--export-dot FILE` | Export state graph to DOT format |
41
- | `--dot-mode MODE` | DOT mode: `full`, `trace`, `clean` (default), `choices` |
42
- | `--allow-deadlock` | Allow states with no successors |
43
- | `--check-liveness` | Check liveness and fairness properties |
44
- | `--continue` | Continue past invariant violations |
45
- | `--count-satisfying NAME` | Count states satisfying a definition (repeatable) |
46
- | `--sweep NAME=V1;V2;...` | Sweep a constant across values, compare results |
47
- | `--scenario TEXT` | Explore a specific scenario (or `@file`) |
48
- | `-i` | Interactive TUI exploration mode |
49
- | `--present FILE` | Run a demo manifest (`.json`/`.toml`); TUI walkthrough, or `--validate` for a pass/fail report |
50
- | `--export-md FILE` | With `--present`: write a Markdown walkthrough |
51
- | `--export-html FILE` | With `--present`: write a self-contained HTML walkthrough |
52
- | `--explorable` | With `--export-html`: embed the wasm engine for in-browser state exploration |
53
- | `--json` | JSON output |
54
- | `-v` | Verbose output (depth breakdowns, etc.) |
55
- | `--version`, `-V` | Show version information |
56
-
57
- ## Documentation
58
-
59
- | Guide | Contents |
60
- |-------|----------|
61
- | [CLI Guide](CLI_GUIDE.md) | Configuration files, scenarios, demo walkthroughs (incl. the `--explorable` browser explorer), interactive mode, analytics, output, and state-graph visualization |
62
- | [TLA+ Support](TLA_SUPPORT.md) | Supported operator subset, module instances, spec structure, and limitations |
63
- | [WebAssembly](WASM.md) | Browser-embeddable WASM API, including the live stepping bindings |
64
- | [MCP Server](MCP.md) | `tla-mcp` install, client registration, and tool reference |
65
- | [Syntax Status](SYNTAX_STATUS.md) | Operator-by-operator coverage table |
66
- | [Architecture](ARCHITECTURE.md) | Internal design |
67
- | [Practical TLA+ Guide](USER_GUIDE_TO_PRACTICAL_TLA.md) | Worked guidance for writing checkable specs |
68
-
69
- ## License
70
-
71
- MIT
56
+ | Option | Type | Description |
57
+ |--------|------|-------------|
58
+ | `constants` | object | Constant values (`{"N": 3, "Procs": ["a","b"]}`); a JSON array becomes a set, an object a record |
59
+ | `cfg_source` | string | TLC-style cfg file contents |
60
+ | `max_states` | number | Maximum states to explore |
61
+ | `max_depth` | number | Maximum trace depth |
62
+ | `allow_deadlock` | bool | Allow states with no successors |
63
+ | `export_dot` | bool | Include DOT graph in result |
64
+ | `dot_mode` | string | DOT export mode: `full`, `trace`, `clean` (default), `choices` |
65
+
66
+ ## Stepping API
67
+
68
+ For step-by-step exploration there are four additional bindings. `explore_init`, `explore_next`, and `explore_invariants` power the [`--explorable` HTML export](https://github.com/fabracht/tla-rs/blob/main/CLI_GUIDE.md#demo-walkthroughs); `explore_eval` is available for embedders that want to evaluate an arbitrary expression at a state:
69
+
70
+ | Binding | Returns |
71
+ |---------|---------|
72
+ | `explore_init(spec, cfg, constants)` | The initial states. |
73
+ | `explore_next(spec, cfg, constants, state)` | The enabled transitions from a state, with action names and change deltas. |
74
+ | `explore_eval(spec, cfg, constants, state, expr)` | The value of a TLA+ expression evaluated at a state. |
75
+ | `explore_invariants(spec, cfg, constants, state)` | Each invariant's name and whether it holds at the state. |
76
+
77
+ Each takes the spec source, a cfg source string (empty for none), and a JSON constants object; the per-state bindings also take a JSON state. All return a JSON string carrying an `ok` flag (and an `error` message when `ok` is false). States round-trip through the typed JSON form produced by `explore_init`/`explore_next`, so the result of one call can be fed straight into the next.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tla-checker",
3
- "version": "0.9.0",
3
+ "version": "0.24.8",
4
4
  "type": "module",
5
5
  "description": "A TLA+ model checker compiled to WebAssembly",
6
6
  "license": "MIT OR Apache-2.0",
@@ -8,6 +8,10 @@
8
8
  "type": "git",
9
9
  "url": "git+https://github.com/fabracht/tla-rs.git"
10
10
  },
11
+ "homepage": "https://github.com/fabracht/tla-rs#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/fabracht/tla-rs/issues"
14
+ },
11
15
  "main": "tla_checker.js",
12
16
  "types": "tla_checker.d.ts",
13
17
  "files": [
@@ -16,13 +20,5 @@
16
20
  "tla_checker.d.ts",
17
21
  "tla_checker_bg.wasm.d.ts"
18
22
  ],
19
- "keywords": [
20
- "tla",
21
- "model-checking",
22
- "formal-verification",
23
- "wasm"
24
- ],
25
- "sideEffects": [
26
- "./snippets/*"
27
- ]
23
+ "keywords": ["tla", "model-checking", "formal-verification", "wasm"]
28
24
  }
package/tla_checker.js CHANGED
@@ -242,7 +242,6 @@ export function explore_next(spec_source, cfg_source, constants_json, state_json
242
242
  wasm.__wbindgen_export3(deferred5_0, deferred5_1, 1);
243
243
  }
244
244
  }
245
-
246
245
  function __wbg_get_imports() {
247
246
  const import0 = {
248
247
  __proto__: null,
@@ -262,8 +261,7 @@ function getDataViewMemory0() {
262
261
  }
263
262
 
264
263
  function getStringFromWasm0(ptr, len) {
265
- ptr = ptr >>> 0;
266
- return decodeText(ptr, len);
264
+ return decodeText(ptr >>> 0, len);
267
265
  }
268
266
 
269
267
  let cachedUint8ArrayMemory0 = null;
@@ -340,8 +338,9 @@ if (!('encodeInto' in cachedTextEncoder)) {
340
338
 
341
339
  let WASM_VECTOR_LEN = 0;
342
340
 
343
- let wasmModule, wasm;
341
+ let wasmModule, wasmInstance, wasm;
344
342
  function __wbg_finalize_init(instance, module) {
343
+ wasmInstance = instance;
345
344
  wasm = instance.exports;
346
345
  wasmModule = module;
347
346
  cachedDataViewMemory0 = null;
@@ -351,11 +350,15 @@ function __wbg_finalize_init(instance, module) {
351
350
 
352
351
  async function __wbg_load(module, imports) {
353
352
  if (typeof Response === 'function' && module instanceof Response) {
353
+ if (!module.ok) {
354
+ throw new Error(`failed to fetch Wasm: ${module.status} ${module.statusText} fetching '${module.url}'`);
355
+ }
356
+
354
357
  if (typeof WebAssembly.instantiateStreaming === 'function') {
355
358
  try {
356
359
  return await WebAssembly.instantiateStreaming(module, imports);
357
360
  } catch (e) {
358
- const validResponse = module.ok && expectedResponseType(module.type);
361
+ const validResponse = expectedResponseType(module.type);
359
362
 
360
363
  if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
361
364
  console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
Binary file