@mettascript/fuzz 2.10.0 → 3.0.0

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/LLMS.md ADDED
@@ -0,0 +1,34 @@
1
+ # @mettascript/fuzz
2
+ Property testing for MeTTa, written in MeTTa. Declare a generator + a property; it generates cases, shrinks a failure to its smallest stable form, returns a replayable result. Also exhaustive enumeration of small domains, model-vs-real state machines, bounded reachability search. Properties are MeTTa code; the TS API only reads results back.
3
+ **Pick** test a MeTTa program→here. `npm i @mettascript/fuzz` — importing registers the `fuzz` module, then MeTTa reaches it with `(import! &self fuzz)`.
4
+ **Property**
5
+ ```metta
6
+ !(import! &self fuzz)
7
+ (: reverse-involution (-> Atom FuzzProperty))
8
+ (= (reverse-involution $xs) (expect-atom-equal (reverse (reverse $xs)) $xs))
9
+ !(fuzz-check reverse-involution (gen-list (gen-int -100 100) 0 40) reverse-involution
10
+ (fuzz-config (Runs 200)))
11
+ ; (FuzzPassed (Property reverse-involution) (Seed 0) (FuzzStatistics (Counts (Passed 213) … (Edges 13) (Random 200)) …))
12
+ ```
13
+ `Runs` counts the **random** cases; edge cases are drawn on top — that is why 200 runs report 213 passes.
14
+ **Expectations** (return one, not a bare `Bool`, so a failure carries a tag + readable details) `(fuzz-pass)` · `(fuzz-fail <tag> <details>)` · `(expect-true b d)` / `(expect-false b d)` · `(expect-atom-equal a b)` structural · `(expect-alpha-equal a b)` ignores variable names · `(expect-results-exact a b)` + `-alpha` / `-multiset` / `-set` relaxing renaming, order, multiplicity.
15
+ **Generators are data** — `(gen-int 0 9)` is an atom the runner interprets, not a function; that is what makes one declaration replayable, shrinkable and enumerable. *Scalars* `gen-bool gen-int gen-int-origin gen-sized-int gen-float gen-float-range gen-float-bits gen-char gen-char-ascii gen-char-unicode gen-symbol gen-syntax-token gen-const` · *Text* `gen-string gen-ascii-string gen-unicode-string` · *Structure* `gen-tuple gen-list gen-option gen-element gen-one-of gen-frequency` · *Combinators* `gen-map gen-bind gen-filter gen-sized gen-resize gen-recursive gen-custom` · *Languages* `gen-grammar gen-grammar-root gen-well-typed` (well-formed terms of a declared grammar/type, not raw trees).
16
+ **Shrinking** runs under a named order (`mettascript-shrink-v1`), so the smallest form is stable across runs rather than a function of the seed; the result says whether it reached a local minimum and why not. A custom generator may supply its own shrinker.
17
+ **Exhaustive** `!(fuzz-check-exhaustive small (gen-bool) always (fuzz-config (MaxEnumerated 10)))` → `(FuzzExhaustivelyVerified (Property small) (DomainCount 2) …)` covers the whole domain — a *proof over it*, not evidence. A domain exceeding the bound is reported incomplete, **never** verified.
18
+ **State machines** generation walks the model only (a command sequence is chosen without touching the real system); execution runs both and compares; a divergence shrinks to the shortest sequence that still diverges.
19
+ ```metta
20
+ (FuzzMachine Counter (InitialModel (Count 0)) (InitializeReal counter-initialize)
21
+ (CommandGenerator counter-command-generator) (Precondition counter-precondition)
22
+ (Execute counter-execute) (NextModel counter-next-model)
23
+ (Postcondition counter-postcondition) (Invariant counter-invariant) (Cleanup counter-cleanup))
24
+ !(fuzz-check-machine Counter (fuzz-config (Runs 20) (MaxSize 6)))
25
+ ```
26
+ **Reachability** `!(fuzz-reachable Counter (Count 0) enumerate transition target (reach-config (MaxDepth 20)))`. A transition may return several next states; the ordered bag becomes outgoing edges and a witness records which branch it took. Four outcomes, deliberately distinct — do not collapse them: `FuzzReachable` found, witness replayed from the initial state before reporting · `FuzzReachabilityExhausted` unreachable **in the declared finite model** · `FuzzUnreachableWithinDepth` nothing at or below `MaxDepth`, says nothing beyond · `FuzzReachabilityCutoff` a limit / incomplete enumeration / replay mismatch, never exhaustion.
27
+ **Suite CLI** declares tests as data; runs the declarations a file carries, **not** its `!` queries.
28
+ ```metta
29
+ (FuzzTest involution (gen-list (gen-int -20 20) 0 6) reverse-involution (fuzz-config (Runs 200)))
30
+ ```
31
+ `metta fuzz suite.metta` · `--seed 7 --runs 50` override each declaration · `--exhaustive` enumerate instead of sample · `--corpus regressions` replay stored counterexamples and record new ones · `metta reach suite.metta` for `(FuzzReachTest …)`. Exit codes `0` pass/definitive · `1` property failure · `2` invalid input or corrupt stored data · `3` incomplete run. `--corpus <dir>` keeps one counterexample per file, meant to be committed; values go through a versioned codec so `NaN` survives exactly.
32
+ **Reading results from TS** `decodeFuzzOutcome(atom)`→typed union · `renderOutcomeLine(o)`→one line · `exitCodeForOutcomes(os)`→worst-first code. The decoder is strict: an unrecognised atom becomes `undecodable`, never a pass.
33
+ **Traps** *`Runs` is the random count, not the total* — reported `Passed` exceeds it. · *Exhausted ≠ unreachable* — `FuzzUnreachableWithinDepth` only bounds the search; a cutoff is neither. · *Verified ≠ passed* — an over-large domain reports incomplete and must not be read as proof. · *The suite CLI ignores `!` queries* — a file whose checks are only `!` lines runs zero tests and exits 0. · *A run is a function of its seed* — same seed, same cases; that is what makes a reported failure reproduce.
34
+ **Next** `node` the `metta fuzz` CLI · `core` engine · `libraries` MeTTa stdlib to test against.
package/README.md CHANGED
@@ -167,3 +167,9 @@ The decoder is strict: an atom it does not recognize becomes an `undecodable` ou
167
167
  ## Determinism
168
168
 
169
169
  A run is a function of its seed. The random source, the shrink order, the replay keys, and the exhaustive enumeration order are all named and versioned, so a reported failure reproduces, and `metta fuzz --seed <n>` twice gives the same cases.
170
+
171
+ ## For language models
172
+
173
+ [`LLMS.md`](./LLMS.md) is a one-page, high-density reference for this package: API surface, working
174
+ examples, and the mistakes that produce wrong code. The repository root carries an
175
+ [`llms.txt`](../../llms.txt) index of all of them.