lawspec 0.7.0 → 0.9.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/LANGUAGE.md ADDED
@@ -0,0 +1,361 @@
1
+ # LawSpec language and compiler boundary (0.9)
2
+
3
+ LawSpec describes portable laws, concrete examples, and adapter contracts. The
4
+ compiler is written in Haskell. Rust is an output backend alongside Java, Python,
5
+ JavaScript, TypeScript, Go, Haskell, and Kotlin.
6
+
7
+ ## Lists and algebraic containers
8
+
9
+ `List a` is an ordered, finite sequence of values of one type. Lists nest and
10
+ retain duplicates. Literals use brackets; their element type comes from the
11
+ surrounding signature, quantifier, or annotation. An unconstrained empty list
12
+ needs an annotation such as `([] :: List Int8)`.
13
+
14
+ ```lawspec
15
+ unit guide.lists
16
+
17
+ reverse :: List Int32 -> List Int32
18
+
19
+ law `reverse preserves length` is
20
+ definition is
21
+ `for all` (xs :: List Int32) .
22
+ prelude.length (reverse xs) = prelude.length xs
23
+ end
24
+ example `duplicates count separately` is
25
+ xs = [3, 1, 3]
26
+ expect prelude.length xs = 3
27
+ expect reverse xs = [3, 1, 3]
28
+ end
29
+ end
30
+ ```
31
+
32
+ `prelude.length` returns an exact integer. List equality compares corresponding
33
+ values in order and requires equal lengths. It preserves scalar equality rules:
34
+ NaN still differs from itself, signed zeros compare equal, and Symbols compare
35
+ by identity. Generic list equality requires `Eq a`.
36
+
37
+ `Maybe a` has constructors `Nothing` and `Just value`. `Either a b` has
38
+ constructors `Left value` and `Right value`. These are algebraic sums, separate
39
+ from the interoperability types `Nullable a` and `Optional a`.
40
+
41
+ ```lawspec
42
+ unit guide.presence
43
+
44
+ echo :: Maybe (Either Int8 Bool) -> Maybe (Either Int8 Bool)
45
+
46
+ law `preserve every alternative` is
47
+ definition is `for all` (x :: Maybe (Either Int8 Bool)) . echo x = x end
48
+ example `absent` is x = Nothing expect echo x = Nothing end
49
+ example `left integer` is x = Just (Left 127) expect echo x = Just (Left 127) end
50
+ example `right boolean` is x = Just (Right false) expect echo x = Just (Right false) end
51
+ end
52
+ ```
53
+
54
+ For `Maybe (Maybe Bool)`, `Nothing`, `Just Nothing`, and `Just (Just false)`
55
+ remain distinct. Nesting a constructor application as an argument generally
56
+ requires parentheses, as in `Just (Left 127)`.
57
+
58
+ The [collections example](examples/specs/collections.lawspec) combines reverse
59
+ involution, sorting idempotence, sortedness, length, and permutation preservation.
60
+ `sorted` and `permutation` in that example are adapters supplied by the user;
61
+ they are not built-in helpers. Sortedness and length alone cannot establish that
62
+ a sorting adapter retained the original elements.
63
+
64
+ ## Products, sums, and pattern matching
65
+
66
+ A `type` declaration names its constructors and each constructor's fields. One
67
+ constructor describes a product; multiple constructors describe a sum. Type
68
+ parameters are declared explicitly with `:: Type`.
69
+
70
+ ```lawspec
71
+ unit guide.trees
72
+
73
+ type Pair (a :: Type) (b :: Type) is
74
+ Pair
75
+ first :: a
76
+ second :: b
77
+ end
78
+
79
+ type Tree (a :: Type) is
80
+ Leaf value :: a
81
+ Branch children :: List (Tree a)
82
+ end
83
+
84
+ definition rebuild (tree :: Tree a) :: Tree a is
85
+ match tree with
86
+ | Leaf value -> Leaf value
87
+ | Branch children -> Branch children
88
+ end
89
+ end
90
+
91
+ law `preserve the constructor and its fields` is
92
+ definition is `for all` (tree :: Tree Int8) . rebuild tree = tree end
93
+ example `nested branches` is
94
+ tree = Branch [Leaf 127, Branch [], Leaf -128]
95
+ expect rebuild tree = Branch [Leaf 127, Branch [], Leaf -128]
96
+ end
97
+ end
98
+ ```
99
+
100
+ Constructors receive fields in declaration order. A match evaluates its
101
+ scrutinee once; each branch binds that constructor's fields in the same order.
102
+ Bindings are scoped to the branch. Matching must be exhaustive and cannot repeat
103
+ a constructor. Lists match with `Nil` and `Cons head tail`; Maybe and Either use
104
+ their constructors above. Recursive declarations must be strictly positive.
105
+ General indexed constructors and GADT result signatures are not supported.
106
+
107
+ Equality is structural and type-directed, including named fields and nested
108
+ containers. Native public declarations retain their names and type parameters;
109
+ schemas and checked codecs support them at runtime. They are not replacements
110
+ for the public data types. See the target guides for native representations:
111
+ [Java](JAVA.md), [Python](PYTHON.md), [JavaScript/TypeScript](WEB.md),
112
+ [Go](GO.md), [Haskell](HASKELL.md), [Kotlin](KOTLIN.md), and [Rust](RUST.md).
113
+ In Haskell, `Text` remains `Data.Text.Text`, while `List Char` becomes the linked
114
+ list `[Char]`. These are distinct LawSpec types even when they contain the same
115
+ characters.
116
+
117
+ Generators compose the target framework's generators and shrinkers. Recursive
118
+ values have a structural size budget; each constructor reserves enough budget
119
+ for its fields before distributing the remainder. Boundaries include empty and
120
+ singleton lists and constructor-specific values. Small finite domains are
121
+ enumerated. An empty type cannot supply a generated argument, but containers
122
+ such as `List Empty` and `Maybe Empty` can still be inhabited. An empty or
123
+ unreachable input domain never makes a property pass vacuously.
124
+
125
+ Whole-value refinements can inspect products and sums using exhaustive matches.
126
+ List element refinements, Maybe/Either payload refinements, and refined arguments
127
+ of recursive and nonrecursive named type constructors are supported; see
128
+ [refinements](REFINEMENTS.md#named-data-payloads). Direct refinements on named
129
+ constructor fields use checked constructor contracts. Recursive payload predicates
130
+ follow stored type arguments and preserve outer dependent inputs.
131
+
132
+ ## Total definitions
133
+
134
+ A unit can supply an implementation as a checked total definition:
135
+
136
+ ```lawspec
137
+ definition increment (x :: Int8) :: BigInt
138
+ requires Integer Int8
139
+ is
140
+ x + 1
141
+ end
142
+ ```
143
+
144
+ Parameters and the result have explicit types. The optional `requires` clause
145
+ uses the same `Eq`, `Integer`, `Ordered`, and `Bounded` capabilities as laws.
146
+ Requirements are checked even when the definition is unused. Bodies must have
147
+ exhaustive matches, proven structural descent for recursive calls, and guards
148
+ for operations that could otherwise fail. Calls may use other checked
149
+ definitions; external adapters cannot establish a definition's totality.
150
+
151
+ For exact arithmetic, the totality checker can combine linear bounds and Boolean
152
+ guards. For example, `x >= 0 && 1 / (x + 1) > 0` is safe for integer `x`: the
153
+ right side runs only when its denominator is positive. Proof arithmetic uses
154
+ arbitrary exact fractions, preserves strict boundaries, and has a bounded work
155
+ budget. An unproved obligation is rejected; IEEE expressions never acquire
156
+ rational identities such as `x - x = 0` from this checker.
157
+
158
+ Primitive integer ranges are available to the checker automatically, including
159
+ the selected machine width and BigUInt's nonnegative domain. Integer comparisons
160
+ retain integrality: for Int8 `x`, `x < 127 && prelude.Int8 (x + 1) > x` safely
161
+ narrows only on the guarded branch. The unguarded conversion is rejected because
162
+ `127 + 1` is outside Int8. Range bounds alone do not prove that a Rational or
163
+ Decimal input has no fractional part.
164
+ Pattern matching retains the primitive ranges of extracted fields within that
165
+ branch. For example, an Int8 list head still makes `head + 129` strictly positive;
166
+ that fact cannot be reused for an Int64 field in another constructor branch.
167
+
168
+ Definitions produce reusable generated source with checked native entry points
169
+ on all eight targets. They do not produce user-owned adapter stubs. Integer
170
+ arithmetic preserves the mathematical result; the example above returns `128`
171
+ for the largest Int8 input. See [the total-function example](examples/specs/total_functions.lawspec)
172
+ for recursive list counting, structural equality, and explicit expected values.
173
+
174
+ Definitions can quantify type variables implicitly through their signatures:
175
+
176
+ ```lawspec
177
+ definition same (x :: a) (y :: a) :: Bool requires Eq a is x == y end
178
+ definition count (xs :: List a) :: BigInt is
179
+ match xs with
180
+ | Nil -> 0
181
+ | Cons head tail -> 1 + count tail
182
+ end
183
+ end
184
+ ```
185
+
186
+ Each template is checked for typing, capabilities, termination, and definedness,
187
+ including unused templates. Calls specialize it to concrete argument and result
188
+ types before Core elaboration. Different calls can use different types; recursive
189
+ self-calls must retain the same types. Ambiguous calls require an annotation,
190
+ such as `count ([] :: List Int8)` to specify an empty list's element type.
191
+ Unused templates emit no instances.
192
+ Checked definitions may also appear in refinement predicates and adapter
193
+ preconditions or postconditions. Their closed call graphs contain only other
194
+ checked definitions; adapter calls remain forbidden in predicates. The compiler
195
+ uses the same concrete Core definitions to check example domains and plan finite
196
+ cases and boundaries that generated tests use at runtime.
197
+ Definition parameters and results may carry refinements. The compiler proves
198
+ body definedness and result claims under ordered input preconditions, checks
199
+ callee preconditions, and preserves the contracts through specialization. Native
200
+ entry points enforce the same contracts. See [refined definitions](REFINEMENTS.md#refined-definitions).
201
+
202
+ ## Source and declarations
203
+
204
+ A source has one named `unit`, function signatures, data declarations, checked
205
+ definitions, reusable refinements, and laws. Qualified unit names determine target module/package paths. Function
206
+ signatures are curried: `a -> b -> c` takes two inputs and returns `c`. Parentheses
207
+ group types and expressions. Comments start with `--` and run to the line end.
208
+
209
+ The following grammar summarizes the main forms; the parser and executable
210
+ compiler tests specify lexical details:
211
+
212
+ ```text
213
+ source = "unit" qualified-name declaration*
214
+ declaration = name "::" type | law | refinement | data-type | function
215
+ data-type = "type" name ("(" name "::" "Type" ")")*
216
+ "is" constructor* "end"
217
+ constructor = name (name "::" type)*
218
+ function = "definition" name parameter* "::" type requirements?
219
+ "is" expression "end"
220
+ type = type-atom ["->" type]
221
+ type-atom = primitive | type-variable | "(" type ")"
222
+ | ("Nullable" | "Optional" | "List" | "Maybe") type-atom
223
+ | "Either" type-atom type-atom
224
+ | data-type-name type-atom*
225
+ | refinement-name argument*
226
+ | "(" name "::" type ["where" expression] ")"
227
+ refinement = "refinement" name parameter* requirements?
228
+ "is" type "end"
229
+ parameter = "(" name "::" type ["where" expression] ")"
230
+ requirements = "requires" (capability type)+
231
+ capability = "Eq" | "Integer" | "Ordered" | "Bounded"
232
+ law = "law" quoted-name parameter* requirements? "is"
233
+ "definition" "is" proposition "end"
234
+ description? rationale? example* references? "end"
235
+ proposition = "`for all`" parameter+ "." proposition
236
+ | expression "=" expression
237
+ | expression "implies" proposition
238
+ | proposition "and" proposition
239
+ | quoted-name expression* | expression
240
+ expression = ... | "[" [expression ("," expression)*] "]"
241
+ | constructor-name expression*
242
+ | "match" expression "with"
243
+ ("|" constructor-name name* "->" expression)+ "end"
244
+ example = "example" quoted-name "is" (name "=" literal)+
245
+ ("expect" expression "=" literal)+ "end"
246
+ ```
247
+
248
+ Law names use backticks. Text/metadata use double quotes with escapes. Named
249
+ refinement declarations state their type versus value parameter kinds, including
250
+ forward references; the compiler validates their arity and argument kinds.
251
+ Lowercase type names represent variables. `a :: Type` is a type parameter, not a
252
+ runtime value with a generator.
253
+
254
+ A generic law is specialized when invoked with concrete adapters. Its declared
255
+ capabilities must justify its operations; specialization resolves those
256
+ requirements for the actual types. `Integer` as a capability requires an integer
257
+ type. `Integer` in a concrete result signature denotes a representation-independent
258
+ mathematical integer. See [refinements and abstract integers](REFINEMENTS.md).
259
+
260
+ ## Expressions and arithmetic
261
+
262
+ Application binds most tightly. The remaining precedence, highest first, is:
263
+ unary `!`/`-`, composition `.`, multiplication/division, addition/subtraction,
264
+ comparisons (`==`, `!=`, `<`, `<=`, `>`, `>=`), `&&`, then `||`.
265
+ Comparisons do not chain. Arithmetic associates left; composition associates
266
+ right. An adjacent numeric sign remains part of an argument: `f -42` applies `f`
267
+ to negative 42. Write `x - 42` for subtraction.
268
+
269
+ Assertion `=` differs from Boolean `==`. `implies` guards its following
270
+ proposition; `and` requires both assertions. Parentheses determine the scope of a
271
+ shared guard. Both Boolean operators and implications short-circuit.
272
+
273
+ Literals acquire types from declared context. Unconstrained integers have type
274
+ `Integer`; decimal tokens have type `Decimal`. An annotation such as
275
+ `(127 :: Int8)` specifies context. A declared float context can type a decimal
276
+ token directly, but an explicitly constructed exact Decimal is not implicitly
277
+ converted into a float.
278
+
279
+ Integer `+`, `-`, `*`, and negation produce exact `Integer` results. Decimal
280
+ dominates integer/Decimal combinations; Rational dominates exact combinations
281
+ involving Rational. Exact `/` returns Rational. `prelude.quot` truncates integer
282
+ quotients toward zero; `prelude.rem` is the associated remainder. Division by
283
+ zero fails when evaluated. Explicit numeric conversions use `prelude.Type`.
284
+ Exact/inexact mixing otherwise fails type checking. IEEE arithmetic widens float
285
+ or complex precision as required; equality treats NaN as unequal and signed
286
+ zero as equal. Decimal rounding is explicit, with a scale and ties-to-even rule.
287
+
288
+ Passing a computed exact result to a bounded adapter argument performs a checked
289
+ conversion. It never wraps, truncates a fraction, or silently changes precision.
290
+ Adapter results are validated against the declared domain before use. See the
291
+ [primitive reference](PRIMITIVES.md) for all domains and helpers.
292
+
293
+ ## Refinements and executable contracts
294
+
295
+ Refinements are pure Boolean predicates over a value and preceding binders.
296
+ They cannot call user adapters. Dependent inputs are generated in order;
297
+ shrinking preserves their predicates. Bounds such as `y > Int8.max - x` are
298
+ computed with exact arithmetic and can drive a dependent generator. If a chosen
299
+ `x` has no possible `y`, generation retries earlier inputs. Search exhaustion
300
+ fails explicitly rather than passing a property with no valid cases.
301
+
302
+ Contracts check preconditions, evaluate an adapter once, validate the result,
303
+ and then check postconditions against that same result. Predicate errors are
304
+ contextual failures, not rejected samples. Small finite domains are enumerated;
305
+ other domains use target property frameworks. `machineBits: 32 | 64` controls
306
+ machine-integer domains independently of the compiler host architecture. Native
307
+ machine-sized adapter bindings additionally verify the executing architecture.
308
+
309
+ ## Compiler stages and public API
310
+
311
+ The parser retains source ranges. Resolution and inference check names, kinds,
312
+ capabilities, contextual literals, and generic specializations. Elaboration
313
+ produces typed core expressions with resolved declaration/binder IDs, explicit
314
+ arithmetic evidence and conversions, plus an authoritative proposition tree.
315
+ Refinement declarations become predicates on quantifiers and contracts; targets
316
+ do not interpret refinement syntax.
317
+
318
+ An independent core validator checks scopes, kinds, operand/result types,
319
+ capability evidence, and conversions. A pure core evaluator supports deterministic
320
+ domain checks and reference tests. The testing planner computes finite cases,
321
+ boundaries, and dependent generator requirements. All eight emitters consume
322
+ that plan and the core, without importing source syntax or inference.
323
+
324
+ `check`/`expand` report semantic validity. `planGeneration` additionally reports
325
+ execution feasibility, including empty finite domains. Source syntax errors,
326
+ semantic errors, core invariant failures, and generation errors have distinct
327
+ diagnostic codes. Runtime failures identify the law/example or adapter contract.
328
+ Parsed expressions retain real source ranges; synthesized expressions identify
329
+ the declaration that caused their creation.
330
+
331
+ API schema v3 uses separately defined wire views, with lossless tagged scalar
332
+ values. It does not serialize internal AST constructors. See the
333
+ [API migration guide](API-MIGRATION.md).
334
+
335
+ ## Beyond 0.9
336
+
337
+ GADTs, indexed families, and general dependent types are planned after 0.9.
338
+ The Core type model distinguishes type arguments from index arguments, but that
339
+ representation is not a claim that arbitrary dependent programs are accepted.
340
+ User-defined products and sums have ordinary uniform type parameters. External
341
+ type bindings, custom generator bindings, and cross-unit packages are separate
342
+ future features.
343
+
344
+ ## Generated project formatting
345
+
346
+ `lawspec init --target java` creates a readable Maven scaffold; Kotlin init
347
+ likewise expands Gradle blocks with two-space indentation. `--minify` explicitly
348
+ selects compact scaffolds and configuration JSON. `generate` and `examples`
349
+ accept the same flag for generated source. The mode is per invocation and does
350
+ not become a project default. Init preserves existing build files, and generation
351
+ preserves user-owned adapters regardless of formatting mode.
352
+
353
+ Generated runtime support and checked definitions belong in source directories;
354
+ framework-specific property helpers belong in test directories. Both follow
355
+ custom layout settings. Python uses PEP 8: four-space indentation, 79-column
356
+ code, and 72-column prose. Other targets follow Google language guidance where
357
+ applicable, with standard Rust formatting. Formatting is deterministic in the
358
+ native and WASM compilers; generation does not download or invoke a formatter.
359
+
360
+ See [the release notes](RELEASE-0.9.md) for compatibility and scope, and the target
361
+ guides for formatting verification and native representation details.
package/PRIMITIVES.md CHANGED
@@ -1,4 +1,4 @@
1
- # LawSpec scalar reference (0.7.0)
1
+ # LawSpec scalar reference (0.9.0)
2
2
 
3
3
  A scalar has a declared domain, checked literals, equality, property inputs, and
4
4
  boundary fixtures. General collections, objects, pointers, and type-only constructs
@@ -142,7 +142,7 @@ portable across architectures.
142
142
  The bundled `scalars.lawspec`, `scalar_catalog.lawspec`, and
143
143
  `scalar_adapters.lawspec` contain explicit fixtures for every scalar family.
144
144
  `tools/scalar-reference.py` produces independent Fraction-based conformance
145
- vectors; `tools/scalar-integration.mjs` executes them across the seven targets.
145
+ vectors; `tools/scalar-integration.mjs` executes them across the eight targets.
146
146
  Set `LAWSPEC_MUTANTS=1` to also verify that incorrect adapters are detected.
147
147
 
148
148
 
package/PYTHON.md ADDED
@@ -0,0 +1,152 @@
1
+ # Python backend
2
+
3
+ Python output follows [PEP 8](https://peps.python.org/pep-0008/): four-space
4
+ indentation, a 79-column code target, 72-column prose comments/docstrings, and
5
+ two blank lines between top-level definitions. Explicit `--minify` permits
6
+ compact layout while preserving Python indentation and semantics.
7
+ `tools/python-formatting-integration.mjs` checks generated runtime, adapter,
8
+ definition, and test files with pycodestyle 2.14.0 at both machine widths. It
9
+ also compares readable and compact syntax trees, including literal contents.
10
+
11
+ Use Python 3.13 or later. Generated tests use Hypothesis; generated data classes,
12
+ scalar operations, and schema validation do not depend on a test framework.
13
+
14
+ ## Native structural values
15
+
16
+ | LawSpec type | Adapter representation |
17
+ | --- | --- |
18
+ | `List a` | `list[A]` |
19
+ | `Maybe a` | `lawspec_schema.Maybe[A]`, with `Nothing` and `Just` variants |
20
+ | `Either a b` | `lawspec_schema.Either[A, B]`, with `Left` and `Right` variants |
21
+ | User-defined products and sums | Named generic dataclasses in `lawspec_data` |
22
+ | `Nullable a`, `Optional a` | Tagged `lawspec_runtime.Presence` values |
23
+
24
+ `Nothing()` differs from `Just(Nothing())`. `Left(value)` differs from
25
+ `Right(value)`. These algebraic variants are separate from the interoperability
26
+ states represented by `Nullable`, `Optional`, `Null`, and `Undefined`.
27
+
28
+ For example, this declaration:
29
+
30
+ ```lawspec
31
+ type Tree (a :: Type) is
32
+ Leaf value :: a
33
+ Branch children :: List (Tree a)
34
+ end
35
+ ```
36
+
37
+ produces a generic `Tree` base and `TreeLeaf` and `TreeBranch` dataclasses. A
38
+ product has one variant: `Pair` with constructor `Pair` produces `PairPair`.
39
+ When names conflict across units or between types and variants, the compiler
40
+ plans distinct names using their Core identities. Use the emitted declarations
41
+ and adapter annotations as the authoritative names.
42
+
43
+ Native pattern matching works on the generated variants:
44
+
45
+ ```python
46
+ import lawspec_data as data
47
+
48
+
49
+ def count_leaves(tree: data.Tree[int]) -> int:
50
+ match tree:
51
+ case data.TreeLeaf():
52
+ return 1
53
+ case data.TreeBranch(children=children):
54
+ return sum(count_leaves(child) for child in children)
55
+ raise TypeError("unknown Tree variant")
56
+ ```
57
+
58
+ Classes are frozen and use slots. Container payloads are copied when crossing
59
+ adapter boundaries, so modifying a native list does not change another use of
60
+ the logical test input. An abstract base cannot be directly constructed; empty
61
+ types acquire no artificial variant.
62
+
63
+ LawSpec equality uses schema-directed comparisons, including IEEE NaN and
64
+ signed-zero rules and Symbol identity. Generated dataclasses do not derive
65
+ Python field equality, whose container shortcuts can change those rules.
66
+
67
+ ## Checked boundaries
68
+
69
+ Generated calls validate input values, convert them to native classes, call the
70
+ adapter, and validate its result. A field extracted from a native product can
71
+ be returned directly from an adapter with the corresponding LawSpec result
72
+ type. The same representation is used for nested and standalone containers.
73
+
74
+ Diagnostics identify constructor fields and list indices. Checks distinguish
75
+ Bool from integers, enforce primitive ranges under the selected `machineBits`,
76
+ reject invalid scalar text, and preserve raw code units, code points, and bytes.
77
+ Preconditions and postconditions operate on validated logical values.
78
+
79
+ ## Total definitions
80
+
81
+ Checked total definitions emit reusable Python functions separately from adapters:
82
+
83
+ ```lawspec
84
+ unit example.total
85
+
86
+ definition increment (x :: Int8) :: BigInt is x + 1 end
87
+ ```
88
+
89
+ ```python
90
+ from lawspec_definitions.example import total
91
+
92
+ symbols = {}
93
+ assert total.increment(symbols, 127) == 128
94
+ ```
95
+
96
+ The first argument is the Symbol fixture context shared within an example.
97
+ Public signatures preserve native container and variant annotations; checked
98
+ conversion enforces element types, ranges, machine profiles, and nested presence
99
+ states at runtime. Errors include the resolved definition name. Source functions
100
+ and implementation bodies have no Hypothesis or pytest dependency.
101
+
102
+ `lawspec_definition_bodies.py` holds checked logical implementations. Public
103
+ modules under `lawspec_definitions/` provide native entry points grouped by unit.
104
+ Both belong in source directories and are generated-owned. Properties invoke
105
+ those checked bodies directly; definitions do not create adapter stubs. Unit
106
+ modules cannot shadow support modules or another unit's package. Native function
107
+ names such as `str` do not shadow built-ins used by generated validation.
108
+
109
+ Definition bodies and Python properties share typed expression rendering. Match
110
+ inputs are evaluated once, branches remain lazy, guards short-circuit, and exact
111
+ Decimal arithmetic is independent of Python's ambient rounding context.
112
+ Definitions must pass structural termination and definedness checks. Generic
113
+ definitions specialize to concrete uses. Refined signatures become checked
114
+ contracts, and refinement predicates may call checked definitions.
115
+
116
+ `tools/python-definitions-integration.mjs` checks standalone source calls,
117
+ properties, incorrect adapters, both machine profiles, custom layouts, compact
118
+ execution, and regeneration protection. The bundled Python corpus passes PEP 8 checks at 79 code columns and 72 prose
119
+ columns. The style audit includes the standalone total-definition fixture.
120
+
121
+ ## Generation and layouts
122
+
123
+ Hypothesis composes tuples, alternatives, lists, and dependent strategies.
124
+ Recursive generation reserves each field's minimum node budget before sharing
125
+ the remainder. List length and element budgets vary together. Shrinking remains
126
+ native to Hypothesis and preserves the schema and structural size bound.
127
+ Small finite domains are enumerated; empty domains do not pass vacuously.
128
+
129
+ `lawspec_data.py` and `lawspec_schema.py` belong in the configured source
130
+ directory. `lawspec_data_strategies.py` belongs in the test directory. Configure
131
+ Python's import paths for those directories when using a custom layout.
132
+ Adapters remain user-owned. Unit names cannot shadow generated support modules.
133
+
134
+
135
+ Internal checked Core definition contracts now run at native and logical entry
136
+ points. Emission proves the obligations first; argument validation precedes
137
+ ordered preconditions, and result validation precedes postconditions. Contract
138
+ binders map explicitly to body inputs and the checked result. Refined source
139
+ signatures now produce these contracts through template proof and specialization.
140
+
141
+ `tools/portable-definition-contract-integration.mjs` exercises Python, JavaScript
142
+ and strict TypeScript with both machine profiles and layouts, without property
143
+ frameworks. It also verifies that deliberately corrupted results are rejected.
144
+ The fixture in `test/DefinitionContractFixture.hs` is shared with the JVM checks.
145
+
146
+ ## Checking Python style
147
+
148
+ Set `LAWSPEC_CORE` to the native compiler, `LAWSPEC_PYTHON` to Python 3.13 or
149
+ later, and `LAWSPEC_PYCODESTYLE` to the `pycodestyle.py` source from version
150
+ 2.14.0. Then run `node tools/python-formatting-integration.mjs`. The checker is
151
+ a development dependency; generating and executing runtime code does not
152
+ require it. Optional positional arguments select individual specification files.