lawspec 0.4.0 → 0.5.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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  **State the law once. Check it everywhere.**
4
4
 
5
- LawSpec 0.4 compiles reusable laws into native property tests, executable examples,
5
+ LawSpec 0.5 compiles reusable laws into native property tests, executable examples,
6
6
  and implementation adapters. The compiler is Haskell, distributed as prebuilt
7
7
  WebAssembly with a Node CLI and an asynchronous, typed JavaScript API.
8
8
 
@@ -11,7 +11,7 @@ WebAssembly with a Node CLI and an asynchronous, typed JavaScript API.
11
11
  Install [LawSpec from npm](https://www.npmjs.com/package/lawspec):
12
12
 
13
13
  ```sh
14
- npm install --save-dev lawspec@0.4.0
14
+ npm install --save-dev lawspec@0.5.0
15
15
  npx lawspec --version
16
16
  ```
17
17
 
@@ -25,8 +25,8 @@ local dependencies so LawSpec can create its `package.json` and test script:
25
25
  ```sh
26
26
  mkdir lawspec-example
27
27
  cd lawspec-example
28
- npm exec --package=lawspec@0.4.0 -- lawspec init --target javascript
29
- npm install --save-dev lawspec@0.4.0
28
+ npm exec --package=lawspec@0.5.0 -- lawspec init --target javascript
29
+ npm install --save-dev lawspec@0.5.0
30
30
  npx lawspec check
31
31
  npx lawspec explain 'example.atoi_codec::itoa and then atoi yields a'
32
32
  npx lawspec doctor
@@ -52,7 +52,7 @@ properties with the selected framework's shrinking and failure reporting.
52
52
 
53
53
  | Target | Build setup | Test libraries | Test command |
54
54
  | --- | --- | --- | --- |
55
- | `java` | Maven, JDK 25, release 25 | JetCheck 0.4.0, JUnit Jupiter 5.14.x | `mvn test` |
55
+ | `java` | Maven, JDK 25, release 25 | JetCheck 0.3.0, JUnit Jupiter 5.14.x | `mvn test` |
56
56
  | `python` | Python 3.13 or 3.14, pyproject | pytest 8.4.x, Hypothesis 6.135.26+ (6.x) | `python -m pytest` |
57
57
  | `javascript` | Node 22+, npm, ESM | fast-check 4.x, node:test | `npm test` |
58
58
  | `typescript` | Node 22+, npm, TypeScript 5.9.x, ESM | fast-check 4.x, node:test | `npm test` |
@@ -61,7 +61,7 @@ properties with the selected framework's shrinking and failure reporting.
61
61
  | `kotlin` | JDK/JVM 25, Gradle 9.1–9.3, Kotlin 2.3.21 | Kotest 5.9.1 | `gradle test` |
62
62
 
63
63
  Java 25 and Python 3.13 are the minimum baselines. New JVM releases are admitted
64
- through compatibility profiles after testing; v0.4's current JVM profile certifies
64
+ through compatibility profiles after testing; v0.5's current JVM profile certifies
65
65
  25. Python templates declare `requires-python = ">=3.13"` and runtime checks
66
66
  currently recognize 3.13 and 3.14. Kotlin templates pin Gradle's supported build
67
67
  configuration to Kotlin 2.3.21 and target JVM 25.
@@ -159,10 +159,11 @@ for all (x :: Int32) . atoi (itoa (x)) = x
159
159
 
160
160
  Reusable laws can declare typed unary function parameters and `requires Eq a`.
161
161
  Definitions support law application, function application/composition, universal
162
- quantification, integer and text literals, and equality. Function signatures use `Int32`
163
- and `Text`; generic variables are supported in reusable laws. v0.4 generates
164
- quantified `Int32` and `Text` inputs, including mixed and multiple inputs. Both
165
- types can also be intermediate or compared results. Functions are synchronous
162
+ quantification, `implies`, Boolean predicates, scalar literals, and equality.
163
+ Function signatures use `Int32`, `Text`, and `Bool`; generic variables are
164
+ supported in reusable laws. v0.5 generates quantified inputs of all three types,
165
+ including mixed and multiple inputs. These types can also be intermediate or
166
+ compared results. Functions are synchronous
166
167
  and unary. Text literals are double-quoted, with escapes such as `\"`, `\\`,
167
168
  `\n`, and `\t`; examples must bind each input to a literal of its declared type.
168
169
  Text values contain Unicode scalar values; surrogate code points are rejected.
@@ -178,11 +179,85 @@ Additional primitives, external law packages, cross-unit imports beyond the
178
179
  prelude, async functions, direct existing-symbol binding and browser hosting are
179
180
  outside this release.
180
181
 
181
- ## Expected results and migration to 0.4
182
+ ## Predicates and conditional laws (0.5)
183
+
184
+ A predicate is a unary function returning `Bool`. Use `true` and `false` in
185
+ expressions, example bindings, and expected results. A Boolean expression can
186
+ stand alone as a law's definition: it must evaluate to `true`.
187
+
188
+ `condition implies consequence` checks the consequence only when the condition
189
+ is true. Conditions must have type `Bool`; nested implications short-circuit in
190
+ source order. The consequence can be an equality, another implication, a Boolean
191
+ predicate, or a reusable law application. Quantify any inputs before using them.
192
+
193
+ ```lawspec
194
+ unit example.parse_port
195
+
196
+ validPort :: Int32 -> Bool
197
+ render :: Int32 -> Text
198
+ parse :: Text -> Int32
199
+
200
+ law `valid ports round trip` is
201
+ definition is
202
+ `for all` (x :: Int32) .
203
+ validPort x implies
204
+ parse (render x) = x
205
+ end
206
+
207
+ example `ordinary port` is
208
+ x = 443
209
+ expect validPort x = true
210
+ expect render x = "443"
211
+ expect parse (render x) = 443
212
+ end
213
+
214
+ example `zero is rejected; the round trip is skipped` is
215
+ x = 0
216
+ expect validPort x = false
217
+ end
218
+ end
219
+ ```
220
+
221
+ The [complete port example](https://github.com/brain-fuel/lawspec/blob/v0.5.0/examples/specs/parse_port.lawspec)
222
+ defines valid ports as 1–65535, and covers both endpoints, ordinary ports, zero,
223
+ negative values, and 65536. All explicit `expect` assertions run regardless of
224
+ the law's condition. A false condition skips only the consequence: invalid ports
225
+ never reach `render` or `parse` through the law. Predicate errors still fail the
226
+ test; they are not treated as false.
227
+
228
+ Implication is logical implication, not generator filtering or an assumption.
229
+ Randomized tests still sample the full input domain and count a false condition
230
+ as satisfying the law. A narrow predicate may therefore exercise few or no
231
+ consequences during a random run. Explicit valid examples ensure the important
232
+ cases run, and expectations of both `true` and `false` catch always-false and
233
+ always-true predicate implementations.
234
+
235
+ The prelude includes `satisfies predicate` (the predicate holds for every input)
236
+ and `left inverse when predicate parse render` (the guarded round trip above).
237
+ These reusable laws preserve the condition and its lexical bindings when expanded.
238
+ `equivalent` can also compare two predicates, since `Bool` supports equality.
239
+ The [Boolean flags example](https://github.com/brain-fuel/lawspec/blob/v0.5.0/examples/specs/boolean_flags.lawspec)
240
+ checks that flipping twice restores both `false` and `true`; all targets generate
241
+ Boolean property inputs and explicit tests for both Boolean boundary values. Java caps Boolean-only JetCheck runs at the number of
242
+ possible input combinations (up to 100), avoiding generator exhaustion.
243
+
244
+ In 0.5, `implies`, `true`, and `false` become reserved words. Existing 0.4 specs
245
+ that use those words as identifiers need renaming. The API adds `BoolLit`,
246
+ `Holds`, and `Implies` AST variants, Boolean literal values, and an ordered
247
+ `guards` array on expanded laws. `lawspec explain` prints the conditions.
248
+
249
+ Kotlin adapters now group functions in an `object` named after the unit (for
250
+ example, `object ParsePort` in package `example`). This allows both the port and
251
+ alternatives units to define `render(Int)`. When upgrading a Kotlin project,
252
+ move existing top-level adapter functions into the indicated object; generation
253
+ preserves your adapter and reports the required stub shape. Generated tests call
254
+ `ParsePort.validPort(...)`, `ParsePort.render(...)`, and `ParsePort.parse(...)`.
255
+
256
+ ## Expected results and migration from 0.3
182
257
 
183
258
  Every `example` must bind all quantified inputs and then include one or more
184
259
  `expect <expression> = <literal>` assertions. The expected literal must have the
185
- same `Int32` or `Text` type as the expression. Expressions can reference the
260
+ same `Int32`, `Text`, or `Bool` type as the expression. Expressions can reference the
186
261
  example's inputs and the unit's functions, including composed function calls.
187
262
  Input names shadow function names within expectations, following lexical scope.
188
263
 
@@ -240,7 +315,7 @@ This expands to `for all (x :: Int32) . render (x) = referenceRender (x)`.
240
315
  The example inherits the input name `x` from the prelude. Both functions are
241
316
  user-owned adapter functions; either may delegate to your existing code.
242
317
 
243
- [The complete example](https://github.com/brain-fuel/lawspec/blob/v0.4.0/examples/specs/equivalent.lawspec) compares decimal
318
+ [The complete example](https://github.com/brain-fuel/lawspec/blob/v0.5.0/examples/specs/equivalent.lawspec) compares decimal
244
319
  renderers and two implementations that clamp negative integers to zero. For
245
320
  JavaScript, their adapters can be:
246
321
 
@@ -255,7 +330,7 @@ The same specification generates native tests for all seven targets. The
255
330
  integration suite checks both examples with matching implementations, then
256
331
  breaks each alternative separately to verify detection. The general equivalence law alone does not establish independent correctness;
257
332
  two implementations can share the same bug. Explicit expectations additionally
258
- check the specified outputs at the supplied example inputs. Quantified inputs can be `Int32` or `Text`.
333
+ check the specified outputs at the supplied example inputs. Quantified inputs can be `Int32`, `Text`, or `Bool`.
259
334
 
260
335
  ## Text properties and idempotence
261
336
 
@@ -277,7 +352,7 @@ law `normalizers agree` is
277
352
  end
278
353
  ```
279
354
 
280
- The [slug example](https://github.com/brain-fuel/lawspec/blob/v0.4.0/examples/specs/slug.lawspec)
355
+ The [slug example](https://github.com/brain-fuel/lawspec/blob/v0.5.0/examples/specs/slug.lawspec)
281
356
  compares two implementations of ASCII-space replacement. It includes empty,
282
357
  Unicode and escaped text. Each target uses its native string generator:
283
358
  JetCheck `Generator.stringsOf(Generator.asciiPrintableChars())`, Hypothesis `st.text()`, fast-check `fc.string()`,
@@ -304,7 +379,7 @@ law `canonicalization reaches a fixed point` is
304
379
  end
305
380
  ```
306
381
 
307
- The [canonical URL example](https://github.com/brain-fuel/lawspec/blob/v0.4.0/examples/specs/canonical_url.lawspec)
382
+ The [canonical URL example](https://github.com/brain-fuel/lawspec/blob/v0.5.0/examples/specs/canonical_url.lawspec)
308
383
  uses removal of **all trailing slashes** as a small fixed-point demonstration,
309
384
  not a complete URL canonicalization algorithm. For JavaScript:
310
385
 
@@ -313,10 +388,10 @@ export const canonicalize = value => value.replace(/\/+$/, "");
313
388
  ```
314
389
 
315
390
  Removing just one trailing slash fails the supplied repeated-slash example.
316
- The [mixed-input example](https://github.com/brain-fuel/lawspec/blob/v0.4.0/examples/specs/mixed_inputs.lawspec)
391
+ The [mixed-input example](https://github.com/brain-fuel/lawspec/blob/v0.5.0/examples/specs/mixed_inputs.lawspec)
317
392
  shows `Text` and `Int32` in the same quantified property and executable example.
318
- The JavaScript API represents input bindings and expected values as `number | string`.
319
- Each example includes `expectations: { actual: Expr; expected: number | string }[]`.
393
+ The JavaScript API represents input bindings and expected values as `number | string | boolean`.
394
+ Each example includes `expectations: { actual: Expr; expected: number | string | boolean }[]`.
320
395
 
321
396
  ## Generate all example artifacts
322
397
 
@@ -378,7 +453,7 @@ by the JS shim.
378
453
  ## Build and verify
379
454
 
380
455
  For contributors working from a repository checkout, build a local archive with
381
- `npm pack ./npm` and install it with `npm install --save-dev ./lawspec-0.4.0.tgz`.
456
+ `npm pack ./npm` and install it with `npm install --save-dev ./lawspec-0.5.0.tgz`.
382
457
  The package payload lives in `npm/`.
383
458
 
384
459
  ```sh
package/bin/lawspec.mjs CHANGED
@@ -154,7 +154,11 @@ async function init() {
154
154
  function showExpression(expr) {
155
155
  const value = expr.contents;
156
156
  if (expr.tag === "Var") return value;
157
- if (expr.tag === "Number" || expr.tag === "StringLit")
157
+ if (
158
+ expr.tag === "Number" ||
159
+ expr.tag === "StringLit" ||
160
+ expr.tag === "BoolLit"
161
+ )
158
162
  return JSON.stringify(value);
159
163
  if (expr.tag === "Apply")
160
164
  return `${showExpression(value[0])} (${showExpression(value[1])})`;
@@ -181,13 +185,13 @@ function explainExamples(law) {
181
185
  async function main() {
182
186
  if (!verb || ["help", "--help", "-h"].includes(verb)) {
183
187
  output(
184
- "LawSpec 0.4.0\nUsage: lawspec init --target <language> [--project <directory>]\n lawspec check | doctor | explain <unit>::<law> | generate\n lawspec examples [--target <language>] [--output example_artifacts]\nOptions: --config <path>, --target <language>, --json\nGeneration: --dry-run, --check\nTargets: " +
188
+ "LawSpec 0.5.0\nUsage: lawspec init --target <language> [--project <directory>]\n lawspec check | doctor | explain <unit>::<law> | generate\n lawspec examples [--target <language>] [--output example_artifacts]\nOptions: --config <path>, --target <language>, --json\nGeneration: --dry-run, --check\nTargets: " +
185
189
  targets.join(", "),
186
190
  );
187
191
  return;
188
192
  }
189
193
  if (verb === "--version") {
190
- output("0.4.0");
194
+ output("0.5.0");
191
195
  return;
192
196
  }
193
197
  if (positional.length > (verb === "explain" ? 1 : 0))
@@ -207,7 +211,7 @@ async function main() {
207
211
  : result
208
212
  .map(
209
213
  (r) =>
210
- `${r.target}: ${r.files.length} artifacts in ${r.directory}; ${r.preservedAdapters.length} user adapters preserved.`,
214
+ `${r.target}: ${r.files.length} artifacts in ${r.directory}; ${r.preservedAdapters.length} user adapters preserved.${r.adapterUpdates.length ? "\nReview required adapter signatures:\n" + r.adapterUpdates.map((a) => a.path + "\n" + a.requiredAdapter).join("\n") : ""}`,
211
215
  )
212
216
  .join("\n") +
213
217
  "\nInspection artifacts only; native toolchains and dependencies are not checked. Stubs must be implemented before running tests.",
package/build.json CHANGED
@@ -17,23 +17,23 @@
17
17
  "wasm/lawspec-wasm.cabal"
18
18
  ],
19
19
  "digests": {
20
- "package.yaml": "2c1176c912901bd218743a88df1b67fb1ee8d58ed73fcbe7e2f23827f10a3a0f",
20
+ "package.yaml": "deae9eb35385fd0e08aa44432ae718e7ba6bad8e8320c728018ee9d224733c8c",
21
21
  "src/LawSpec/Api.hs": "00b1e4bc81231ebd387f10652463904084ebf9c3c4486fd2c2217a6d4dbfc157",
22
- "src/LawSpec/Compile.hs": "336eca415ed6c8594612ad5acfc7ff6f29ef387cf3cb374b60b2407f811c31c7",
23
- "src/LawSpec/Emit.hs": "2e23ca38aa5c4c65305283705633209843dd6ba116c43ba8a42ee8731040f7c3",
24
- "src/LawSpec/Gen.hs": "305d7710dbc69b25d95fa6c0ac9a59622481f6b89682c1e5c9048def3962315a",
25
- "src/LawSpec/Model.hs": "d1eda2b420edbc327b1adbf437c6f39a9e576ef0ab9b82f468c28202a433eb96",
26
- "src/LawSpec/Parser.hs": "7fef1876c52d2204f852704150288910bb0c12bcde1d3159219ad25526a879b6",
27
- "src/LawSpec/Prelude.hs": "0b60dd85bdf0642077dfb497043c63606d507e71e12d3ed8bfe2bf773214c66b",
22
+ "src/LawSpec/Compile.hs": "fd696c774025cb0ec6eb29f71661ab71ac603314865ef068778ae9df1355b6cb",
23
+ "src/LawSpec/Emit.hs": "7f53109a18d2450313c9dc9f9ff0fe31d80f533858baf9b2c30e36b8849b416c",
24
+ "src/LawSpec/Gen.hs": "c4b5d4f003c52fb31983794187890ef0dad09c86a451d8e1145974605a5ca0e8",
25
+ "src/LawSpec/Model.hs": "148f133296be537d4e076c2716219fdafa6d2a44b26c9de4b033f87694870911",
26
+ "src/LawSpec/Parser.hs": "12b652dbbf174a7091609385c4564bd47b99e45329cfc1bcdaa3936901b2f966",
27
+ "src/LawSpec/Prelude.hs": "98cc20e242d2f70510fa09e59d0f3e387d1ebe438b4d3435ba2f32a1192cfb4e",
28
28
  "stack.yaml": "20ccf4d599e355e60b7aa4f814a7cd4299fe2048616cc2e6dbdc22a7bd8cec73",
29
29
  "stack.yaml.lock": "ae222b9c81af920c56e50fa4596fa57786e7fa5a7b461390362b2b2ff63818c7",
30
30
  "wasm/app/Exports.hs": "4ecbdac8faa2449e6fc61b93c82e6278fa14374154f29b4dacf0eef433f06a47",
31
31
  "wasm/cabal.project": "021e560afdc5eb4cb7169e7119ecb8f92c9ee170245af909c94b612941bff5cc",
32
32
  "wasm/cabal.project.freeze": "733dbed3d2ecccb26e874fd58f136296dad772184deb1658c196b5d54a0814dc",
33
- "wasm/lawspec-wasm.cabal": "098f1d0fc52575907312c95095846d1d4f6e7ace7cfbe0419a305b9fe8a75a92",
34
- "npm/core.wasm": "0a4ce15cefcd866cd7dd584c32d683c7f8a46823104afcceba1298570883a88a",
33
+ "wasm/lawspec-wasm.cabal": "4c96fa2ec9c6cb61ca16f705c23cdae8723054bb252d27d8ef58043f8e31b868",
34
+ "npm/core.wasm": "581d42431681aa93b64bcd775d403612974f5cb9c7350be4b07d3ed49575c18e",
35
35
  "npm/core_jsffi.js": "88d136efe92f7cff5758c8fec8d9b6bbc9707fe37741cebeeb415fe34ce3d72b",
36
36
  "npm/api.mjs": "d6df654600172131ac66a55b86876fc29cde2a76a0a63bbefff3183488a4837b",
37
- "npm/index.d.ts": "85ad409ae09d243d3b3f21243d0784390d7b0209e2a09fc7c3b733e8dd2e8765"
37
+ "npm/index.d.ts": "9687bedaa439c0888aa54cb94279f4fbda536122f0e55f6ab4ec3ea82ddb4283"
38
38
  }
39
39
  }
package/core.wasm CHANGED
Binary file
@@ -0,0 +1,21 @@
1
+ unit example.boolean_flags
2
+
3
+ flipFlag :: Bool -> Bool
4
+
5
+ law `flipping twice restores either flag` is
6
+ definition is
7
+ `left inverse` flipFlag flipFlag
8
+ end
9
+
10
+ example `disabled becomes enabled and then disabled again` is
11
+ x = false
12
+ expect flipFlag x = true
13
+ expect flipFlag (flipFlag x) = false
14
+ end
15
+
16
+ example `enabled becomes disabled and then enabled again` is
17
+ x = true
18
+ expect flipFlag x = false
19
+ expect flipFlag (flipFlag x) = true
20
+ end
21
+ end
@@ -0,0 +1,66 @@
1
+ unit example.parse_port
2
+
3
+ validPort :: Int32 -> Bool
4
+ render :: Int32 -> Text
5
+ parse :: Text -> Int32
6
+
7
+ law `valid ports round trip` is
8
+ definition is
9
+ `for all` (x :: Int32) .
10
+ validPort x implies
11
+ parse (render x) = x
12
+ end
13
+
14
+ description is
15
+ "For ports in 1 through 65535, {parse} recovers the value written by {render}"
16
+ end
17
+
18
+ example `ordinary port` is
19
+ x = 443
20
+ expect validPort x = true
21
+ expect render x = "443"
22
+ expect parse (render x) = 443
23
+ end
24
+
25
+ example `lowest port is accepted and round trips` is
26
+ x = 1
27
+ expect validPort x = true
28
+ expect render x = "1"
29
+ expect parse (render x) = 1
30
+ end
31
+
32
+ example `highest port is accepted and round trips` is
33
+ x = 65535
34
+ expect validPort x = true
35
+ expect render x = "65535"
36
+ expect parse (render x) = 65535
37
+ end
38
+
39
+ example `zero is rejected; rendering and parsing are skipped` is
40
+ x = 0
41
+ expect validPort x = false
42
+ end
43
+
44
+ example `negative port is rejected; rendering and parsing are skipped` is
45
+ x = -1
46
+ expect validPort x = false
47
+ end
48
+
49
+ example `65536 is rejected; rendering and parsing are skipped` is
50
+ x = 65536
51
+ expect validPort x = false
52
+ end
53
+ end
54
+
55
+ law `the same port contract via the prelude` is
56
+ definition is
57
+ `left inverse when` validPort parse render
58
+ end
59
+
60
+ example `port 8080 satisfies the inherited condition and round trips` is
61
+ x = 8080
62
+ expect validPort x = true
63
+ expect render x = "8080"
64
+ expect parse (render x) = 8080
65
+ end
66
+ end
package/index.d.ts CHANGED
@@ -5,12 +5,12 @@ export interface Location { file: string; line: number; column: number }
5
5
  export interface Diagnostic { code: string; message: string; at: Location | null }
6
6
  export interface Artifact { path: string; content: string; ownership: 'user' | 'generated' }
7
7
  export type Type = {tag: 'Named' | 'Variable'; contents: string} | {tag: 'Arrow'; contents: [Type, Type]};
8
- export type Expr = {tag: 'Var' | 'StringLit'; contents: string} | {tag: 'Number'; contents: number} | {tag: 'Apply' | 'Compose'; contents: [Expr, Expr]};
9
- export type Definition = {tag: 'Forall'; contents: [[string, Type][], Definition]} | {tag: 'Equal'; contents: [Expr, Expr]} | {tag: 'Invoke'; contents: [string, Expr[]]};
10
- export interface Expectation { actual: Expr; expected: number | string }
11
- export interface Example { exampleName: string; bindings: [string, number | string][]; expectations: Expectation[] }
8
+ export type Expr = {tag: 'Var' | 'StringLit'; contents: string} | {tag: 'Number'; contents: number} | {tag: 'BoolLit'; contents: boolean} | {tag: 'Apply' | 'Compose'; contents: [Expr, Expr]};
9
+ export type Definition = {tag: 'Forall'; contents: [[string, Type][], Definition]} | {tag: 'Equal'; contents: [Expr, Expr]} | {tag: 'Holds'; contents: Expr} | {tag: 'Implies'; contents: [Expr, Definition]} | {tag: 'Invoke'; contents: [string, Expr[]]};
10
+ export interface Expectation { actual: Expr; expected: number | string | boolean }
11
+ export interface Example { exampleName: string; bindings: [string, number | string | boolean][]; expectations: Expectation[] }
12
12
  export interface Law { lawName: string; parameters: [string, Type][]; requirements: Type[]; definition: Definition; description: string; rationale: string; examples: Example[]; references: string[]; location: Location }
13
- export interface Expanded { owner: string; name: string; inputs: {inputName: string; inputId: string; inputType: Type}[]; left: Expr; right: Expr; trace: string[]; original: Law }
13
+ export interface Expanded { owner: string; name: string; inputs: {inputName: string; inputId: string; inputType: Type}[]; left: Expr; right: Expr; guards: Expr[]; trace: string[]; original: Law }
14
14
  export interface CheckRequest { sources: Source[] }
15
15
  export interface GenerationRequest extends CheckRequest { target: Target; sourceDir?: string; testDir?: string }
16
16
  export interface Result { diagnostics: Diagnostic[]; laws?: Expanded[]; expansions?: string[]; files?: Artifact[] }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lawspec",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "State the law once. Check it everywhere.",
5
5
  "license": "MIT",
6
6
  "type": "module",