tokra 0.0.1.pre.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 +7 -0
- data/.pre-commit-config.yaml +16 -0
- data/AGENTS.md +126 -0
- data/CHANGELOG.md +21 -0
- data/CODE_OF_CONDUCT.md +16 -0
- data/Cargo.toml +23 -0
- data/LICENSE +661 -0
- data/LICENSES/AGPL-3.0-or-later.txt +235 -0
- data/LICENSES/Apache-2.0.txt +73 -0
- data/LICENSES/CC-BY-SA-4.0.txt +170 -0
- data/LICENSES/CC0-1.0.txt +121 -0
- data/LICENSES/MIT.txt +18 -0
- data/README.md +45 -0
- data/README.rdoc +4 -0
- data/REUSE.toml +11 -0
- data/Rakefile +27 -0
- data/Steepfile +15 -0
- data/clippy.toml +5 -0
- data/clippy_exceptions.rb +59 -0
- data/doc/contributors/adr/001.md +187 -0
- data/doc/contributors/adr/002.md +132 -0
- data/doc/contributors/adr/003.md +116 -0
- data/doc/contributors/chats/001.md +3874 -0
- data/doc/contributors/plan/001.md +271 -0
- data/examples/verify_hello_world/app.rb +114 -0
- data/examples/verify_hello_world/index.html +88 -0
- data/examples/verify_ping_pong/README.md +0 -0
- data/examples/verify_ping_pong/app.rb +132 -0
- data/examples/verify_ping_pong/public/styles.css +182 -0
- data/examples/verify_ping_pong/views/index.erb +94 -0
- data/examples/verify_ping_pong/views/layout.erb +22 -0
- data/exe/semantic-highlight +0 -0
- data/ext/tokra/Cargo.toml +23 -0
- data/ext/tokra/extconf.rb +12 -0
- data/ext/tokra/src/lib.rs +719 -0
- data/lib/tokra/native.rb +79 -0
- data/lib/tokra/rack/handler.rb +177 -0
- data/lib/tokra/version.rb +12 -0
- data/lib/tokra.rb +19 -0
- data/mise.toml +8 -0
- data/rustfmt.toml +4 -0
- data/sig/tokra.rbs +7 -0
- data/tasks/lint.rake +151 -0
- data/tasks/rust.rake +63 -0
- data/tasks/steep.rake +11 -0
- data/tasks/test.rake +26 -0
- data/test_native.rb +37 -0
- data/vendor/goodcop/base.yml +1047 -0
- metadata +112 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
|
|
4
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
# ADR 003: Tokra Build System & "Ping Pong" Validation
|
|
8
|
+
|
|
9
|
+
## Status
|
|
10
|
+
Accepted
|
|
11
|
+
|
|
12
|
+
## Date
|
|
13
|
+
2026-01-29
|
|
14
|
+
|
|
15
|
+
## Context
|
|
16
|
+
Tokra bridges three distinct ecosystems: Ruby (Gems), Rust (Cargo), and System Libraries (Tao/Wry dependencies like GTK/WebKit).
|
|
17
|
+
A naive implementation using standard `bundle gem --ext` often fails in CI/CD or on user machines because it assumes the presence of Rust toolchains and system headers in non-standard locations.
|
|
18
|
+
|
|
19
|
+
Furthermore, because Ractors isolate memory state, "classic" Ruby tests (RSpec) that mock objects often produce false positives. They verify logic but fail to verify that objects can actually traverse the Ractor boundary without crashing the VM.
|
|
20
|
+
|
|
21
|
+
## Decision
|
|
22
|
+
|
|
23
|
+
### 1. The Build Glue: `rb_sys`
|
|
24
|
+
We will mandate the use of `rb_sys` to normalize the Rust build environment.
|
|
25
|
+
|
|
26
|
+
* **gemspec:** Must include `spec.add_dependency "rb_sys"`.
|
|
27
|
+
* **extconf.rb:** Must use `create_rust_makefile` to defer compilation to Cargo while respecting Ruby's `mkmf` environment.
|
|
28
|
+
* **Cargo.toml:** Must use `crate-type = ["cdylib"]` to generate a shared object loadable by Ruby.
|
|
29
|
+
|
|
30
|
+
### 2. The Validation Standard: "The Ping Pong Test"
|
|
31
|
+
|
|
32
|
+
Before any feature is accepted, it must pass the **Ping Pong Test**. This test verifies the full round-trip capability of the architecture, proving that the Ractor bridge, Main Loop, and IPC are functional.
|
|
33
|
+
|
|
34
|
+
#### The Test Protocol
|
|
35
|
+
|
|
36
|
+
1. **Boot:** Ruby Main Ractor starts.
|
|
37
|
+
2. **Init:** Rust creates Window & WebView.
|
|
38
|
+
3. **Frontend Emit:** JS executes `window.ipc.postMessage("PING")`.
|
|
39
|
+
4. **Rust Bridge:** `Tokra::Native` shareable callback fires (on Main Thread).
|
|
40
|
+
5. **Port Send:** Main Ractor sends "PING" to Worker Ractor via `Ractor::Port`.
|
|
41
|
+
6. **Logic Processing:** Worker Ractor appends "PONG".
|
|
42
|
+
7. **Response Port:** Worker sends response back via response `Ractor::Port`.
|
|
43
|
+
8. **Proxy Wake:** Worker Ractor triggers `proxy.wake_up()`.
|
|
44
|
+
9. **Rust Wake:** `Tao` loop wakes, executes callback on Main Thread.
|
|
45
|
+
10. **Frontend Receive:** Main Ractor calls `webview.eval` to send "PINGPONG".
|
|
46
|
+
11. **Verify:** JS assertion confirms receipt of "PINGPONG".
|
|
47
|
+
|
|
48
|
+
#### Reference Implementation
|
|
49
|
+
|
|
50
|
+
```ruby
|
|
51
|
+
# test/integration/ping_pong_test.rb
|
|
52
|
+
# frozen_string_literal: true
|
|
53
|
+
|
|
54
|
+
require "tokra"
|
|
55
|
+
require "timeout"
|
|
56
|
+
|
|
57
|
+
class PingPongTest < Minitest::Test
|
|
58
|
+
def test_full_round_trip
|
|
59
|
+
Timeout.timeout(0.5) do # 500ms for CI stability
|
|
60
|
+
# Communication ports (explicit, not default)
|
|
61
|
+
ipc_port = Ractor::Port.new
|
|
62
|
+
response_port = Ractor::Port.new
|
|
63
|
+
|
|
64
|
+
# Worker Ractor - processes messages and responds
|
|
65
|
+
worker = Ractor.new(response_port) do |resp_port|
|
|
66
|
+
msg = Ractor.receive
|
|
67
|
+
resp_port << (msg + "PONG")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
event_loop = Tokra::Native::EventLoop.new
|
|
71
|
+
proxy = event_loop.create_proxy
|
|
72
|
+
result = nil
|
|
73
|
+
|
|
74
|
+
# IPC handler must be shareable
|
|
75
|
+
ipc_handler = Ractor.shareable_proc do |raw_msg|
|
|
76
|
+
ipc_port << raw_msg
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
window = Tokra::Native::Window.new(event_loop)
|
|
80
|
+
webview = Tokra::Native::WebView.new(
|
|
81
|
+
window,
|
|
82
|
+
"data:text/html,<script>window.ipc.postMessage('PING')</script>",
|
|
83
|
+
ipc_handler
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
event_loop.run do |event|
|
|
87
|
+
case event
|
|
88
|
+
when Tokra::Native::IpcEvent
|
|
89
|
+
worker << event.message
|
|
90
|
+
when Tokra::Native::WakeUpEvent
|
|
91
|
+
result = response_port.receive
|
|
92
|
+
webview.eval("window.result = '#{result}'")
|
|
93
|
+
break
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
assert_equal "PINGPONG", result
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Failure Condition:** If the app hangs, crashes, or times out (>500ms in CI), the build fails. This test MUST run in CI on Linux (headless), macOS, and Windows.
|
|
104
|
+
|
|
105
|
+
## Consequences
|
|
106
|
+
|
|
107
|
+
### Positive
|
|
108
|
+
|
|
109
|
+
* **Reliability:** `rb_sys` handles the complexity of finding `libclang` and linking Ruby headers.
|
|
110
|
+
* **Isolation Verification:** The Ping Pong test proves that objects are actually Ractor-safe (Shareable or Movable), preventing "Works in RSpec, Segfaults in Production" bugs.
|
|
111
|
+
* **Port Ownership:** Using explicit `Ractor::Port` makes message flow clear and prevents accidental cross-Ractor access.
|
|
112
|
+
|
|
113
|
+
### Negative
|
|
114
|
+
|
|
115
|
+
* **CI Complexity:** CI runners must have Rust, GTK-dev, and WebKit-dev headers installed.
|
|
116
|
+
* **Timeout Tuning:** The 500ms timeout may need adjustment for slower CI runners or first-run compilation.
|