diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index b67789c..277ad42 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,107 @@ +# MeTTaScript 2.8.0 + +A property-testing library written in MeTTa, `collapse` matching current Hyperon, and interpreter work that +makes deep tail recursion finish instead of overflowing. + +## Property testing: `@mettascript/fuzz` + +State a property that should hold for every input, and the library generates inputs, finds a counterexample, +and shrinks it to the smallest one that still fails: + +```metta +!(import! &self fuzz) + +(: reverse-involution (-> Atom FuzzProperty)) +(= (reverse-involution $xs) (expect-atom-equal (reverse (reverse $xs)) $xs)) + +!(fuzz-check reverse-involution (gen-list (gen-int -100 100) 0 40) reverse-involution + (fuzz-config (Runs 200))) +``` + +The policy is MeTTa. Generation, shrinking, the run loop, the state machines, and the search are rewrite +rules in `packages/fuzz/src/metta`, and TypeScript supplies only what a representation needs: a random +source, a structural key over atoms, and a versioned atom codec. + +What the library covers: + +- Generators as data, from scalars and text through `gen-tuple`, `gen-list`, `gen-map`, `gen-bind`, + `gen-filter`, `gen-recursive`, and `gen-custom`. Because a generator is an atom rather than a function, + the same declaration can be replayed from a seed, shrunk, or enumerated. +- Grammar and type-directed generation, so a generated term is a sentence of a declared language or a + well-typed term rather than a random tree. +- Shrinking 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, or stopped early and why. +- Exhaustive checking with a choice-vector cursor. `FuzzExhaustivelyVerified` carries the domain count and + means the whole domain passed. A domain that does not fit the bound is reported as an incomplete run, + never as verified. +- Model-based state machines: describe the system as a model you trust and the real thing you do not, and a + divergence shrinks to the shortest command sequence that separates them. +- Bounded reachability, breadth first, over a transition relation that may return several next states. A + reported witness is replayed from the initial state before it is trusted, and the four answers stay + distinct: a witness, exhaustion of a finite model, nothing found at or below `MaxDepth`, and a cutoff. +- Expectation combinators that carry a tag and details, so a failure says what was wrong rather than + returning `False`. + +Every run is a function of its seed. The random source, the shrink order, the replay keys, and the +enumeration order are all named and versioned, so a reported failure reproduces. + +## Running suites from the command line + +Declare tests as data and let the CLI find them: + +```bash +metta fuzz suite.metta # run every (FuzzTest ...) declaration +metta fuzz --exhaustive suite.metta # enumerate each domain instead +metta fuzz --corpus regressions suite.metta # replay stored counterexamples, record new ones +metta reach suite.metta # run every (FuzzReachTest ...) declaration +``` + +Exit codes make the command a test gate: 0 for a pass or a definitive answer, 1 for a property failure, 2 +for invalid input or corrupt stored data, 3 for an incomplete run. Results go to stdout and diagnostics to +stderr, so `--json` prints exactly one document. + +Reading a suite runs its declarations, not its `!` queries, so discovery cannot become a way to execute +whatever else a file would have done. `import!` and `register-module!` are kept, because a property defined +in an imported file would be undefined without them. + +`--corpus