ruby_reactor 0.8.3 → 0.8.5

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.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.release-please-manifest.json +1 -1
  3. data/.specify/feature.json +1 -1
  4. data/CHANGELOG.md +208 -0
  5. data/CLAUDE.md +1 -1
  6. data/README.md +140 -102
  7. data/lib/ruby_reactor/dsl/async_macros.rb +30 -1
  8. data/lib/ruby_reactor/dsl/async_reactor_builder.rb +10 -7
  9. data/lib/ruby_reactor/dsl/compose_builder.rb +10 -11
  10. data/lib/ruby_reactor/dsl/interrupt_builder.rb +1 -3
  11. data/lib/ruby_reactor/dsl/map_builder.rb +0 -2
  12. data/lib/ruby_reactor/dsl/reactor.rb +8 -11
  13. data/lib/ruby_reactor/dsl/retryable.rb +45 -0
  14. data/lib/ruby_reactor/dsl/step_builder.rb +131 -33
  15. data/lib/ruby_reactor/error/argument_resolution_error.rb +19 -0
  16. data/lib/ruby_reactor/error/rescuable.rb +28 -0
  17. data/lib/ruby_reactor/error/undeclared_input_error.rb +13 -0
  18. data/lib/ruby_reactor/executor/compensation_manager.rb +30 -26
  19. data/lib/ruby_reactor/executor/result_handler.rb +21 -18
  20. data/lib/ruby_reactor/executor/retry_manager.rb +11 -12
  21. data/lib/ruby_reactor/executor/step_coordination.rb +11 -8
  22. data/lib/ruby_reactor/executor/step_executor.rb +59 -49
  23. data/lib/ruby_reactor/executor.rb +38 -4
  24. data/lib/ruby_reactor/map/collector.rb +21 -11
  25. data/lib/ruby_reactor/map/dispatcher.rb +29 -3
  26. data/lib/ruby_reactor/map/element_executor.rb +9 -3
  27. data/lib/ruby_reactor/map/helpers.rb +32 -2
  28. data/lib/ruby_reactor/map/result_enumerator.rb +18 -12
  29. data/lib/ruby_reactor/reactor.rb +24 -0
  30. data/lib/ruby_reactor/rspec/matchers.rb +19 -3
  31. data/lib/ruby_reactor/rspec/test_subject.rb +3 -5
  32. data/lib/ruby_reactor/step/async_reactor_step.rb +6 -2
  33. data/lib/ruby_reactor/step/compose_step.rb +14 -4
  34. data/lib/ruby_reactor/step/input_contract.rb +5 -0
  35. data/lib/ruby_reactor/step/inputs.rb +57 -0
  36. data/lib/ruby_reactor/step/map_step.rb +140 -25
  37. data/lib/ruby_reactor/step.rb +20 -7
  38. data/lib/ruby_reactor/step_worker.rb +46 -22
  39. data/lib/ruby_reactor/storage/adapter.rb +4 -0
  40. data/lib/ruby_reactor/storage/redis_adapter.rb +9 -0
  41. data/lib/ruby_reactor/storage/redis_reactor_scan.rb +1 -1
  42. data/lib/ruby_reactor/version.rb +1 -1
  43. data/lib/ruby_reactor/web/api.rb +1 -1
  44. data/lib/ruby_reactor/web/public/assets/{index-CeZU-ESu.js → index-CQbgHtd0.js} +10 -10
  45. data/lib/ruby_reactor/web/public/index.html +1 -1
  46. data/lib/ruby_reactor/worker.rb +3 -1
  47. data/lib/ruby_reactor.rb +20 -7
  48. data/specs/006-step-retry-declarations/checklists/requirements.md +41 -0
  49. data/specs/006-step-retry-declarations/contracts/dsl-surface.md +89 -0
  50. data/specs/006-step-retry-declarations/data-model.md +58 -0
  51. data/specs/006-step-retry-declarations/plan.md +187 -0
  52. data/specs/006-step-retry-declarations/quickstart.md +80 -0
  53. data/specs/006-step-retry-declarations/research.md +194 -0
  54. data/specs/006-step-retry-declarations/spec.md +453 -0
  55. data/specs/006-step-retry-declarations/tasks.md +382 -0
  56. data/specs/007-execution-flow-analysis/analysis/README.md +147 -0
  57. data/specs/007-execution-flow-analysis/analysis/execution-order.md +359 -0
  58. data/specs/007-execution-flow-analysis/analysis/findings-and-options.md +502 -0
  59. data/specs/007-execution-flow-analysis/analysis/invariants.md +109 -0
  60. data/specs/007-execution-flow-analysis/checklists/requirements.md +39 -0
  61. data/specs/007-execution-flow-analysis/contracts/report-structure.md +71 -0
  62. data/specs/007-execution-flow-analysis/data-model.md +83 -0
  63. data/specs/007-execution-flow-analysis/evidence/harness.rb +229 -0
  64. data/specs/007-execution-flow-analysis/evidence/output.txt +333 -0
  65. data/specs/007-execution-flow-analysis/evidence/probes/01_plain.rb +122 -0
  66. data/specs/007-execution-flow-analysis/evidence/probes/02_compose.rb +182 -0
  67. data/specs/007-execution-flow-analysis/evidence/probes/03_map.rb +232 -0
  68. data/specs/007-execution-flow-analysis/evidence/probes/04_async.rb +132 -0
  69. data/specs/007-execution-flow-analysis/evidence/probes/05_background.rb +58 -0
  70. data/specs/007-execution-flow-analysis/evidence/probes/06_coordination.rb +158 -0
  71. data/specs/007-execution-flow-analysis/evidence/probes/07_interrupts_manual.rb +185 -0
  72. data/specs/007-execution-flow-analysis/evidence/run.rb +15 -0
  73. data/specs/007-execution-flow-analysis/plan.md +127 -0
  74. data/specs/007-execution-flow-analysis/quickstart.md +51 -0
  75. data/specs/007-execution-flow-analysis/research.md +202 -0
  76. data/specs/007-execution-flow-analysis/spec.md +270 -0
  77. data/specs/007-execution-flow-analysis/tasks.md +257 -0
  78. data/specs/008-rollback-reliability/checklists/requirements.md +43 -0
  79. data/specs/008-rollback-reliability/contracts/api-surface.md +126 -0
  80. data/specs/008-rollback-reliability/contracts/rollback-semantics.md +76 -0
  81. data/specs/008-rollback-reliability/data-model.md +139 -0
  82. data/specs/008-rollback-reliability/plan.md +233 -0
  83. data/specs/008-rollback-reliability/quickstart.md +105 -0
  84. data/specs/008-rollback-reliability/research.md +653 -0
  85. data/specs/008-rollback-reliability/spec.md +561 -0
  86. data/specs/008-rollback-reliability/tasks.md +1110 -0
  87. data/specs/future_improvements.md +48 -0
  88. data/specs/specs-inputs-by-method-md-piped-wigderson.md +77 -0
  89. metadata +47 -2
@@ -248,3 +248,51 @@ Direction:
248
248
 
249
249
  Spec: compose → fan-out map, with and without a park after the map. The root completes either
250
250
  way.
251
+
252
+ ## Rollback follow-ups (008)
253
+
254
+ Raised while implementing specs/008-rollback-reliability. None blocks it.
255
+
256
+ - **Sweeper re-enqueues in-progress inline runs.** `RubyReactor::Sweeper` re-enqueues any
257
+ top-level context that is `running` with no `async:` lock. A run still executing in the
258
+ caller's process never holds that lock, so a sweep during it enqueues a worker that resumes the
259
+ same run forward. Pre-existing; 008 only keeps `aborted` runs out of it. Direction: mark
260
+ caller-process runs (the `inline_async_execution` inverse) so the sweeper skips them until they
261
+ are stale by a timestamp, or give them their own liveness lock.
262
+ - **Map-level `undo_all` override.** Map rollback always replays each element's own step `undo`s.
263
+ A bulk refund API may want one call for all elements instead. Direction: an optional
264
+ `undo_all { |completed_results| ... }` on `map` that replaces the per-element replay.
265
+ - **Rollback fan-out for very large maps.** Map rollback is serial, in the process that detected
266
+ the failure, so its time is linear in the number of completed elements (10,000 elements take
267
+ about a minute in the test suite). Direction: enqueue one rollback job per element (or per
268
+ batch) and resolve the parent's failure once they report back.
269
+ - **A resume for a second pending interrupt while the first is executing.** A reactor paused at
270
+ several ready interrupts takes their resumes one at a time: each accepted resume marks the run
271
+ `running` (008 FR-032), and the run pauses again at the interrupts still pending. A resume that
272
+ arrives for another pending interrupt while the first resume is still executing is rejected
273
+ ("the reactor is running"). Interrupt steps have no body, so that window is short, but a caller
274
+ resuming two interrupts at once can hit it. Direction: accept it for an interrupt that has not
275
+ executed yet (store its payload and let the running resume pick it up), or return a retryable
276
+ error.
277
+ - **An interrupted `compensate` of the failing step is not re-run.** An interruption (signal, exit,
278
+ out of memory) during the failing step's own `compensate` leaves the run `aborted`. A manual
279
+ `Reactor.undo(id)` undoes the completed steps but never re-runs that `compensate`, so the step
280
+ can stay half-compensated. Pre-existing (008 R-08). Direction: record the failing step on the
281
+ aborted run and have manual undo re-run its `compensate` before the undo stack.
282
+ - **Recover a resume contended on a lock.** An inline `continue` that cannot take the reactor's
283
+ `with_lock` or `with_semaphore` raises its `AcquisitionError` and leaves the run `paused`; the
284
+ caller has to retry it (008 review, 2026-09-30). A webhook sender that does not retry loses the
285
+ resume. Direction:
286
+ - Validate the payload first, synchronously in the calling process, as `resume: :background`
287
+ does today. An invalid payload returns its validation failure to the caller (the webhook),
288
+ and nothing is stored or enqueued.
289
+ - Only a valid payload is stored and handed off. On contention, mark the run `running` and give
290
+ the resume to a worker. The worker snoozes on the contended lock without spending retries and
291
+ resumes once the lock is free. The deferred resume never re-validates the payload, so it
292
+ cannot fail on validation after the caller was told it was accepted.
293
+ - `continue` returns a `DispatchResult` instead of raising, and a second `continue` is rejected
294
+ as for any running resume.
295
+ - **Two resumes in the same instant.** Two `continue` calls that both read `paused` before either
296
+ saves `running` are separated only by the per-run context lock, which inline Sidekiq testing
297
+ skips. Accepted for now (008 review, 2026-09-27). Direction: claim the resume with an atomic
298
+ status compare-and-set.
@@ -0,0 +1,77 @@
1
+ # Plan: `inputs.order_id` (implement specs/inputs_by_method.md)
2
+
3
+ ## Context
4
+
5
+ `Step#inputs` is a plain Hash, so a typo like `inputs[:order_id]` (declared `:order_guid`) returns `nil` and blows up later, far from the bug — worst in `undo`/`compensate`, which skip validation. The design doc (`specs/inputs_by_method.md`) decides: step code reads inputs through a frozen read-only `Step::Inputs` object (`inputs.order_id`); any unreadable name raises `Error::UndeclaredInputError` naming the step and its declared inputs. No `[]`, no shim — every call site migrates in the same change (`feat!`). This plan implements that doc as written; deviations/additions found while reading the code are marked **(new)**.
6
+
7
+ Branch: `inputs_by_method` off `main`. Test-first (Constitution III): new specs first, then lib, then migration.
8
+
9
+ **Step 0 (on approval):** copy this plan to `specs/inputs_by_method_plan.md` (next to the design doc) and stop there. Implementation starts only when asked.
10
+
11
+ ## 1. New code (lib)
12
+
13
+ **`lib/ruby_reactor/step/inputs.rb`** — `RubyReactor::Step::Inputs` (Zeitwerk picks it up).
14
+ - `initialize(values, contract: nil, owner:)`: `@values = values.to_h` (so passing an `Inputs` or nil is safe), readable `@names` = `contract.declarations.keys` when the contract has declarations, else `@values.keys.map(&:to_sym)` **(new: a contract with only `validate_inputs` and no `input` falls back to present keys instead of making everything unreadable)**; `@redacted = contract&.redacted_names || []`; `freeze`.
15
+ - `method_missing(name, *args)`: readable name and no args → `Utils::FetchIndifferent.call(@values, name)`; else raise `UndeclaredInputError`. `respond_to_missing?` → `@names.include?(name) || super`.
16
+ - `to_h` → supplied readable names only, symbol keys, via FetchIndifferent (key present as sym or string). `alias to_hash to_h`.
17
+ - `inspect` → `to_h` with redacted names replaced by `InputContract::REDACTED`.
18
+
19
+ **`lib/ruby_reactor/error/undeclared_input_error.rb`** — `< NoMethodError`, `def retryable? = false`. Message: `"#{owner} has no input :#{name}. Declared inputs: :a, :b."` (`none` when empty). Retry path already honours it: `Failure#retryable?` (`lib/ruby_reactor.rb:167`) and `StepFailureError#retryable?` ask the error.
20
+
21
+ **Reserved names** — `InputContract#input` (`lib/ruby_reactor/step/input_contract.rb:25`): raise `Error::ValidationError` when `Step::Inputs.public_method_defined?(name)`. Checked all 141 input names in spec/demo_app/docs: no clashes.
22
+
23
+ ## 2. Injection points (the only places the object is built)
24
+
25
+ | Where | Change |
26
+ |---|---|
27
+ | `Step#initialize` (`lib/ruby_reactor/step.rb:44`) | `@inputs = Inputs.new(inputs, contract: (self.class.input_contract if self.class.declares_inputs?), owner: self.class.name)`. Covers `.run`/`.undo`/`.compensate`. Update header comment example (`step.rb:8`). |
28
+ | `Step.enforce_contract!` / `with_defaults` (`step.rb:168-179`) | **(new)** `arguments.to_h` first, so a documented nested call `OtherStep.run(inputs, context)` from a step body, and TestSubject's `original` callable, still hand the contract a Hash. |
29
+ | `StepConfig` (`lib/ruby_reactor/dsl/step_builder.rb`) | Add `def wrap_inputs(arguments) = Step::Inputs.new(arguments, contract: input_contract, owner: "step :#{name}")`. |
30
+ | `StepConfig#call_body` (`step_builder.rb:367`) | `run_block.call(wrap_inputs(arguments), context)`. Duck-typed `impl.run` (line 372) unchanged. |
31
+ | `CompensationManager#compensate_step` / `#undo_step` (`lib/ruby_reactor/executor/compensation_manager.rb:126,171`) | Wrap `arguments` with `step_config.wrap_inputs` before the inline block call only. |
32
+ | `TestSubject#original_impl_for` duck-impl lambda (`lib/ruby_reactor/rspec/test_subject.rb:772`) | **(new)** `impl.run(args.to_h, ctx)`. Mock blocks replace `@run_block`, so they receive `Inputs` like the body they stand in for — the `Step` path is covered by the `to_h` above. |
33
+
34
+ ## 3. Returning inputs from a step
35
+
36
+ - `RubyReactor.Success` (`lib/ruby_reactor.rb:391`): `Success.new(value.is_a?(Step::Inputs) ? value.to_h : value)`.
37
+ - `ResultHandler#handle_unknown_result` (`lib/ruby_reactor/executor/result_handler.rb:192`): build `success_result` first, then `validate_step_output` on `success_result.value`, **and (new) `@context.set_result(..., success_result.value)`** — the doc's swap alone would still store the raw `Inputs` in context.
38
+
39
+ ## 4. Built-in steps
40
+
41
+ Per the doc, `MapStep`, `ComposeStep`, `AsyncReactorStep` declare their keys (`input :source`, `input :fan_out, optional: true`, …, untyped → no validator, `enforce!` is a no-op) and switch `inputs[:x]` → `inputs.x` (31 sites). `fail_fast: inputs.fail_fast.nil? || inputs.fail_fast` stays.
42
+ - **(new)** drop `inputs[:step_name] ||` in `map_step.rb:193`: `step_name` is never wired, and once declared, `validate_definition!` would wire it by name from a reactor input called `:step_name`.
43
+
44
+ ## 5. Migration (no shim)
45
+
46
+ Counts: `inputs[` — spec 131, docs 49, README 10, demo_app 44; `args[` — spec 378, docs 157, README 54, demo_app 414 (most in inline blocks).
47
+ - Step bodies only (class `run`/`undo`/`compensate`, inline `run`/`undo`/`compensate` blocks, TestSubject mock blocks): `x[:k]` → `x.k`. Hand edits, not a global replace — lock/semaphore/rate-limit key procs, `validate_inputs`, `where`/`guard`, `transform:` procs stay Hashes.
48
+ - Other Hash use on inputs (`each`, `slice`, `eq(hash)` in specs) → `.to_h`. `**inputs`, `merge(inputs)`, `Success(inputs)` keep working.
49
+ - Docs/README/`demo_app/documentation`: rename inline block param `args` → `inputs`; `documentation/core_concepts.md` step-inputs section documents reader API, `UndeclaredInputError`, reserved names, `to_h`/`**`, `Success(inputs)` conversion (nested not converted).
50
+ - Order: lib → `spec/` → `demo_app/` → docs/README.
51
+
52
+ **Silent-pass trap:** a spec that expects a step to fail still passes if an unmigrated `[]` now fails it for a different reason. So grep is the driver and the suite is the net, not the other way round.
53
+
54
+ ## 6. Demo (Constitution VI)
55
+
56
+ Via `/speckit-demo-tests`: `demo_app/app/reactors/undeclared_input_demo_reactor.rb` (step reads a typo'd input), `demo:undeclared_input` in `demo_app/lib/tasks/demo_reactors.rake`, `demo_app/spec/reactors/undeclared_input_demo_reactor_spec.rb` asserting failure with `UndeclaredInputError` and one attempt despite `retries`.
57
+
58
+ ## 7. Tests (written first)
59
+
60
+ `spec/ruby_reactor/step/inputs_spec.rb`:
61
+ - reader returns value; declared-optional absent → `nil`; `false` stays `false`; string-keyed hash readable.
62
+ - undeclared name raises `UndeclaredInputError` with exact message; `respond_to?`; clash with private Kernel name (`select`) as a declared input reads fine.
63
+ - contract-less step reads present keys only; unwired inline step with `inputs do` reads only declared.
64
+ - `to_h` omits unsupplied optionals; `**inputs`; `inspect` redacts; frozen, no `[]`.
65
+ - `input :method` → `ValidationError` at class definition.
66
+ - class `undo`/`compensate` and inline `run`/`undo`/`compensate` blocks receive `Inputs`; typo in `compensate` surfaces as rollback failure naming the input.
67
+ - step with `retries max_attempts: 3` + typo → one attempt.
68
+ - `Success(inputs)` sync (`result(:step, :x)` works) and async round trip (Hash, not a string); bare `run { |inputs| inputs }` stored/validated as Hash.
69
+ - nested `OtherStep.run(inputs, context)` from a step body works; TestSubject `mock_step` with `original.call(args, ctx)` on a class step works.
70
+
71
+ ## Verification
72
+
73
+ 1. `bundle exec rspec` (real Redis) green; rerun flaky async specs alone before chasing them.
74
+ 2. `cd demo_app && bundle exec rspec` green; `bin/rails demo:undeclared_input` shows the error.
75
+ 3. `bundle exec rubocop` clean.
76
+ 4. Residual audit: `grep -rnE 'inputs\[|\bargs\[' lib spec demo_app documentation README.md` — every remaining hit is a Hash context (key procs, validators, `where`/`guard`, reactor DSL `inputs[name]` in `dsl/reactor.rb`).
77
+ 5. Commit as `feat!:` with a migration note (`inputs[:x]` → `inputs.x`, Hash methods → `inputs.to_h`).
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_reactor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.3
4
+ version: 0.8.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Artur
@@ -165,9 +165,11 @@ files:
165
165
  - lib/ruby_reactor/dsl/lockable.rb
166
166
  - lib/ruby_reactor/dsl/map_builder.rb
167
167
  - lib/ruby_reactor/dsl/reactor.rb
168
+ - lib/ruby_reactor/dsl/retryable.rb
168
169
  - lib/ruby_reactor/dsl/step_builder.rb
169
170
  - lib/ruby_reactor/dsl/template_helpers.rb
170
171
  - lib/ruby_reactor/dsl/validation_helpers.rb
172
+ - lib/ruby_reactor/error/argument_resolution_error.rb
171
173
  - lib/ruby_reactor/error/async_result_pending.rb
172
174
  - lib/ruby_reactor/error/async_wait_timeout_error.rb
173
175
  - lib/ruby_reactor/error/base.rb
@@ -179,9 +181,11 @@ files:
179
181
  - lib/ruby_reactor/error/execution_parked.rb
180
182
  - lib/ruby_reactor/error/input_validation_error.rb
181
183
  - lib/ruby_reactor/error/reactor_contention_park.rb
184
+ - lib/ruby_reactor/error/rescuable.rb
182
185
  - lib/ruby_reactor/error/schema_version_error.rb
183
186
  - lib/ruby_reactor/error/step_contention_park.rb
184
187
  - lib/ruby_reactor/error/step_failure_error.rb
188
+ - lib/ruby_reactor/error/undeclared_input_error.rb
185
189
  - lib/ruby_reactor/error/undo_error.rb
186
190
  - lib/ruby_reactor/error/validation_error.rb
187
191
  - lib/ruby_reactor/executor.rb
@@ -229,6 +233,7 @@ files:
229
233
  - lib/ruby_reactor/step/async_reactor_step.rb
230
234
  - lib/ruby_reactor/step/compose_step.rb
231
235
  - lib/ruby_reactor/step/input_contract.rb
236
+ - lib/ruby_reactor/step/inputs.rb
232
237
  - lib/ruby_reactor/step/map_step.rb
233
238
  - lib/ruby_reactor/step_signals.rb
234
239
  - lib/ruby_reactor/step_sweeper.rb
@@ -261,15 +266,55 @@ files:
261
266
  - lib/ruby_reactor/web/config.ru
262
267
  - lib/ruby_reactor/web/coordination_serializer.rb
263
268
  - lib/ruby_reactor/web/public/assets/index-BQvIWPdx.css
264
- - lib/ruby_reactor/web/public/assets/index-CeZU-ESu.js
269
+ - lib/ruby_reactor/web/public/assets/index-CQbgHtd0.js
265
270
  - lib/ruby_reactor/web/public/index.html
266
271
  - lib/ruby_reactor/web/public/vite.svg
267
272
  - lib/ruby_reactor/worker.rb
268
273
  - llms-full.txt
269
274
  - llms.txt
270
275
  - sig/ruby_reactor.rbs
276
+ - specs/006-step-retry-declarations/checklists/requirements.md
277
+ - specs/006-step-retry-declarations/contracts/dsl-surface.md
278
+ - specs/006-step-retry-declarations/data-model.md
279
+ - specs/006-step-retry-declarations/plan.md
280
+ - specs/006-step-retry-declarations/quickstart.md
281
+ - specs/006-step-retry-declarations/research.md
282
+ - specs/006-step-retry-declarations/spec.md
283
+ - specs/006-step-retry-declarations/tasks.md
284
+ - specs/007-execution-flow-analysis/analysis/README.md
285
+ - specs/007-execution-flow-analysis/analysis/execution-order.md
286
+ - specs/007-execution-flow-analysis/analysis/findings-and-options.md
287
+ - specs/007-execution-flow-analysis/analysis/invariants.md
288
+ - specs/007-execution-flow-analysis/checklists/requirements.md
289
+ - specs/007-execution-flow-analysis/contracts/report-structure.md
290
+ - specs/007-execution-flow-analysis/data-model.md
291
+ - specs/007-execution-flow-analysis/evidence/harness.rb
292
+ - specs/007-execution-flow-analysis/evidence/output.txt
293
+ - specs/007-execution-flow-analysis/evidence/probes/01_plain.rb
294
+ - specs/007-execution-flow-analysis/evidence/probes/02_compose.rb
295
+ - specs/007-execution-flow-analysis/evidence/probes/03_map.rb
296
+ - specs/007-execution-flow-analysis/evidence/probes/04_async.rb
297
+ - specs/007-execution-flow-analysis/evidence/probes/05_background.rb
298
+ - specs/007-execution-flow-analysis/evidence/probes/06_coordination.rb
299
+ - specs/007-execution-flow-analysis/evidence/probes/07_interrupts_manual.rb
300
+ - specs/007-execution-flow-analysis/evidence/run.rb
301
+ - specs/007-execution-flow-analysis/plan.md
302
+ - specs/007-execution-flow-analysis/quickstart.md
303
+ - specs/007-execution-flow-analysis/research.md
304
+ - specs/007-execution-flow-analysis/spec.md
305
+ - specs/007-execution-flow-analysis/tasks.md
306
+ - specs/008-rollback-reliability/checklists/requirements.md
307
+ - specs/008-rollback-reliability/contracts/api-surface.md
308
+ - specs/008-rollback-reliability/contracts/rollback-semantics.md
309
+ - specs/008-rollback-reliability/data-model.md
310
+ - specs/008-rollback-reliability/plan.md
311
+ - specs/008-rollback-reliability/quickstart.md
312
+ - specs/008-rollback-reliability/research.md
313
+ - specs/008-rollback-reliability/spec.md
314
+ - specs/008-rollback-reliability/tasks.md
271
315
  - specs/future_improvements.md
272
316
  - specs/scoped_rspec_matchers.md
317
+ - specs/specs-inputs-by-method-md-piped-wigderson.md
273
318
  - teley/Dockerfile
274
319
  homepage: https://github.com/arturictus/ruby_reactor
275
320
  licenses: []