hegeltest 0.1.0 → 0.1.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: facbe6e366b74782ab68e979295856ef15c8da56ea9d9fe9291764cbf1629eb3
4
- data.tar.gz: e78e0364232dc02974f7ca81135a34325a76287c425d59f1d384ef2f2acfb2aa
3
+ metadata.gz: 5979893a1e1ad319ad6526c5f2ad6927961084c40006946c3f4e0d3bb6a9f269
4
+ data.tar.gz: b5c146a01b94e5832fac50b42c983c844a3b494849038c6776ae54d7fb23a787
5
5
  SHA512:
6
- metadata.gz: c977d4fd78f3439b18b731ae14c6772968aff53271fe1f44a8712f044a6dc0bcdcbd0ece18da677a7e3599a831651806a979c6985d5b942e6d89534c5c6eae14
7
- data.tar.gz: 429fb8e7ce09f224c32368ad0d34bc69d1020f56891bdb2616da02acb86fa0ef5c174f340f27fc5a0cdf4918e8a4f82075781128850656b571e0b4232143abf5
6
+ metadata.gz: 7f0d698a9810abb8c3c2d68e38ad947386948ca840d59339962378db721cd8a961009ce7a68d69577b0aed240fbc80d84b635971c2810bcd0cf827eed6a6368d
7
+ data.tar.gz: 111d8e783b4236b9b5105819b9b34e96d2bbb1a0c314a25dc6f093903e0652bedad4d70d9c8951c865e3bcdeb1947c67f425668b599bffce79c6825468c3ce3e
data/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.1] - 2026-08-31
4
+
5
+ The reference that ships inside the gem told a reader to install `hegeltest`
6
+ from git and to point `HEGEL_LIBHEGEL_PATH` at a local build. 0.1.0 shipped
7
+ that text, and 0.1.0 needs neither. A reader who followed it spent their first
8
+ minutes on a checkout and an engine build. The reference now says what the
9
+ README says.
10
+
11
+ A drawn value written inside a larger expression named itself after the
12
+ assignment target, so `term_start_date = Date.new(tc.draw(...), 2, 29)`
13
+ reported `term_start_date` beside a year. Such a draw now takes the generic
14
+ name, and `label:` names it when a name is wanted. See
15
+ [ADR 0014](docs/adr/0014-name-a-drawn-value-only-when-the-draw-is-the-whole-assigned-value.md).
16
+
17
+ The settings table names 100 as libhegel's own default for `test_cases`. The
18
+ README shows how to scope `Hegel::Syntax::Methods` to tagged example groups in
19
+ a suite that already exists, and how to share a group of draws through a plain
20
+ Ruby method. The `text` section says which generators cover the character-set
21
+ options it does not take, measured against libhegel 0.32.5.
22
+
3
23
  ## [0.1.0] - 2026-08-20
4
24
 
5
25
  The first release.
@@ -19,4 +39,5 @@ The engine is called through the `ffi` gem. Each platform gem carries the
19
39
  matching `libhegel` 0.32.5 build. The platform-independent gem carries none,
20
40
  so a run on it needs `HEGEL_LIBHEGEL_PATH` pointing at a local build.
21
41
 
42
+ [0.1.1]: https://github.com/meganemura/hegel-ruby/releases/tag/v0.1.1
22
43
  [0.1.0]: https://github.com/meganemura/hegel-ruby/releases/tag/v0.1.0
data/README.md CHANGED
@@ -31,8 +31,7 @@ same process. There is no server and no Python dependency.
31
31
 
32
32
  ## Status
33
33
 
34
- **The first release is prepared, and the version is `0.1.0`.** Everything
35
- described below runs: Hegel finds a counterexample, shrinks it,
34
+ **Released as `hegeltest` 0.1.0.** Hegel finds a counterexample, shrinks it,
36
35
  names the values it drew, and re-raises your own exception.
37
36
 
38
37
  Work ran in three stages, and all three are done:
@@ -44,22 +43,18 @@ Work ran in three stages, and all three are done:
44
43
  3. **The advanced features**: the example database, targeted testing,
45
44
  stateful testing, phases, and health checks.
46
45
 
47
- **Nothing is published to RubyGems yet.** The packaging is built:
48
- `rake platform_gems:build` produces one gem per platform, each carrying the
49
- matching `libhegel` build. The arm64 macOS gem is verified to find that
50
- engine inside itself and run a property with no `HEGEL_LIBHEGEL_PATH` set.
51
- A `v*` tag publishes all six gems from CI. The Hegel maintainers permit a
52
- third-party project to redistribute their release binaries
53
- ([hegeldev/hegel-rust#411]).
54
-
55
- So running this today means cloning the repository:
46
+ Install it the way you install any gem:
56
47
 
57
- ```bash
58
- bin/setup
59
- bundle exec rake libhegel:fetch # downloads the pinned build, checked against its SHA-256
60
- bundle exec rake
48
+ ```ruby
49
+ # Gemfile
50
+ gem "hegeltest"
61
51
  ```
62
52
 
53
+ Each platform gem carries the matching `libhegel` build, so an install
54
+ compiles nothing and needs no engine on the side. The Hegel maintainers
55
+ permit a third-party project to redistribute their release binaries
56
+ ([hegeldev/hegel-rust#411]).
57
+
63
58
  Every push to main runs the suite on Ruby 3.3, 3.4, and 4.0, across Linux x64
64
59
  and arm64, macOS arm64, and Windows x64 and arm64. Windows arm64 starts at
65
60
  Ruby 3.4, the oldest Ruby that RubyInstaller publishes an arm64 build for. A
@@ -79,13 +74,13 @@ pull request runs Linux x64 alone.
79
74
  | Platforms | Linux amd64/arm64, macOS arm64, Windows amd64/arm64 |
80
75
  | Engine delivery | One prebuilt `libhegel` per platform-specific gem, built by `rake platform_gems:build` |
81
76
 
82
- `HEGEL_LIBHEGEL_PATH` will override the bundled engine with a local build.
77
+ `HEGEL_LIBHEGEL_PATH` overrides the bundled engine with a local build.
83
78
 
84
79
  The gem name follows the Rust implementation, whose published crate is
85
80
  `hegeltest` and whose library is `hegel`. The name `hegel` on RubyGems.org
86
81
  stays free for whoever publishes an official Ruby implementation.
87
82
 
88
- macOS on Intel has no published `libhegel` artifact, so that platform will need
83
+ macOS on Intel has no published `libhegel` artifact, so that platform needs
89
84
  `HEGEL_LIBHEGEL_PATH` and a local build.
90
85
 
91
86
  ## Quickstart
@@ -135,6 +130,33 @@ Including `Hegel::Syntax::Methods` makes the generators available without a
135
130
  prefix, the way FactoryBot makes `create` available. The same generators stay
136
131
  reachable as `Hegel::Generators.arrays(...)` without the include.
137
132
 
133
+ An existing RSpec suite can limit the 25 generator names to tagged example
134
+ groups. This keeps the names out of other groups that have their own helpers:
135
+
136
+ ```ruby
137
+ config.include Hegel::Syntax::Methods, :hegel
138
+ ```
139
+
140
+ A new project can include the methods in every group, as the Quickstart does.
141
+
142
+ Hegel draws values imperatively, so an ordinary Ruby method can share a group
143
+ of draws between properties. Give the method parameter a descriptive name,
144
+ which the default RuboCop naming rule accepts where a block parameter `tc`
145
+ needs no change:
146
+
147
+ ```ruby
148
+ def draw_sorted_pair(test_case)
149
+ low = test_case.draw(integers(min_value: 0, max_value: 100))
150
+ high = test_case.draw(integers(min_value: low, max_value: 200))
151
+ [low, high]
152
+ end
153
+
154
+ Hegel.test do |tc|
155
+ low, high = draw_sorted_pair(tc)
156
+ expect(low).to be <= high
157
+ end
158
+ ```
159
+
138
160
  The generators are `arrays`, `binary`, `booleans`, `characters`, `composite`,
139
161
  `dates`, `datetimes`, `deferred`, `domains`, `emails`, `floats`, `from_regex`,
140
162
  `hashes`, `integers`, `ip_addresses`, `just`, `one_of`, `optional`,
@@ -241,9 +263,10 @@ Inside a test, `tc.note` records a message the failure report prints, and
241
263
  ## Development
242
264
 
243
265
  ```bash
244
- bin/setup # install dependencies
245
- bundle exec rake # run the tests and the linter
246
- bin/console # open an interactive prompt
266
+ bin/setup # install dependencies
267
+ bundle exec rake libhegel:fetch # download the pinned engine, checked against its SHA-256
268
+ bundle exec rake # run the tests and the linter
269
+ bin/console # open an interactive prompt
247
270
  ```
248
271
 
249
272
  `just` recipes call the same Rake tasks, so `just test` and `just lint` work
data/docs/README.md CHANGED
@@ -20,6 +20,7 @@ An index of the design records for `hegel-ruby`.
20
20
  - [0011: Let the test case own every pool drawn from it](adr/0011-let-the-test-case-own-every-pool-drawn-from-it.md)
21
21
  - [0012: Build a failure origin from the caller's own frame](adr/0012-build-a-failure-origin-from-the-callers-own-frame.md)
22
22
  - [0013: Bind libhegel through the ffi gem](adr/0013-bind-libhegel-through-the-ffi-gem.md)
23
+ - [0014: Name a drawn value only when the draw is the whole assigned value](adr/0014-name-a-drawn-value-only-when-the-draw-is-the-whole-assigned-value.md)
23
24
 
24
25
  A new decision gets a new record. A changed decision supersedes the old
25
26
  record instead of editing it, so the history stays readable.
@@ -0,0 +1,74 @@
1
+ # 0014: Name a drawn value only when the draw is the whole assigned value
2
+
3
+ ## Status
4
+
5
+ Accepted.
6
+
7
+ ## Context
8
+
9
+ [ADR 0005](0005-name-drawn-values-from-the-callers-source-with-prism.md)
10
+ recovers a drawn value's name by parsing the caller's source and reading the
11
+ assignment that covers the draw's line. Its Consequences section lists three
12
+ cases it had not checked: a heredoc, several draws on one line, and a method
13
+ chain.
14
+
15
+ A first use of the gem outside this repository reached one of them. The
16
+ caller wrote a draw inside a larger expression:
17
+
18
+ ```ruby
19
+ term_start_date = Date.new(tc.draw(integers(min_value: 1904, max_value: 1904)), 2, 29)
20
+ ```
21
+
22
+ Measured against libhegel 0.32.5, the failure report printed:
23
+
24
+ ```
25
+ term_start_date = 1904
26
+ ```
27
+
28
+ The name says "a date". The value is a year. The reader misread that report
29
+ twice before adding a `label:`.
30
+
31
+ `Hegel::DrawName` already carries the rule this breaks. Its own
32
+ documentation states it: a wrong name misdirects a reader of the failure
33
+ report more than a missing one does, so an ambiguous line returns nil rather
34
+ than choosing between candidates. The module applied that rule to two
35
+ assignments written side by side, and applied the opposite rule to a draw
36
+ buried in one assignment's value.
37
+
38
+ A draw pulled out into a plain method is a separate case, and it already
39
+ worked. Measured on the same engine, a helper whose body reads
40
+ `year = tc.draw(integers(min_value: 1900, max_value: 1910))` reported
41
+ `year = 1900`. `Hegel::TestCase::DRAW_CALLER_DEPTH` lands on the line that
42
+ called the draw, which is the helper's own line, and the name there is the
43
+ one the caller wrote.
44
+
45
+ ## Decision
46
+
47
+ Recover a name only when the assignment's value is the draw call itself: the
48
+ value node is a `Prism::CallNode` whose name is one of the methods that reach
49
+ `Hegel::TestCase#record_draw`. Any other value node returns nil, and
50
+ `Hegel::TestCase#name_for` falls back to the generic name.
51
+
52
+ The three method names stay in `Hegel::TestCase`, which defines them, and
53
+ `Hegel::DrawName.for` takes them as an argument. A fourth draw method then
54
+ has one place to be added.
55
+
56
+ ## Consequences
57
+
58
+ A draw written inside a larger expression reports the generic name and its
59
+ value. The reader loses a name and keeps a value that agrees with it. A
60
+ caller who wants the name back passes `label:`, which
61
+ [ADR 0005](0005-name-drawn-values-from-the-callers-source-with-prism.md)
62
+ already gives precedence over the recovered name.
63
+
64
+ A method chain answers the question ADR 0005 left open, and answers it the
65
+ same way: `xs = tc.draw_integer(0, 10).to_s` reports the generic name,
66
+ because `xs` holds a String and the drawn value is an Integer.
67
+
68
+ A draw written inside another draw's arguments shares the enclosing
69
+ assignment's name, because the enclosing assignment's value is a draw call
70
+ and one line carries both draws. `label:` separates them.
71
+
72
+ `Hegel::DrawName` now answers a narrower question than its name suggests on
73
+ its own, so its documentation states the question it answers and the reason
74
+ for the narrowing.
@@ -6,9 +6,10 @@ module Hegel
6
6
  # Recovers a drawn value's variable name from the caller's own source (see
7
7
  # docs/adr/0005), so a failure report can print `n = 501` instead of
8
8
  # `draw = 501` when the caller never passed a label:. This module only
9
- # answers "what name does path:lineno assign a value to"; deciding
10
- # whether to call it, and what to fall back to when it answers nil, is
11
- # Hegel::TestCase#name_for's job, not this one's.
9
+ # answers "what name does path:lineno assign the value a draw call there
10
+ # produced, when that call is the whole assigned value"; deciding whether
11
+ # to call it, what counts as a draw call, and what to fall back to when it
12
+ # answers nil, is Hegel::TestCase#name_for's job, not this one's.
12
13
  module DrawName
13
14
  # Node types #for treats as "this line names a drawn value". An
14
15
  # explicit list, not every Prism::Node subclass whose name ends in
@@ -23,10 +24,20 @@ module Hegel
23
24
 
24
25
  # The name +path+:+lineno+ assigns a drawn value to, or nil when that
25
26
  # cannot be answered confidently: +path+ cannot be read, Prism cannot
26
- # parse it, or the assignments covering +lineno+ do not single one out.
27
+ # parse it, the assignments covering +lineno+ do not single one out, or
28
+ # the one they single out does not assign a draw call directly.
29
+ # +call_names+ is the set of method names that count as a draw call
30
+ # (Hegel::TestCase::DRAW_METHOD_NAMES); this module has no opinion of
31
+ # its own about which methods draw.
32
+ #
27
33
  # A wrong name would misdirect a reader of the failure report more than
28
34
  # a missing one would, so an ambiguous line returns nil rather than
29
- # guessing between candidates.
35
+ # guessing between candidates. That is also why a singled-out
36
+ # assignment still answers nil when its value is built from a draw
37
+ # rather than being the draw itself, as in `xs = [tc.draw(integers)]`
38
+ # or `n = tc.draw(integers).abs`: the recovered name would describe the
39
+ # Array or the Integer#abs result, not the drawn value the report
40
+ # actually prints next to it.
30
41
  #
31
42
  # Several assignments can cover one line by nesting rather than by
32
43
  # ambiguity. `error = assert_raises do ... n = tc.draw_integer(...) ...
@@ -35,13 +46,16 @@ module Hegel
35
46
  # whenever another candidate sits inside it. Two assignments written
36
47
  # side by side on one line contain neither the other, nothing singles
37
48
  # one out, and the answer is nil.
38
- def for(path, lineno)
49
+ def for(path, lineno, call_names)
39
50
  program = parse(path)
40
51
  return nil unless program
41
52
 
42
53
  matches = assignment_nodes(program).select { |node| covers?(node.location, lineno) }
43
54
  innermost = matches.reject { |node| matches.any? { |other| encloses?(node, other) } }
44
- innermost.one? ? innermost.first.name.to_s : nil
55
+ return nil unless innermost.one?
56
+
57
+ node = innermost.first
58
+ (node.value.is_a?(Prism::CallNode) && call_names.include?(node.value.name)) ? node.name.to_s : nil
45
59
  end
46
60
 
47
61
  # Drops every cached parse. #for's only state; a fresh process would
@@ -25,6 +25,12 @@ module Hegel
25
25
  # #name_for's fallback when a draw has no better name (see below).
26
26
  DEFAULT_DRAW_NAME = "draw"
27
27
 
28
+ # The method names that reach #record_draw: #draw_integer, #draw_boolean,
29
+ # and #draw below. Hegel::DrawName.for takes this as an argument rather
30
+ # than knowing the list itself, so that class -- not DrawName -- stays
31
+ # the one place a fourth draw method needs to be added.
32
+ DRAW_METHOD_NAMES = [:draw, :draw_integer, :draw_boolean].freeze
33
+
28
34
  # Frames from #name_for's own caller_locations call up to the user's own
29
35
  # source line: #record_draw's call to #name_for (1), the public
30
36
  # draw_integer/draw_boolean/draw call to #record_draw (2), and the
@@ -517,7 +523,7 @@ module Hegel
517
523
  return label if label
518
524
 
519
525
  location = caller_locations(depth, 1)&.first
520
- (location && DrawName.for(location.path, location.lineno)) || DEFAULT_DRAW_NAME
526
+ (location && DrawName.for(location.path, location.lineno, DRAW_METHOD_NAMES)) || DEFAULT_DRAW_NAME
521
527
  end
522
528
  end
523
529
  end
data/lib/hegel/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hegel
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
data/sig/hegel.rbs CHANGED
@@ -17,6 +17,7 @@ module Hegel
17
17
 
18
18
  class TestCase
19
19
  DEFAULT_DRAW_NAME: String
20
+ DRAW_METHOD_NAMES: Array[Symbol]
20
21
  DRAW_CALLER_DEPTH: Integer
21
22
 
22
23
  def initialize: (untyped impl, untyped ctx, untyped handle, ?record: bool) -> void
@@ -326,7 +327,7 @@ module Hegel
326
327
  module DrawName
327
328
  ASSIGNMENT_NODE_TYPES: Array[untyped]
328
329
 
329
- def self.for: (String path, Integer lineno) -> String?
330
+ def self.for: (String path, Integer lineno, Array[Symbol] call_names) -> String?
330
331
  def self.reset_cache: () -> void
331
332
  def self.parse: (String path) -> untyped
332
333
  def self.cache: () -> Hash[String, untyped]
@@ -13,16 +13,18 @@
13
13
 
14
14
  ## Setup
15
15
 
16
- Hegel for Ruby is packaged as the `hegeltest` gem, which has not reached
17
- RubyGems.org yet. Installing it from git works for the Ruby code. A git
18
- checkout carries no `libhegel` engine, so a run also needs
19
- `HEGEL_LIBHEGEL_PATH` pointing at a local build:
16
+ Hegel for Ruby is packaged as the `hegeltest` gem. Each platform gem carries
17
+ the matching `libhegel` engine, so an install compiles nothing and needs no
18
+ engine on the side:
20
19
 
21
20
  ```ruby
22
21
  # Gemfile
23
- gem "hegeltest", git: "https://github.com/meganemura/hegel-ruby"
22
+ gem "hegeltest"
24
23
  ```
25
24
 
25
+ A platform with no published `libhegel` build, such as macOS on Intel, needs
26
+ `HEGEL_LIBHEGEL_PATH` pointing at a local build instead.
27
+
26
28
  Require it, then include the generator methods wherever tests draw values:
27
29
 
28
30
  ```ruby
@@ -127,7 +129,7 @@ end
127
129
 
128
130
  | Keyword | Type | Default | Purpose |
129
131
  |---|---|---|---|
130
- | `test_cases` | `Integer` or `nil` | `nil` (libhegel's own default) | Number of test cases to run |
132
+ | `test_cases` | `Integer` or `nil` | `nil` (libhegel's own default: 100) | Number of test cases to run |
131
133
  | `seed` | `Integer` or `nil` | `nil` (libhegel picks its own) | Fixed RNG seed; pair with `derandomize: true` for a reproducible sequence |
132
134
  | `derandomize` | `true`/`false` or `nil` | `nil` (libhegel's own default) | Derive the seed deterministically from the test itself, instead of drawing a random one |
133
135
  | `verbosity` | `Symbol` or `nil` | `nil` (libhegel's own default) | `:quiet`, `:normal`, `:verbose`, or `:debug` |
@@ -273,6 +275,22 @@ To reproduce this failure, pass the blob below to Hegel.test:
273
275
  reproduce_failure: "AAEAAAAACgEAAAAG"
274
276
  ```
275
277
 
278
+ An ordinary Ruby method can share a related group of draws. Use a descriptive
279
+ method parameter name so that the default RuboCop naming rule accepts it:
280
+
281
+ ```ruby
282
+ def draw_sorted_pair(test_case)
283
+ low = test_case.draw(integers(min_value: 0, max_value: 100))
284
+ high = test_case.draw(integers(min_value: low, max_value: 200))
285
+ [low, high]
286
+ end
287
+
288
+ Hegel.test do |tc|
289
+ low, high = draw_sorted_pair(tc)
290
+ raise "values are out of order" unless low <= high
291
+ end
292
+ ```
293
+
276
294
  `assume` discards a test case (the same way `reject` does) unless its
277
295
  condition holds, read as ordinary Ruby truthiness rather than restricted to
278
296
  `true`/`false`, so `tc.assume(hash[:key])` works directly:
@@ -450,6 +468,39 @@ min_size"`. `alphabet:`, `categories:`, `include_characters:`, and
450
468
  expose) are not available in this binding; `codec:`, `min_codepoint:`, and
451
469
  `max_codepoint:` are the alphabet controls it exposes today.
452
470
 
471
+ Other generators cover most character-set jobs. These results were measured
472
+ with libhegel 0.32.5 on this repository's main branch:
473
+
474
+ | Job | Generator | Measured output |
475
+ |---|---|---|
476
+ | Characters to include | `from_regex("[ぁ-んA-Z0-9]{1,5}", fullmatch: true)` | `"げLだづは"`, `"あぐA"` |
477
+ | Characters to exclude | `from_regex("[^,\\t\\n]{0,6}", fullmatch: true)` | `"Ë3ù*掆&"`, `"MßzæŜ\u0002"`; 30 draws contained no comma, tab, or newline |
478
+ | A contiguous block | `text(min_codepoint: 0x300, max_codepoint: 0x36F)` | Every character was in U+0300 through U+036F |
479
+ | An arbitrary alphabet | `arrays(sampled_from(%w[ß a İ]), max_size: 4).map(&:join)` | `"İaİß"`, `"ßßß"` |
480
+
481
+ The `categories:` option remains an open request. A category such as any `Lu`
482
+ or any `Mn` spans codepoint ranges that a codepoint bound cannot select. A
483
+ regular expression character class requires those ranges to be written out.
484
+ The `.filter` method is not a substitute. In a measured run of 50 test cases,
485
+ filtering `text` to `\p{Han}` produced no valid inputs. The engine filtered 50
486
+ inputs and reported this health check:
487
+
488
+ ```
489
+ FailedHealthCheck: FilterTooMuch — it looks like this test is filtering out
490
+ too many inputs. 50 inputs were filtered out by assume() while only 0 valid
491
+ inputs were generated. If this is expected, suppress the check with
492
+ suppress_health_check = [HealthCheck::FilterTooMuch].
493
+ ```
494
+
495
+ The engine writes that last sentence in its own naming. This binding takes
496
+ the same setting as `suppress_health_check: [:filter_too_much]`, listed in
497
+ [Settings](#settings).
498
+
499
+ Unconfigured `text` draws from a much wider Unicode range. In 200 draws of
500
+ `text(min_size: 1, max_size: 4)`, the results included emoji, private-use
501
+ characters, and control characters. The highest codepoint was U+10F11A. A
502
+ property that accepts any string needs no character-set options.
503
+
453
504
  ### `arrays(elements, min_size: 0, max_size: nil)`
454
505
 
455
506
  An `Array` of values from the `elements` generator, with `[min_size,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hegeltest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - meganemura
@@ -59,6 +59,7 @@ files:
59
59
  - docs/adr/0011-let-the-test-case-own-every-pool-drawn-from-it.md
60
60
  - docs/adr/0012-build-a-failure-origin-from-the-callers-own-frame.md
61
61
  - docs/adr/0013-bind-libhegel-through-the-ffi-gem.md
62
+ - docs/adr/0014-name-a-drawn-value-only-when-the-draw-is-the-whole-assigned-value.md
62
63
  - docs/architecture.md
63
64
  - lib/hegel.rb
64
65
  - lib/hegel/draw_name.rb