rooibos 0.5.0 → 0.6.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.
Files changed (171) hide show
  1. checksums.yaml +4 -4
  2. data/.builds/ruby-3.2.yml +9 -5
  3. data/.builds/ruby-3.3.yml +9 -5
  4. data/.builds/ruby-3.4.yml +9 -5
  5. data/.builds/ruby-4.0.0.yml +9 -5
  6. data/AGENTS.md +1 -1
  7. data/CHANGELOG.md +57 -0
  8. data/README.md +2 -2
  9. data/README.rdoc +374 -0
  10. data/REUSE.toml +5 -0
  11. data/Rakefile +1 -1
  12. data/doc/best_practices/forms_and_validation.md +20 -0
  13. data/doc/best_practices/http_workflows.md +20 -0
  14. data/doc/best_practices/index.md +26 -0
  15. data/doc/best_practices/lists_and_tables.md +20 -0
  16. data/doc/best_practices/modal_dialogs.md +20 -0
  17. data/doc/best_practices/no_stateful_widgets.md +184 -0
  18. data/doc/best_practices/orchestration.md +20 -0
  19. data/doc/best_practices/streaming_data.md +20 -0
  20. data/doc/contributors/design/commands_and_outlets.md +1 -1
  21. data/doc/contributors/documentation_plan.md +616 -0
  22. data/doc/contributors/documentation_stub_audit.md +112 -0
  23. data/doc/contributors/documentation_style.md +275 -0
  24. data/doc/contributors/e2e_pty.md +168 -0
  25. data/doc/contributors/specs/earliest_tutorial_steps_per_story.md +70 -0
  26. data/doc/contributors/specs/file_browser.md +789 -0
  27. data/doc/contributors/specs/file_browser_stories.md +774 -0
  28. data/doc/contributors/specs/tutorials_to_stories.rb +167 -0
  29. data/doc/contributors/todo/scrollbar.md +118 -0
  30. data/doc/contributors/tutorial_old/01_project_setup.md +20 -0
  31. data/doc/contributors/tutorial_old/02_hello_world.md +24 -0
  32. data/doc/contributors/tutorial_old/03_adding_state.md +26 -0
  33. data/doc/contributors/tutorial_old/06_organizing_your_code.md +20 -0
  34. data/doc/contributors/tutorial_old/07_your_first_command.md +21 -0
  35. data/doc/contributors/tutorial_old/08_the_preview_pane.md +20 -0
  36. data/doc/contributors/tutorial_old/09_loading_states.md +20 -0
  37. data/doc/contributors/tutorial_old/10_testing_your_app.md +20 -0
  38. data/doc/contributors/tutorial_old/11_polish_and_refine.md +20 -0
  39. data/doc/contributors/tutorial_old/12_going_further.md +20 -0
  40. data/doc/contributors/tutorial_old/index.md +20 -0
  41. data/doc/essentials/commands.md +20 -0
  42. data/doc/essentials/index.md +31 -0
  43. data/doc/essentials/messages.md +21 -0
  44. data/doc/essentials/models.md +21 -0
  45. data/doc/essentials/shortcuts.md +19 -0
  46. data/doc/essentials/the_elm_architecture.md +24 -0
  47. data/doc/essentials/the_runtime.md +21 -0
  48. data/doc/essentials/update_functions.md +20 -0
  49. data/doc/essentials/views.md +22 -0
  50. data/doc/getting_started/for_go_developers.md +16 -0
  51. data/doc/getting_started/for_python_developers.md +16 -0
  52. data/doc/getting_started/for_rails_developers.md +17 -0
  53. data/doc/getting_started/for_ratatui_ruby_developers.md +17 -0
  54. data/doc/getting_started/for_react_developers.md +17 -0
  55. data/doc/getting_started/index.md +52 -0
  56. data/doc/getting_started/install.md +20 -0
  57. data/doc/getting_started/quickstart.md +9 -45
  58. data/doc/getting_started/ruby_primer.md +19 -0
  59. data/doc/getting_started/why_rooibos.md +20 -0
  60. data/doc/index.md +79 -11
  61. data/doc/scaling_up/async_patterns.md +20 -0
  62. data/doc/scaling_up/command_composition.md +20 -0
  63. data/doc/scaling_up/custom_commands.md +21 -0
  64. data/doc/scaling_up/fractal_architecture.md +20 -0
  65. data/doc/scaling_up/index.md +30 -0
  66. data/doc/scaling_up/message_routing.md +20 -0
  67. data/doc/scaling_up/ractor_safety.md +20 -0
  68. data/doc/scaling_up/testing.md +21 -0
  69. data/doc/troubleshooting/common_errors.md +20 -0
  70. data/doc/troubleshooting/debugging.md +21 -0
  71. data/doc/troubleshooting/index.md +23 -0
  72. data/doc/troubleshooting/performance.md +20 -0
  73. data/doc/tutorial/01_project_setup.md +44 -0
  74. data/doc/tutorial/02_hello_world.md +45 -0
  75. data/doc/tutorial/03_static_file_list.md +44 -0
  76. data/doc/tutorial/04_arrow_navigation.md +47 -0
  77. data/doc/tutorial/05_real_files.md +45 -0
  78. data/doc/tutorial/06_safe_refactoring.md +21 -0
  79. data/doc/tutorial/07_red_first_tdd.md +26 -0
  80. data/doc/tutorial/08_file_metadata.md +42 -0
  81. data/doc/tutorial/09_text_preview.md +44 -0
  82. data/doc/tutorial/10_directory_tree.md +42 -0
  83. data/doc/tutorial/11_pane_focus.md +40 -0
  84. data/doc/tutorial/12_sorting.md +41 -0
  85. data/doc/tutorial/13_filtering.md +43 -0
  86. data/doc/tutorial/14_toggle_hidden.md +41 -0
  87. data/doc/tutorial/15_text_input_widget.md +43 -0
  88. data/doc/tutorial/16_rename_files.md +42 -0
  89. data/doc/tutorial/17_confirmation_dialogs.md +43 -0
  90. data/doc/tutorial/18_progress_indicators.md +43 -0
  91. data/doc/tutorial/19_atomic_operations.md +42 -0
  92. data/doc/tutorial/20_external_editor.md +42 -0
  93. data/doc/tutorial/21_modal_overlays.md +41 -0
  94. data/doc/tutorial/22_error_handling.md +43 -0
  95. data/doc/tutorial/23_terminal_capabilities.md +53 -0
  96. data/doc/tutorial/24_mouse_events.md +43 -0
  97. data/doc/tutorial/25_resize_events.md +43 -0
  98. data/doc/tutorial/26_loading_states.md +42 -0
  99. data/doc/tutorial/27_performance.md +43 -0
  100. data/doc/tutorial/28_color_schemes.md +47 -0
  101. data/doc/tutorial/29_configuration.md +124 -0
  102. data/doc/tutorial/30_going_further.md +17 -0
  103. data/doc/tutorial/index.md +17 -0
  104. data/examples/app_file_browser/app.rb +40 -0
  105. data/examples/app_fractal_dashboard/dashboard/update_manual.rb +7 -7
  106. data/examples/app_fractal_dashboard/fragments/custom_shell_input.rb +5 -5
  107. data/examples/app_fractal_dashboard/fragments/custom_shell_modal.rb +1 -1
  108. data/examples/app_fractal_dashboard/fragments/disk_usage.rb +2 -2
  109. data/examples/app_fractal_dashboard/fragments/network_panel.rb +4 -4
  110. data/examples/app_fractal_dashboard/fragments/ping.rb +2 -2
  111. data/examples/app_fractal_dashboard/fragments/stats_panel.rb +4 -4
  112. data/examples/app_fractal_dashboard/fragments/system_info.rb +2 -2
  113. data/examples/app_fractal_dashboard/fragments/uptime.rb +2 -2
  114. data/examples/verify_website_first_app/app.rb +85 -0
  115. data/examples/verify_website_hello_mvu/app.rb +31 -0
  116. data/examples/widget_command_system/app.rb +15 -13
  117. data/exe/rooibos +10 -0
  118. data/generate_tutorial_stubs.rb +126 -0
  119. data/lib/rooibos/cli/commands/new.rb +373 -0
  120. data/lib/rooibos/cli/commands/run.rb +98 -0
  121. data/lib/rooibos/cli.rb +78 -0
  122. data/lib/rooibos/command/all.rb +76 -23
  123. data/lib/rooibos/command/batch.rb +61 -34
  124. data/lib/rooibos/command/custom.rb +84 -1
  125. data/lib/rooibos/command/http.rb +121 -55
  126. data/lib/rooibos/command/lifecycle.rb +5 -5
  127. data/lib/rooibos/command/open.rb +93 -0
  128. data/lib/rooibos/command/outlet.rb +105 -3
  129. data/lib/rooibos/command/wait.rb +9 -6
  130. data/lib/rooibos/command.rb +114 -89
  131. data/lib/rooibos/message/batch.rb +39 -0
  132. data/lib/rooibos/message/canceled.rb +51 -0
  133. data/lib/rooibos/message/error.rb +48 -0
  134. data/lib/rooibos/message/open.rb +30 -0
  135. data/lib/rooibos/message.rb +84 -4
  136. data/lib/rooibos/router.rb +11 -14
  137. data/lib/rooibos/runtime.rb +40 -43
  138. data/lib/rooibos/shortcuts.rb +47 -0
  139. data/lib/rooibos/test_helper.rb +71 -6
  140. data/lib/rooibos/version.rb +1 -1
  141. data/lib/rooibos/welcome.rb +237 -0
  142. data/lib/rooibos.rb +4 -3
  143. data/mise.toml +1 -1
  144. data/rbs_collection.lock.yaml +2 -2
  145. data/sig/concurrent.rbs +4 -0
  146. data/sig/gem.rbs +20 -0
  147. data/sig/rooibos/cli.rbs +42 -0
  148. data/sig/rooibos/command.rbs +59 -7
  149. data/sig/rooibos/message.rbs +66 -2
  150. data/sig/rooibos/shortcuts.rbs +14 -0
  151. data/sig/rooibos/test_helper.rbs +6 -2
  152. data/sig/rooibos/welcome.rbs +75 -0
  153. data/tasks/install.rake +29 -0
  154. data/tasks/resources/build.yml.erb +2 -0
  155. metadata +274 -38
  156. data/doc/concepts/application_architecture.md +0 -197
  157. data/doc/concepts/application_testing.md +0 -49
  158. data/doc/concepts/async_work.md +0 -164
  159. data/doc/concepts/commands.md +0 -530
  160. data/doc/concepts/message_processing.md +0 -51
  161. data/doc/contributors/WIP/decomposition_strategies_analysis.md +0 -258
  162. data/doc/contributors/WIP/implementation_plan.md +0 -409
  163. data/doc/contributors/WIP/init_callable_proposal.md +0 -344
  164. data/doc/contributors/WIP/runtime_refactoring_status.md +0 -47
  165. data/doc/contributors/WIP/task.md +0 -36
  166. data/doc/contributors/WIP/v0.4.0_todo.md +0 -468
  167. data/doc/contributors/kit-no-outlet.md +0 -238
  168. data/doc/contributors/priorities.md +0 -38
  169. data/doc/images/.gitkeep +0 -0
  170. data/exe/.gitkeep +0 -0
  171. /data/doc/contributors/{WIP → design}/mvu_tea_implementations_research.md +0 -0
@@ -0,0 +1,20 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
+ -->
5
+
6
+ # Forms and Validation
7
+
8
+
9
+ By the end of this guide, you will:
10
+
11
+ - Collect multi-field user input in your Model
12
+ - Validate input and store error messages
13
+ - Display inline validation feedback
14
+ - Submit form data via Commands
15
+
16
+ > ⚠️ **This page is a stub.** Help us write it! See the [Documentation Plan](../contributors/documentation_plan.md) and [Style Guide](../contributors/documentation_style.md).
17
+
18
+ ---
19
+
20
+ **Best Practices:** [Modal Dialogs](./modal_dialogs.md) | [Lists and Tables](./lists_and_tables.md) | [HTTP Workflows](./http_workflows.md) | [Streaming Data](./streaming_data.md) | [Orchestration](./orchestration.md)
@@ -0,0 +1,20 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
+ -->
5
+
6
+ # HTTP Workflows
7
+
8
+
9
+ By the end of this guide, you will:
10
+
11
+ - Model loading/success/error states for HTTP requests
12
+ - Implement retry logic with exponential backoff
13
+ - Cache responses to avoid redundant fetches
14
+ - Handle offline/error states gracefully
15
+
16
+ > ⚠️ **This page is a stub.** Help us write it! See the [Documentation Plan](../contributors/documentation_plan.md) and [Style Guide](../contributors/documentation_style.md).
17
+
18
+ ---
19
+
20
+ **Best Practices:** [Modal Dialogs](./modal_dialogs.md) | [Forms and Validation](./forms_and_validation.md) | [Lists and Tables](./lists_and_tables.md) | [Streaming Data](./streaming_data.md) | [Orchestration](./orchestration.md)
@@ -0,0 +1,26 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
+ -->
5
+
6
+ # Best Practices
7
+
8
+ Common UI patterns and recipes for Rooibos applications.
9
+
10
+ ---
11
+
12
+ ## UI Patterns
13
+
14
+ - [**Modal Dialogs**](./modal_dialogs.md) — Overlays, focus capture, result routing
15
+ - [**Forms and Validation**](./forms_and_validation.md) — Multi-field input, error display
16
+ - [**Lists and Tables**](./lists_and_tables.md) — Scrolling, selection, pagination
17
+
18
+ ## Data Patterns
19
+
20
+ - [**HTTP Workflows**](./http_workflows.md) — Loading states, retries, caching
21
+ - [**Streaming Data**](./streaming_data.md) — SSE, websockets, incremental updates
22
+ - [**Orchestration**](./orchestration.md) — Parallel commands, sequential flows
23
+
24
+ ---
25
+
26
+ **Having trouble?** Check out [Troubleshooting](../troubleshooting/common_errors.md).
@@ -0,0 +1,20 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
+ -->
5
+
6
+ # Lists and Tables
7
+
8
+
9
+ By the end of this guide, you will:
10
+
11
+ - Implement keyboard-navigable scrolling lists
12
+ - Track selection state in your Model
13
+ - Support pagination for large datasets
14
+ - Link to RatatuiRuby List and Table widgets
15
+
16
+ > ⚠️ **This page is a stub.** Help us write it! See the [Documentation Plan](../contributors/documentation_plan.md) and [Style Guide](../contributors/documentation_style.md).
17
+
18
+ ---
19
+
20
+ **Best Practices:** [Modal Dialogs](./modal_dialogs.md) | [Forms and Validation](./forms_and_validation.md) | [HTTP Workflows](./http_workflows.md) | [Streaming Data](./streaming_data.md) | [Orchestration](./orchestration.md)
@@ -0,0 +1,20 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
+ -->
5
+
6
+ # Modal Dialogs
7
+
8
+
9
+ By the end of this guide, you will:
10
+
11
+ - Implement a modal overlay that captures focus
12
+ - Route the dialog result (confirm/cancel) back to the parent
13
+ - Handle the "escape to close" pattern
14
+ - Design reusable modal fragments
15
+
16
+ > ⚠️ **This page is a stub.** Help us write it! See the [Documentation Plan](../contributors/documentation_plan.md) and [Style Guide](../contributors/documentation_style.md).
17
+
18
+ ---
19
+
20
+ **Best Practices:** [Forms and Validation](./forms_and_validation.md) | [Lists and Tables](./lists_and_tables.md) | [HTTP Workflows](./http_workflows.md) | [Streaming Data](./streaming_data.md) | [Orchestration](./orchestration.md)
@@ -0,0 +1,184 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
+ -->
5
+
6
+ # Stateless Widgets in MVU
7
+
8
+ After reading this guide, you will know:
9
+
10
+ - Why Rooibos uses stateless widgets instead of stateful widgets
11
+ - How to achieve selection highlighting, scrolling, and bounds clamping
12
+ - When to handle Resize events for viewport-aware layouts
13
+
14
+ ---
15
+
16
+ ## Context
17
+
18
+ RatatuiRuby offers two widget rendering modes: stateless (`render_widget`) and stateful (`render_stateful_widget`). Stateful widgets accept a mutable state object during render, updating scroll offsets and clamping selections based on viewport size.
19
+
20
+ ```ruby
21
+ # Stateful approach (imperative, inside draw block)
22
+ RatatuiRuby.draw do |frame|
23
+ frame.render_stateful_widget(list, frame.area, @list_state)
24
+ # @list_state is mutated during render
25
+ end
26
+ ```
27
+
28
+ ## Problem
29
+
30
+ MVU separates *what to display* (View) from *when to render* (Runtime). The View callable builds a widget tree. The Runtime renders it later.
31
+
32
+ Stateful widgets blur this boundary. They mutate state during render, creating hidden side effects. This breaks the MVU guarantee: **state only changes via Update**.
33
+
34
+ Passing mutable state during render means:
35
+
36
+ 1. State changes happen outside Update
37
+ 2. State mutations are invisible to the message flow
38
+ 3. Testing becomes harder—you can't predict state after render
39
+
40
+ ## Solution
41
+
42
+ Rooibos uses stateless widgets exclusively. All state management happens in your Model, computed by your Update function.
43
+
44
+ The "magic" that stateful widgets perform is simple arithmetic. You can do it yourself.
45
+
46
+ ---
47
+
48
+ ## What Stateful Widgets Actually Do
49
+
50
+ Stateful widgets perform two render-time operations:
51
+
52
+ ### 1. Selection Bounds Clamping
53
+
54
+ If `selected >= items.length`, clamp to the last item:
55
+
56
+ ```ruby
57
+ # In Update, after any selection change
58
+ def clamp_selection(model)
59
+ max_index = model.items.length - 1
60
+ if model.selected && model.selected > max_index
61
+ model.with(selected: [max_index, 0].max)
62
+ else
63
+ model
64
+ end
65
+ end
66
+ ```
67
+
68
+ ### 2. Scroll Offset Calculation
69
+
70
+ Compute which item should be at the top of the visible window:
71
+
72
+ ```ruby
73
+ # In Update, after selection or viewport changes
74
+ def calculate_offset(model)
75
+ return model unless model.selected
76
+
77
+ visible_count = model.viewport.height
78
+ selected = model.selected
79
+ offset = model.offset
80
+
81
+ # If selected is above current view, scroll up
82
+ if selected < offset
83
+ model.with(offset: selected)
84
+ # If selected is below current view, scroll down
85
+ elsif selected >= offset + visible_count
86
+ model.with(offset: selected - visible_count + 1)
87
+ else
88
+ model
89
+ end
90
+ end
91
+ ```
92
+
93
+ ---
94
+
95
+ ## Storing Viewport Dimensions
96
+
97
+ Your Model stores the terminal dimensions. Query them in `Init` and update on `Resize` events.
98
+
99
+ ### Init
100
+
101
+ ```ruby
102
+ Init = -> {
103
+ [
104
+ Model.new(
105
+ items: [],
106
+ selected: nil,
107
+ offset: 0,
108
+ viewport: RatatuiRuby.viewport_area
109
+ ),
110
+ fetch_items_command
111
+ ]
112
+ }
113
+ ```
114
+
115
+ ### Update
116
+
117
+ ```ruby
118
+ Update = ->(model, message) {
119
+ case message
120
+ in Rooibos::Message::Resize(width:, height:)
121
+ new_viewport = RatatuiRuby::Layout::Rect.new(x: 0, y: 0, width:, height:)
122
+ new_model = model.with(viewport: new_viewport)
123
+ [calculate_offset(new_model), nil]
124
+ in SelectNext
125
+ new_selected = [(model.selected || -1) + 1, model.items.length - 1].min
126
+ new_model = model.with(selected: new_selected)
127
+ [calculate_offset(new_model), nil]
128
+ # ...
129
+ end
130
+ }
131
+ ```
132
+
133
+ ### View
134
+
135
+ ```ruby
136
+ View = ->(model, tui) {
137
+ visible_items = model.items[model.offset, model.viewport.height] || []
138
+
139
+ list = tui.list(
140
+ items: visible_items,
141
+ highlight_style: tui.style(fg: :yellow)
142
+ )
143
+
144
+ # Highlighting uses the offset-adjusted index
145
+ if model.selected
146
+ visible_selected = model.selected - model.offset
147
+ list = list.with(selected_index: visible_selected)
148
+ end
149
+
150
+ list
151
+ }
152
+ ```
153
+
154
+ ---
155
+
156
+ ## Benefits
157
+
158
+ ### Testable State
159
+
160
+ All state changes happen in Update. Test your logic without rendering:
161
+
162
+ ```ruby
163
+ def test_selection_clamps_to_bounds
164
+ viewport = RatatuiRuby::Layout::Rect.new(x: 0, y: 0, width: 80, height: 10)
165
+ model = Model.new(items: ["a", "b"], selected: 5, offset: 0, viewport:)
166
+ result, _ = Update.call(model, ClampSelection.new)
167
+ assert_equal 1, result.selected
168
+ end
169
+ ```
170
+
171
+ ### Predictable Rendering
172
+
173
+ View is a pure function. Given the same Model, it returns the same widget tree. No hidden mutations.
174
+
175
+ ### No Frame Dependency
176
+
177
+ View runs before the draw callback. Terminal queries work normally.
178
+
179
+ ---
180
+
181
+ ## See Also
182
+
183
+ - [The Elm Architecture](../essentials/the_elm_architecture.md) — Core MVU concepts
184
+ - [Lists and Tables](lists_and_tables.md) — Patterns for scrollable collections
@@ -0,0 +1,20 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
+ -->
5
+
6
+ # Orchestration
7
+
8
+
9
+ By the end of this guide, you will:
10
+
11
+ - Coordinate parallel commands with `Command.all`
12
+ - Sequence dependent operations (A then B then C)
13
+ - Handle partial failures in multi-step workflows
14
+ - Design robust async pipelines
15
+
16
+ > ⚠️ **This page is a stub.** Help us write it! See the [Documentation Plan](../contributors/documentation_plan.md) and [Style Guide](../contributors/documentation_style.md).
17
+
18
+ ---
19
+
20
+ **Best Practices:** [Modal Dialogs](./modal_dialogs.md) | [Forms and Validation](./forms_and_validation.md) | [Lists and Tables](./lists_and_tables.md) | [HTTP Workflows](./http_workflows.md) | [Streaming Data](./streaming_data.md)
@@ -0,0 +1,20 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
+ -->
5
+
6
+ # Streaming Data
7
+
8
+
9
+ By the end of this guide, you will:
10
+
11
+ - Handle SSE (Server-Sent Events) streams
12
+ - Process websocket messages as they arrive
13
+ - Update UI incrementally without blocking
14
+ - Clean up streaming connections on app exit
15
+
16
+ > ⚠️ **This page is a stub.** Help us write it! See the [Documentation Plan](../contributors/documentation_plan.md) and [Style Guide](../contributors/documentation_style.md).
17
+
18
+ ---
19
+
20
+ **Best Practices:** [Modal Dialogs](./modal_dialogs.md) | [Forms and Validation](./forms_and_validation.md) | [Lists and Tables](./lists_and_tables.md) | [HTTP Workflows](./http_workflows.md) | [Orchestration](./orchestration.md)
@@ -43,7 +43,7 @@ Long-running commands block the event loop. WebSocket listeners, database poller
43
43
 
44
44
  `Thread#kill` terminates immediately. Mutexes may deadlock. Resources may leak. Database transactions may abort mid-write.
45
45
 
46
- The `CancellationToken` signals cancellation requests. Commands check `token.cancelled?` periodically and stop at safe points. Cleanup code runs. Resources release. Transactions commit.
46
+ The `CancellationToken` signals cancellation requests. Commands check `token.canceled?` periodically and stop at safe points. Cleanup code runs. Resources release. Transactions commit.
47
47
 
48
48
  | Aspect | `Thread#kill` | CancellationToken |
49
49
  |--------|---------------|------------------|