rooibos 0.5.0 → 0.6.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.
- checksums.yaml +4 -4
- data/.builds/ruby-3.2.yml +9 -5
- data/.builds/ruby-3.3.yml +9 -5
- data/.builds/ruby-3.4.yml +9 -5
- data/.builds/ruby-4.0.0.yml +9 -5
- data/AGENTS.md +1 -1
- data/CHANGELOG.md +46 -0
- data/README.md +2 -2
- data/README.rdoc +374 -0
- data/REUSE.toml +5 -0
- data/Rakefile +1 -1
- data/doc/best_practices/forms_and_validation.md +20 -0
- data/doc/best_practices/http_workflows.md +20 -0
- data/doc/best_practices/index.md +26 -0
- data/doc/best_practices/lists_and_tables.md +20 -0
- data/doc/best_practices/modal_dialogs.md +20 -0
- data/doc/best_practices/no_stateful_widgets.md +184 -0
- data/doc/best_practices/orchestration.md +20 -0
- data/doc/best_practices/streaming_data.md +20 -0
- data/doc/contributors/design/commands_and_outlets.md +1 -1
- data/doc/contributors/documentation_plan.md +616 -0
- data/doc/contributors/documentation_stub_audit.md +112 -0
- data/doc/contributors/documentation_style.md +275 -0
- data/doc/contributors/e2e_pty.md +168 -0
- data/doc/contributors/specs/earliest_tutorial_steps_per_story.md +70 -0
- data/doc/contributors/specs/file_browser.md +789 -0
- data/doc/contributors/specs/file_browser_stories.md +774 -0
- data/doc/contributors/specs/tutorials_to_stories.rb +167 -0
- data/doc/contributors/todo/scrollbar.md +118 -0
- data/doc/contributors/tutorial_old/01_project_setup.md +20 -0
- data/doc/contributors/tutorial_old/02_hello_world.md +24 -0
- data/doc/contributors/tutorial_old/03_adding_state.md +26 -0
- data/doc/contributors/tutorial_old/06_organizing_your_code.md +20 -0
- data/doc/contributors/tutorial_old/07_your_first_command.md +21 -0
- data/doc/contributors/tutorial_old/08_the_preview_pane.md +20 -0
- data/doc/contributors/tutorial_old/09_loading_states.md +20 -0
- data/doc/contributors/tutorial_old/10_testing_your_app.md +20 -0
- data/doc/contributors/tutorial_old/11_polish_and_refine.md +20 -0
- data/doc/contributors/tutorial_old/12_going_further.md +20 -0
- data/doc/contributors/tutorial_old/index.md +20 -0
- data/doc/essentials/commands.md +20 -0
- data/doc/essentials/index.md +31 -0
- data/doc/essentials/messages.md +21 -0
- data/doc/essentials/models.md +21 -0
- data/doc/essentials/shortcuts.md +19 -0
- data/doc/essentials/the_elm_architecture.md +24 -0
- data/doc/essentials/the_runtime.md +21 -0
- data/doc/essentials/update_functions.md +20 -0
- data/doc/essentials/views.md +22 -0
- data/doc/getting_started/for_go_developers.md +16 -0
- data/doc/getting_started/for_python_developers.md +16 -0
- data/doc/getting_started/for_react_developers.md +17 -0
- data/doc/getting_started/index.md +52 -0
- data/doc/getting_started/install.md +20 -0
- data/doc/getting_started/quickstart.md +9 -45
- data/doc/getting_started/ruby_primer.md +19 -0
- data/doc/getting_started/why_rooibos.md +20 -0
- data/doc/index.md +79 -11
- data/doc/scaling_up/async_patterns.md +20 -0
- data/doc/scaling_up/command_composition.md +20 -0
- data/doc/scaling_up/custom_commands.md +21 -0
- data/doc/scaling_up/fractal_architecture.md +20 -0
- data/doc/scaling_up/index.md +30 -0
- data/doc/scaling_up/message_routing.md +20 -0
- data/doc/scaling_up/ractor_safety.md +20 -0
- data/doc/scaling_up/testing.md +21 -0
- data/doc/troubleshooting/common_errors.md +20 -0
- data/doc/troubleshooting/debugging.md +21 -0
- data/doc/troubleshooting/index.md +23 -0
- data/doc/troubleshooting/performance.md +20 -0
- data/doc/tutorial/01_project_setup.md +44 -0
- data/doc/tutorial/02_hello_world.md +45 -0
- data/doc/tutorial/03_static_file_list.md +44 -0
- data/doc/tutorial/04_arrow_navigation.md +47 -0
- data/doc/tutorial/05_real_files.md +45 -0
- data/doc/tutorial/06_safe_refactoring.md +21 -0
- data/doc/tutorial/07_red_first_tdd.md +26 -0
- data/doc/tutorial/08_file_metadata.md +42 -0
- data/doc/tutorial/09_text_preview.md +44 -0
- data/doc/tutorial/10_directory_tree.md +42 -0
- data/doc/tutorial/11_pane_focus.md +40 -0
- data/doc/tutorial/12_sorting.md +41 -0
- data/doc/tutorial/13_filtering.md +43 -0
- data/doc/tutorial/14_toggle_hidden.md +41 -0
- data/doc/tutorial/15_text_input_widget.md +43 -0
- data/doc/tutorial/16_rename_files.md +42 -0
- data/doc/tutorial/17_confirmation_dialogs.md +43 -0
- data/doc/tutorial/18_progress_indicators.md +43 -0
- data/doc/tutorial/19_atomic_operations.md +42 -0
- data/doc/tutorial/20_external_editor.md +42 -0
- data/doc/tutorial/21_modal_overlays.md +41 -0
- data/doc/tutorial/22_error_handling.md +43 -0
- data/doc/tutorial/23_terminal_capabilities.md +53 -0
- data/doc/tutorial/24_mouse_events.md +43 -0
- data/doc/tutorial/25_resize_events.md +43 -0
- data/doc/tutorial/26_loading_states.md +42 -0
- data/doc/tutorial/27_performance.md +43 -0
- data/doc/tutorial/28_color_schemes.md +47 -0
- data/doc/tutorial/29_configuration.md +124 -0
- data/doc/tutorial/30_going_further.md +17 -0
- data/doc/tutorial/index.md +17 -0
- data/examples/app_file_browser/app.rb +40 -0
- data/examples/app_fractal_dashboard/dashboard/update_manual.rb +7 -7
- data/examples/app_fractal_dashboard/fragments/custom_shell_input.rb +5 -5
- data/examples/app_fractal_dashboard/fragments/custom_shell_modal.rb +1 -1
- data/examples/app_fractal_dashboard/fragments/disk_usage.rb +2 -2
- data/examples/app_fractal_dashboard/fragments/network_panel.rb +4 -4
- data/examples/app_fractal_dashboard/fragments/ping.rb +2 -2
- data/examples/app_fractal_dashboard/fragments/stats_panel.rb +4 -4
- data/examples/app_fractal_dashboard/fragments/system_info.rb +2 -2
- data/examples/app_fractal_dashboard/fragments/uptime.rb +2 -2
- data/examples/verify_website_first_app/app.rb +85 -0
- data/examples/verify_website_hello_mvu/app.rb +31 -0
- data/examples/widget_command_system/app.rb +15 -13
- data/exe/rooibos +10 -0
- data/generate_tutorial_stubs.rb +126 -0
- data/lib/rooibos/cli/commands/new.rb +373 -0
- data/lib/rooibos/cli/commands/run.rb +98 -0
- data/lib/rooibos/cli.rb +78 -0
- data/lib/rooibos/command/all.rb +25 -20
- data/lib/rooibos/command/batch.rb +26 -25
- data/lib/rooibos/command/custom.rb +84 -1
- data/lib/rooibos/command/http.rb +59 -55
- data/lib/rooibos/command/lifecycle.rb +5 -5
- data/lib/rooibos/command/open.rb +86 -0
- data/lib/rooibos/command/outlet.rb +105 -3
- data/lib/rooibos/command/wait.rb +5 -5
- data/lib/rooibos/command.rb +57 -74
- data/lib/rooibos/message/batch.rb +39 -0
- data/lib/rooibos/message/canceled.rb +51 -0
- data/lib/rooibos/message/error.rb +48 -0
- data/lib/rooibos/message/open.rb +30 -0
- data/lib/rooibos/message.rb +84 -4
- data/lib/rooibos/router.rb +11 -14
- data/lib/rooibos/runtime.rb +40 -43
- data/lib/rooibos/shortcuts.rb +47 -0
- data/lib/rooibos/test_helper.rb +71 -6
- data/lib/rooibos/version.rb +1 -1
- data/lib/rooibos/welcome.rb +237 -0
- data/lib/rooibos.rb +4 -3
- data/mise.toml +1 -1
- data/rbs_collection.lock.yaml +2 -2
- data/sig/concurrent.rbs +3 -0
- data/sig/gem.rbs +20 -0
- data/sig/rooibos/cli.rbs +42 -0
- data/sig/rooibos/command.rbs +48 -0
- data/sig/rooibos/message.rbs +60 -0
- data/sig/rooibos/shortcuts.rbs +14 -0
- data/sig/rooibos/test_helper.rbs +6 -2
- data/sig/rooibos/welcome.rbs +75 -0
- data/tasks/install.rake +29 -0
- data/tasks/resources/build.yml.erb +2 -0
- metadata +272 -38
- data/doc/concepts/application_architecture.md +0 -197
- data/doc/concepts/application_testing.md +0 -49
- data/doc/concepts/async_work.md +0 -164
- data/doc/concepts/commands.md +0 -530
- data/doc/concepts/message_processing.md +0 -51
- data/doc/contributors/WIP/decomposition_strategies_analysis.md +0 -258
- data/doc/contributors/WIP/implementation_plan.md +0 -409
- data/doc/contributors/WIP/init_callable_proposal.md +0 -344
- data/doc/contributors/WIP/runtime_refactoring_status.md +0 -47
- data/doc/contributors/WIP/task.md +0 -36
- data/doc/contributors/WIP/v0.4.0_todo.md +0 -468
- data/doc/contributors/kit-no-outlet.md +0 -238
- data/doc/contributors/priorities.md +0 -38
- data/doc/images/.gitkeep +0 -0
- data/exe/.gitkeep +0 -0
- /data/doc/contributors/{WIP → design}/mvu_tea_implementations_research.md +0 -0
|
@@ -1,344 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
|
|
4
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
5
|
-
-->
|
|
6
|
-
|
|
7
|
-
# Init Callable Architecture Proposal
|
|
8
|
-
|
|
9
|
-
## Problem Statement
|
|
10
|
-
|
|
11
|
-
The current codebase has **three different names** for the initial state instance:
|
|
12
|
-
|
|
13
|
-
1. **`MODEL`** - Used in simple examples (README, verify_readme_usage)
|
|
14
|
-
2. **`INITIAL`** - Used in fractal fragments (dashboard examples)
|
|
15
|
-
3. **`init:`** - Runtime parameter for startup commands (different semantics)
|
|
16
|
-
|
|
17
|
-
Additionally, the planned v0.4.0 transition (`INITIAL` → `Initial`) would create visual collision with `Model`, where both look like type names despite having different purposes.
|
|
18
|
-
|
|
19
|
-
### Current Fragment Pattern
|
|
20
|
-
|
|
21
|
-
```ruby
|
|
22
|
-
module SystemInfo
|
|
23
|
-
Model = Data.define(:output, :loading)
|
|
24
|
-
INITIAL = Model.new(output: "Press 's'", loading: false) # Static constant
|
|
25
|
-
|
|
26
|
-
UPDATE = ->(message, model) { ... }
|
|
27
|
-
VIEW = ->(model, tui) { ... }
|
|
28
|
-
end
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### Current Limitations
|
|
32
|
-
|
|
33
|
-
- **No parameterization**: Child fragments can't receive initialization props from parents
|
|
34
|
-
- **Naming confusion**: `Model` (type) vs `INITIAL`/`MODEL` (instance) vs `init:` (command)
|
|
35
|
-
- **Static only**: Can't dispatch initial commands alongside state
|
|
36
|
-
- **No context**: Root fragments can't access ARGV, ENV, or other runtime context
|
|
37
|
-
|
|
38
|
-
## Proposed Solution
|
|
39
|
-
|
|
40
|
-
Replace the static `INITIAL`/`MODEL` constant with an **`Init` callable** that:
|
|
41
|
-
|
|
42
|
-
1. **Returns `[model, command]`** - Same pattern as `Update`
|
|
43
|
-
2. **Accepts flags/props** - Context from parent or runtime
|
|
44
|
-
3. **Supports DWIM**: Can return just `model` (no command) like `Update`
|
|
45
|
-
|
|
46
|
-
### New Fragment Pattern
|
|
47
|
-
|
|
48
|
-
```ruby
|
|
49
|
-
module SystemInfo
|
|
50
|
-
Model = Data.define(:output, :loading)
|
|
51
|
-
|
|
52
|
-
# Init receives flags from parent, returns [model, command?]
|
|
53
|
-
Init = ->(disabled: false) do
|
|
54
|
-
message = disabled ? "(disabled)" : "Press 's' for system info"
|
|
55
|
-
[Model.new(output: message, loading: false), nil]
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
Update = ->(message, model) { ... }
|
|
59
|
-
View = ->(model, tui) { ... }
|
|
60
|
-
end
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### Root Fragment with Runtime Context
|
|
64
|
-
|
|
65
|
-
```ruby
|
|
66
|
-
module App
|
|
67
|
-
Model = Data.define(:user_name, :debug_mode, :data)
|
|
68
|
-
|
|
69
|
-
Init = ->(argv:, env:) do
|
|
70
|
-
debug = env['DEBUG'] == '1'
|
|
71
|
-
name = argv[0] || env['USER'] || 'guest'
|
|
72
|
-
|
|
73
|
-
model = Model.new(user_name: name, debug_mode: debug, data: nil)
|
|
74
|
-
command = Command.http(:get, "/api/startup", :initial_data)
|
|
75
|
-
|
|
76
|
-
[model, command]
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
Update = ->(message, model) { ... }
|
|
80
|
-
View = ->(model, tui) { ... }
|
|
81
|
-
end
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### Fractal Composition
|
|
85
|
-
|
|
86
|
-
```ruby
|
|
87
|
-
|
|
88
|
-
module Dashboard
|
|
89
|
-
Model = Data.define(:stats, :network, :theme)
|
|
90
|
-
|
|
91
|
-
Init = ->(theme: :dark, env:) do
|
|
92
|
-
# Parent can pass props to children
|
|
93
|
-
stats_model, stats_cmd = StatsPanel::Init.(theme: theme)
|
|
94
|
-
network_model, network_cmd = NetworkPanel::Init.(theme: theme)
|
|
95
|
-
|
|
96
|
-
model = Model.new(stats: stats_model, network: network_model, theme: theme)
|
|
97
|
-
command = Command.batch(
|
|
98
|
-
Rooibos.route(stats_cmd, :stats),
|
|
99
|
-
Rooibos.route(network_cmd, :network)
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
[model, command]
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
Update = from_router
|
|
106
|
-
View = ->(model, tui) { ... }
|
|
107
|
-
end
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
## Benefits
|
|
111
|
-
|
|
112
|
-
### 1. Eliminates Naming Confusion
|
|
113
|
-
|
|
114
|
-
| Current (3 names) | Proposed (1 name) |
|
|
115
|
-
|-------------------|-------------------|
|
|
116
|
-
| `Model` (type) | `Model` (type) |
|
|
117
|
-
| `INITIAL` or `MODEL` (instance) | `Init` (callable) |
|
|
118
|
-
| `init:` (runtime param) | `init:` (runtime param) |
|
|
119
|
-
|
|
120
|
-
### 2. Enables Parameterization (React-Style Props)
|
|
121
|
-
|
|
122
|
-
Parents can pass configuration to children:
|
|
123
|
-
|
|
124
|
-
```ruby
|
|
125
|
-
# Parent decides child's theme, debug mode, etc.
|
|
126
|
-
child_model, child_cmd = ChildFragment::Init.(theme: :light, debug: true)
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### 3. Unifies Initialization Pattern
|
|
130
|
-
|
|
131
|
-
Both `Init` and `Update` now follow the same signature:
|
|
132
|
-
|
|
133
|
-
```ruby
|
|
134
|
-
Init :: (flags) -> [Model, Command?]
|
|
135
|
-
Update :: (Message, Model) -> [Model, Command?]
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### 4. Supports Initial Commands
|
|
139
|
-
|
|
140
|
-
No need for separate `init:` runtime parameter pattern:
|
|
141
|
-
|
|
142
|
-
```ruby
|
|
143
|
-
# Old way
|
|
144
|
-
INITIAL = Model.new(data: nil)
|
|
145
|
-
Rooibos.run(model: INITIAL, init: -> { fetch_data_command })
|
|
146
|
-
|
|
147
|
-
# New way
|
|
148
|
-
Init = -> { [Model.new(data: nil), fetch_data_command] }
|
|
149
|
-
Rooibos.run(fragment: MyApp) # Init is called automatically
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
### 5. Access to Runtime Context
|
|
153
|
-
|
|
154
|
-
Root fragments can inspect ARGV, ENV, config files, etc.:
|
|
155
|
-
|
|
156
|
-
```ruby
|
|
157
|
-
Init = ->(argv:, env:) do
|
|
158
|
-
config = parse_config(argv[0]) if argv[0]
|
|
159
|
-
# ...
|
|
160
|
-
end
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
## Migration Path
|
|
164
|
-
|
|
165
|
-
### Phase 1: Introduce `Init` alongside `INITIAL`
|
|
166
|
-
|
|
167
|
-
Both patterns work during transition:
|
|
168
|
-
|
|
169
|
-
```ruby
|
|
170
|
-
# Old style (deprecated)
|
|
171
|
-
INITIAL = Model.new(...)
|
|
172
|
-
|
|
173
|
-
# New style (preferred)
|
|
174
|
-
Init = -> { Model.new(...) }
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
### Phase 2: Runtime Changes
|
|
178
|
-
|
|
179
|
-
```ruby
|
|
180
|
-
# Current
|
|
181
|
-
Rooibos.run(model: Fragment::INITIAL, view: Fragment::VIEW, update: Fragment::UPDATE)
|
|
182
|
-
|
|
183
|
-
# Transitional (supports both)
|
|
184
|
-
Rooibos.run(fragment: Fragment) # Calls Fragment::Init
|
|
185
|
-
# OR
|
|
186
|
-
Rooibos.run(model: initial_model, view: view, update: update) # Old style
|
|
187
|
-
|
|
188
|
-
# Future
|
|
189
|
-
Rooibos.run(fragment: Fragment, argv: ARGV, env: ENV)
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
### Phase 3: DSL for Fractal Composition
|
|
193
|
-
|
|
194
|
-
Router could auto-call child `Init`:
|
|
195
|
-
|
|
196
|
-
```ruby
|
|
197
|
-
|
|
198
|
-
module Dashboard
|
|
199
|
-
include Rooibos::Router
|
|
200
|
-
|
|
201
|
-
# Automatically calls StatsPanel::Init and NetworkPanel::Init
|
|
202
|
-
mount :stats, fragment: StatsPanel, theme: :dark
|
|
203
|
-
mount :network, fragment: NetworkPanel, theme: :dark
|
|
204
|
-
|
|
205
|
-
Update = from_router
|
|
206
|
-
end
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
## Open Questions
|
|
210
|
-
|
|
211
|
-
### 1. Fragment Signature
|
|
212
|
-
|
|
213
|
-
What constants are required?
|
|
214
|
-
|
|
215
|
-
**Option A: All four**
|
|
216
|
-
```ruby
|
|
217
|
-
Model, Init, Update, View # Complete fragment
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
**Option B: Flexible**
|
|
221
|
-
```ruby
|
|
222
|
-
Model, Update, View # No Init = empty model
|
|
223
|
-
Model, Init # View-less (backend fragment?)
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
### 2. Init Return Type DWIM
|
|
227
|
-
|
|
228
|
-
How flexible should the return be?
|
|
229
|
-
|
|
230
|
-
```ruby
|
|
231
|
-
Init = -> { Model.new(...) } # Just model, no command
|
|
232
|
-
Init = -> { [Model.new(...), nil] } # Explicit tuple
|
|
233
|
-
Init = -> { [Model.new(...), some_command] } # With command
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
### 3. Backward Compatibility
|
|
237
|
-
|
|
238
|
-
**Breaking or transitional?**
|
|
239
|
-
|
|
240
|
-
- **Option A**: v0.5.0 breaking change, remove `INITIAL` support entirely
|
|
241
|
-
- **Option B**: v0.4.x transitional, support both patterns with deprecation warnings
|
|
242
|
-
- **Option C**: v0.4.x additive, keep `INITIAL` forever, `Init` is optional
|
|
243
|
-
|
|
244
|
-
### 4. Runtime API
|
|
245
|
-
|
|
246
|
-
**How does `Rooibos.run` change?**
|
|
247
|
-
|
|
248
|
-
```ruby
|
|
249
|
-
# Current
|
|
250
|
-
Rooibos.run(model: initial, view: view, update: update, init: startup_cmd)
|
|
251
|
-
|
|
252
|
-
# Proposed Option 1: Fragment-first
|
|
253
|
-
Rooibos.run(fragment: App, argv: ARGV, env: ENV)
|
|
254
|
-
|
|
255
|
-
# Proposed Option 2: Hybrid
|
|
256
|
-
Rooibos.run(fragment: App) # Uses App::Init
|
|
257
|
-
# OR
|
|
258
|
-
Rooibos.run(model: model, view: view, update: update) # Old style still works
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
### 5. Router DSL Integration
|
|
262
|
-
|
|
263
|
-
Should `route :child, to: ChildFragment` auto-initialize?
|
|
264
|
-
|
|
265
|
-
```ruby
|
|
266
|
-
# Manual (explicit control)
|
|
267
|
-
route :child, to: ChildFragment
|
|
268
|
-
Init = ->(theme:) do
|
|
269
|
-
child_model, child_cmd = ChildFragment::Init.(theme: theme)
|
|
270
|
-
[Model.new(child: child_model), Rooibos.route(child_cmd, :child)]
|
|
271
|
-
end
|
|
272
|
-
|
|
273
|
-
# Automatic (magic convenience)
|
|
274
|
-
mount :child, fragment: ChildFragment, theme: :dark # Auto-calls Init
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
## Implementation Sketch
|
|
278
|
-
|
|
279
|
-
### Runtime Changes
|
|
280
|
-
|
|
281
|
-
```ruby
|
|
282
|
-
module Rooibos
|
|
283
|
-
def self.run(fragment: nil, model: nil, view: nil, update: nil, argv: [], env: {})
|
|
284
|
-
if fragment
|
|
285
|
-
# New style: fragment-first
|
|
286
|
-
init_result = fragment::Init.call(argv: argv, env: env)
|
|
287
|
-
model, init_cmd = normalize_update_result(init_result)
|
|
288
|
-
view = fragment::View
|
|
289
|
-
update = fragment::Update
|
|
290
|
-
else
|
|
291
|
-
# Old style: explicit model/view/update
|
|
292
|
-
# (backward compatible)
|
|
293
|
-
end
|
|
294
|
-
|
|
295
|
-
Runtime.run(model: model, view: view, update: update, init: init_cmd)
|
|
296
|
-
end
|
|
297
|
-
end
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
### Fragment Helpers
|
|
301
|
-
|
|
302
|
-
```ruby
|
|
303
|
-
|
|
304
|
-
module Rooibos::Fragment
|
|
305
|
-
# Normalize Init or Update return values
|
|
306
|
-
def self.call_init(fragment, **flags)
|
|
307
|
-
result = fragment::Init.call(**flags)
|
|
308
|
-
normalize(result)
|
|
309
|
-
end
|
|
310
|
-
|
|
311
|
-
def self.normalize(result)
|
|
312
|
-
case result
|
|
313
|
-
in [model, command] then [model, command]
|
|
314
|
-
in model then [model, nil]
|
|
315
|
-
end
|
|
316
|
-
end
|
|
317
|
-
end
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
## Recommendation
|
|
321
|
-
|
|
322
|
-
I think this is a **excellent** direction because:
|
|
323
|
-
|
|
324
|
-
1. ✅ **Solves the naming collision** completely
|
|
325
|
-
2. ✅ **Enables parent-to-child props** (long-standing limitation)
|
|
326
|
-
3. ✅ **Unifies Init and Update patterns** (both return tuples)
|
|
327
|
-
4. ✅ **Removes runtime context limitations** (ARGV, ENV access)
|
|
328
|
-
5. ✅ **Simplifies the "what's my initial command?" pattern**
|
|
329
|
-
|
|
330
|
-
### Suggested Approach
|
|
331
|
-
|
|
332
|
-
1. **v0.4.x**: Introduce `Init` as **optional**, keep `INITIAL` support
|
|
333
|
-
2. **Document the pattern** with examples and migration guide
|
|
334
|
-
3. **Add Router DSL sugar** for `mount :child, fragment: ChildFragment, props...`
|
|
335
|
-
4. **v0.5.0**: Deprecate `INITIAL`, make `Init` required
|
|
336
|
-
|
|
337
|
-
This gives users time to migrate while immediately solving the parameterization problem for new code.
|
|
338
|
-
|
|
339
|
-
## Next Steps
|
|
340
|
-
|
|
341
|
-
1. Get user feedback on this proposal
|
|
342
|
-
2. Prototype the runtime changes
|
|
343
|
-
3. Convert one example (fractal dashboard) to new pattern
|
|
344
|
-
4. Document the full API and migration path
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
|
|
4
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
5
|
-
-->
|
|
6
|
-
|
|
7
|
-
# Runtime Refactoring - Final Status
|
|
8
|
-
|
|
9
|
-
## ✅ Completed
|
|
10
|
-
|
|
11
|
-
1. **CHANGE LOG documented** - Breaking changes added:
|
|
12
|
-
- Runtime API signature (positional fragment, fps param, removed argv/env, renamed init to command)
|
|
13
|
-
- Model validation timing (now validates immediately after Init)
|
|
14
|
-
|
|
15
|
-
2. **RBS Signatures** - Fully updated for new signature
|
|
16
|
-
|
|
17
|
-
3. **Rooibos.run signatures** - All test files updated from `fragment:` to positional
|
|
18
|
-
|
|
19
|
-
4. **Model Ractor-shareability** - All tests fixed with `Ractor.make_shareable(..., copy: true)`
|
|
20
|
-
|
|
21
|
-
## ⚠️ Remaining Issues (3 errors from agent_rake)
|
|
22
|
-
|
|
23
|
-
### 1. test_runtime.rb:237 - Test body deleted by accident
|
|
24
|
-
**File**: `test/test_runtime.rb`
|
|
25
|
-
**Issue**: Deleted lines 237-245 which contained the test body for `test_init_triggers_update_before_first_event`
|
|
26
|
-
|
|
27
|
-
**Fix needed**: Restore test body. The test should validate that `command:` parameter gets dispatched at startup.
|
|
28
|
-
|
|
29
|
-
### 2. test_fragment_first_api.rb:48 - Missing with_argv helper
|
|
30
|
-
**File**: `test/test_fragment_first_api.rb`
|
|
31
|
-
**Issue**: `NoMethodError: undefined method 'with_argv'`
|
|
32
|
-
|
|
33
|
-
**Fix needed**: Add `with_argv` helper to `/Users/kerrick/Developer/ratatui_ruby/test/test_helper.rb` (already documented earlier in conversation)
|
|
34
|
-
|
|
35
|
-
### 3. test_runtime_timer.rb:155 - Cancel assertion
|
|
36
|
-
**File**: `test/test_runtime_timer.rb`
|
|
37
|
-
**Issue**: Assertion compares Cancel object vs Wait command directly
|
|
38
|
-
|
|
39
|
-
**Current**: `assert_same original_cmd, cancel_msg`
|
|
40
|
-
**Should be**: `assert_same original_cmd, cancel_msg.handle`
|
|
41
|
-
|
|
42
|
-
The sed command ran but didn't match because cancel_msg is on its own line.
|
|
43
|
-
|
|
44
|
-
## Summary
|
|
45
|
-
|
|
46
|
-
**272 runs, 779 assertions, 2 failures, 1 errors from 95+ errors**
|
|
47
|
-
Major progress! Just need to fix these 3 small issues.
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
|
|
4
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
5
|
-
-->
|
|
6
|
-
|
|
7
|
-
# Task: Update Tests and Docs for Runtime Refactoring
|
|
8
|
-
|
|
9
|
-
## Signature Changes
|
|
10
|
-
- [x] Update RBS signatures for new Runtime.run signature
|
|
11
|
-
- [x] Add with_argv helper to ratatui_ruby test_helper
|
|
12
|
-
- [x] Update Rooibos.run wrapper signature
|
|
13
|
-
|
|
14
|
-
## Test Updates
|
|
15
|
-
- [x] Update test_fragment_first_api.rb - change fragment: to positional
|
|
16
|
-
- [x] Fix argv/env tests to use with_argv/with_env helpers
|
|
17
|
-
- [x] Fix all Command.custom tests to use Ractor-shareable callables
|
|
18
|
-
- [ ] Fix test_init_triggers_update_before_first_event - still failing
|
|
19
|
-
- [ ] Fix test_fragment_first_api_passes_argv_and_env_to_init - ENV hash comparison issue
|
|
20
|
-
- [ ] Update test_snapshots.rb - change all Rooibos.run calls (15+ occurrences)
|
|
21
|
-
- [ ] Update test_fractal_dashboard.rb - change Rooibos.run calls
|
|
22
|
-
- [ ] Update all other test files using Rooibos.run
|
|
23
|
-
- [ ] Add test for fps: parameter
|
|
24
|
-
|
|
25
|
-
## Example Updates
|
|
26
|
-
- [ ] Update verify_readme_usage/app.rb
|
|
27
|
-
- [ ] Update app_fractal_dashboard Init callables (remove argv/env params)
|
|
28
|
-
|
|
29
|
-
## Current Status
|
|
30
|
-
**3 failures, 1 error**: Making final fixes
|
|
31
|
-
- test_init_triggers_update_before_first_event - still needs investigation
|
|
32
|
-
- test_fragment_first_api_passes_argv_and_env_to_init - ENV not being passed correctly
|
|
33
|
-
- test_cancelled_wait_acknowledges_cancellation - intermittent
|
|
34
|
-
- test_custom_accepts_block - fixing Command.custom wrapper pattern
|
|
35
|
-
|
|
36
|
-
Restructuring Command.custom tests to demonstrate automatic shareability handling.
|