ace-runtime 0.1.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 +7 -0
- data/.ace-defaults/runtime/config.yml +7 -0
- data/CHANGELOG.md +19 -0
- data/LICENSE +21 -0
- data/README.md +120 -0
- data/Rakefile +12 -0
- data/docs/usage.md +189 -0
- data/exe/ace-runtime +17 -0
- data/lib/ace/runtime/atoms/detector.rb +34 -0
- data/lib/ace/runtime/atoms/name_sanitizer.rb +34 -0
- data/lib/ace/runtime/atoms/send_contract.rb +160 -0
- data/lib/ace/runtime/cli/commands/send.rb +120 -0
- data/lib/ace/runtime/cli.rb +69 -0
- data/lib/ace/runtime/errors.rb +60 -0
- data/lib/ace/runtime/molecules/runtime_selector.rb +73 -0
- data/lib/ace/runtime/registry.rb +68 -0
- data/lib/ace/runtime/testing/adapter_contract.rb +597 -0
- data/lib/ace/runtime/testing/scripted_runtime.rb +224 -0
- data/lib/ace/runtime/testing.rb +9 -0
- data/lib/ace/runtime/version.rb +7 -0
- data/lib/ace/runtime.rb +102 -0
- metadata +194 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ace
|
|
4
|
+
module Runtime
|
|
5
|
+
module Testing
|
|
6
|
+
# Fixture-local signals. Adapters translate these at their
|
|
7
|
+
# boundary into the contract error model:
|
|
8
|
+
# FixtureUnavailable -> RuntimeUnavailableError
|
|
9
|
+
# FixtureStall -> SendStalledError
|
|
10
|
+
# FixtureTargetMissing -> TargetNotFoundError
|
|
11
|
+
class FixtureError < StandardError; end
|
|
12
|
+
class FixtureUnavailable < FixtureError; end
|
|
13
|
+
class FixtureStall < FixtureError; end
|
|
14
|
+
class FixtureTargetMissing < FixtureError; end
|
|
15
|
+
|
|
16
|
+
# In-memory terminal runtime used by the shared adapter contract
|
|
17
|
+
# suite. It models the native capabilities adapters bind to
|
|
18
|
+
# (windows, panes, raw text writes, named keys, capture, agent
|
|
19
|
+
# state) and records every mutation op in order so the suite can
|
|
20
|
+
# assert delivery ordering and rejection-before-transport.
|
|
21
|
+
#
|
|
22
|
+
# Real adapter suites bind their adapter to this same fixture via
|
|
23
|
+
# a thin transport bridge; the reference implementation is
|
|
24
|
+
# test/support/fake_runtime_adapter.rb in the ace-runtime gem.
|
|
25
|
+
class ScriptedRuntime
|
|
26
|
+
attr_reader :calls, :context, :windows, :panes
|
|
27
|
+
attr_accessor :unavailable
|
|
28
|
+
|
|
29
|
+
def initialize
|
|
30
|
+
@calls = []
|
|
31
|
+
@context = {in_runtime: true, session: "main", window: nil, pane: nil}
|
|
32
|
+
@windows = {}
|
|
33
|
+
@panes = {}
|
|
34
|
+
@unavailable = false
|
|
35
|
+
@stall_next_send = false
|
|
36
|
+
@window_seq = 0
|
|
37
|
+
@pane_seq = 0
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# --- test controls (never recorded) ---
|
|
41
|
+
|
|
42
|
+
def set_context(context)
|
|
43
|
+
@context = context
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def set_output(pane_id, text)
|
|
47
|
+
fetch_pane!(pane_id)[:output] = text
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def set_agent_state(pane_id, state)
|
|
51
|
+
fetch_pane!(pane_id)[:agent_state] = state
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def exit_pane(pane_id)
|
|
55
|
+
fetch_pane!(pane_id)[:alive] = false
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def stall_next_send!
|
|
59
|
+
@stall_next_send = true
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Silent setup mutator for pre-existing windows; adapter-driven
|
|
63
|
+
# creation goes through #create_window so it gets recorded.
|
|
64
|
+
def seed_window(name, root: "/", preset: nil)
|
|
65
|
+
@windows[name] = {
|
|
66
|
+
id: next_window_id, root: root, preset: preset, focused: false, panes: []
|
|
67
|
+
}
|
|
68
|
+
@windows[name][:id]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Silent setup mutator for pre-existing panes.
|
|
72
|
+
def seed_pane(window_name, alive: true, keep_alive: true)
|
|
73
|
+
pane_id = next_pane_id
|
|
74
|
+
@panes[pane_id] = {
|
|
75
|
+
window: window_name, alive: alive, keep_alive: keep_alive,
|
|
76
|
+
output: "", agent_state: nil
|
|
77
|
+
}
|
|
78
|
+
@windows.fetch(window_name)[:panes] << pane_id
|
|
79
|
+
pane_id
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# --- queries (never recorded) ---
|
|
83
|
+
|
|
84
|
+
def unavailable?
|
|
85
|
+
@unavailable
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def window_exists?(name)
|
|
89
|
+
@windows.key?(name)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def window_info(name)
|
|
93
|
+
@windows[name]
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def pane_exists?(pane_id)
|
|
97
|
+
@panes.key?(pane_id)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def alive?(pane_id)
|
|
101
|
+
fetch_pane!(pane_id)[:alive]
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def agent_state(pane_id)
|
|
105
|
+
fetch_pane!(pane_id)[:agent_state]
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# One-shot: a scripted stall means the submission was accepted
|
|
109
|
+
# but the target never started processing it.
|
|
110
|
+
def take_stall!
|
|
111
|
+
stall = @stall_next_send
|
|
112
|
+
@stall_next_send = false
|
|
113
|
+
stall
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# --- native mutation ops (recorded in order) ---
|
|
117
|
+
|
|
118
|
+
def create_window(name:, root:, preset: nil)
|
|
119
|
+
guard_available!
|
|
120
|
+
raise FixtureTargetMissing, "window '#{name}' already exists" if window_exists?(name)
|
|
121
|
+
|
|
122
|
+
record(:create_window, name: name, root: root, preset: preset)
|
|
123
|
+
@windows[name] = {
|
|
124
|
+
id: next_window_id, root: root, preset: preset, focused: false, panes: []
|
|
125
|
+
}
|
|
126
|
+
@windows[name][:id]
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def kill_window(name)
|
|
130
|
+
guard_available!
|
|
131
|
+
raise FixtureTargetMissing, "no window '#{name}'" unless window_exists?(name)
|
|
132
|
+
|
|
133
|
+
record(:kill_window, name: name)
|
|
134
|
+
@windows.delete(name)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def focus_window(name)
|
|
138
|
+
guard_available!
|
|
139
|
+
raise FixtureTargetMissing, "no window '#{name}'" unless window_exists?(name)
|
|
140
|
+
|
|
141
|
+
record(:focus_window, name: name)
|
|
142
|
+
@windows.each_value { |info| info[:focused] = false }
|
|
143
|
+
@windows[name][:focused] = true
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def split_window(window_name)
|
|
147
|
+
guard_available!
|
|
148
|
+
info = @windows[window_name]
|
|
149
|
+
raise FixtureTargetMissing, "no window '#{window_name}'" unless info
|
|
150
|
+
|
|
151
|
+
record(:split_window, window: window_name)
|
|
152
|
+
pane_id = next_pane_id
|
|
153
|
+
@panes[pane_id] = {
|
|
154
|
+
window: window_name, alive: true, keep_alive: false,
|
|
155
|
+
output: "", agent_state: nil
|
|
156
|
+
}
|
|
157
|
+
info[:panes] << pane_id
|
|
158
|
+
pane_id
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def set_keep_alive(pane_id, value)
|
|
162
|
+
guard_available!
|
|
163
|
+
fetch_pane!(pane_id)
|
|
164
|
+
|
|
165
|
+
record(:set_keep_alive, pane: pane_id, value: value)
|
|
166
|
+
@panes[pane_id][:keep_alive] = value
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def write_text(pane_id, text)
|
|
170
|
+
guard_available!
|
|
171
|
+
pane = fetch_pane!(pane_id)
|
|
172
|
+
|
|
173
|
+
raise FixtureStall, "target accepted the submission but never started processing" if take_stall!
|
|
174
|
+
|
|
175
|
+
record(:write_text, pane: pane_id, text: text)
|
|
176
|
+
pane[:output] = text
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def press_key(pane_id, key)
|
|
180
|
+
guard_available!
|
|
181
|
+
pane = fetch_pane!(pane_id)
|
|
182
|
+
|
|
183
|
+
raise FixtureStall, "target accepted the submission but never started processing" if take_stall!
|
|
184
|
+
|
|
185
|
+
record(:press_key, pane: pane_id, key: key)
|
|
186
|
+
pane[:alive] = false if key.to_s.match?(/\Aexit\z/i)
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def capture_output(pane_id, lines:)
|
|
190
|
+
guard_available!
|
|
191
|
+
output = fetch_pane!(pane_id)[:output]
|
|
192
|
+
output.lines.last([lines, 1].max).join
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
private
|
|
196
|
+
|
|
197
|
+
def record(op, **args)
|
|
198
|
+
@calls << {op: op}.merge(args)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def guard_available!
|
|
202
|
+
raise FixtureUnavailable, "runtime backend is not reachable" if @unavailable
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def fetch_pane!(pane_id)
|
|
206
|
+
pane = @panes[pane_id]
|
|
207
|
+
raise FixtureTargetMissing, "no pane '#{pane_id}'" unless pane
|
|
208
|
+
|
|
209
|
+
pane
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def next_window_id
|
|
213
|
+
@window_seq += 1
|
|
214
|
+
"w#{@window_seq}"
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def next_pane_id
|
|
218
|
+
@pane_seq += 1
|
|
219
|
+
"%#{@pane_seq}"
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Packaged adapter contract-test kit. Adapter packages require this in
|
|
4
|
+
# their own test helpers:
|
|
5
|
+
#
|
|
6
|
+
# require "ace/runtime/testing"
|
|
7
|
+
#
|
|
8
|
+
require_relative "testing/scripted_runtime"
|
|
9
|
+
require_relative "testing/adapter_contract"
|
data/lib/ace/runtime.rb
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "runtime/version"
|
|
4
|
+
require "ace/support/config"
|
|
5
|
+
|
|
6
|
+
# Define the error hierarchy before loading components (they raise these)
|
|
7
|
+
require_relative "runtime/errors"
|
|
8
|
+
|
|
9
|
+
require_relative "runtime/atoms/detector"
|
|
10
|
+
require_relative "runtime/atoms/name_sanitizer"
|
|
11
|
+
require_relative "runtime/atoms/send_contract"
|
|
12
|
+
require_relative "runtime/registry"
|
|
13
|
+
require_relative "runtime/molecules/runtime_selector"
|
|
14
|
+
|
|
15
|
+
module Ace
|
|
16
|
+
module Runtime
|
|
17
|
+
class << self
|
|
18
|
+
# Register a duck-typed adapter factory under a runtime name.
|
|
19
|
+
# Adapter packages call this from their
|
|
20
|
+
# lib/ace/runtime/adapters/<name>.rb entrypoint.
|
|
21
|
+
def register(name, factory = nil, &block)
|
|
22
|
+
registry.register(name, factory, &block)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def registry
|
|
26
|
+
@registry ||= Registry.new
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def reset_registry!
|
|
30
|
+
@registry = Registry.new
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def available
|
|
34
|
+
registry.available
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def registered?(name)
|
|
38
|
+
registry.registered?(name)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Resolve a runtime name to a registered adapter. Unknown names
|
|
42
|
+
# fail closed with UnknownRuntimeError listing the available
|
|
43
|
+
# runtimes.
|
|
44
|
+
def resolve(name)
|
|
45
|
+
registry.resolve(name)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Side-effect-free detection: :tmux, :herdr, or nil. tmux wins
|
|
49
|
+
# when both environments are live.
|
|
50
|
+
def detect(env: ENV)
|
|
51
|
+
Atoms::Detector.detect(env: env)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Shared window/tab naming policy.
|
|
55
|
+
def sanitize_name(name, fallback: Atoms::NameSanitizer::FALLBACK)
|
|
56
|
+
Atoms::NameSanitizer.call(name, fallback: fallback)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def gem_root
|
|
60
|
+
@gem_root ||= ::Gem.loaded_specs["ace-runtime"]&.gem_dir ||
|
|
61
|
+
File.expand_path("../..", __dir__)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def debug?
|
|
65
|
+
ENV["ACE_DEBUG"] == "1" || ENV["DEBUG"] == "1"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Configured runtime selection (key: `runtime`), merged through the
|
|
69
|
+
# ACE config cascade (project .ace/ > user ~/.ace/ > gem defaults).
|
|
70
|
+
def config
|
|
71
|
+
@config_mutex.synchronize do
|
|
72
|
+
@config ||= load_config
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def reset_config!
|
|
77
|
+
@config_mutex.synchronize do
|
|
78
|
+
@config = nil
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private
|
|
83
|
+
|
|
84
|
+
def load_config
|
|
85
|
+
resolver = Ace::Support::Config.create(
|
|
86
|
+
config_dir: ".ace",
|
|
87
|
+
defaults_dir: ".ace-defaults",
|
|
88
|
+
gem_path: gem_root
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
resolver.resolve_namespace("runtime").data
|
|
92
|
+
rescue StandardError => e
|
|
93
|
+
warn "ace-runtime: Could not load config: #{e.class} - #{e.message}" if debug?
|
|
94
|
+
{}
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
@config_mutex = Mutex.new
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
require_relative "runtime/cli"
|
metadata
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ace-runtime
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Michal Czyz
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 2026-09-29 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: ace-support-cli
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0.6'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0.6'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: ace-support-config
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0.18'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0.18'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: ace-support-core
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0.31'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0.31'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: ace-support-test-helpers
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0.14'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0.14'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: bundler
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '2.0'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '2.0'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: minitest
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - "~>"
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '5.0'
|
|
89
|
+
type: :development
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - "~>"
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '5.0'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: rake
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - "~>"
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '13.0'
|
|
103
|
+
type: :development
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - "~>"
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '13.0'
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: rubocop
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - "~>"
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '1.88'
|
|
117
|
+
type: :development
|
|
118
|
+
prerelease: false
|
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - "~>"
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '1.88'
|
|
124
|
+
- !ruby/object:Gem::Dependency
|
|
125
|
+
name: simplecov
|
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - "~>"
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: '0.22'
|
|
131
|
+
type: :development
|
|
132
|
+
prerelease: false
|
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - "~>"
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: '0.22'
|
|
138
|
+
description: 'One duck-typed intent API for terminal runtimes: adapter registry with
|
|
139
|
+
fail-closed resolution, side-effect-free detection, shared name sanitization, typed
|
|
140
|
+
errors, central send-matrix validation, the ace-runtime send callback CLI, and the
|
|
141
|
+
shared adapter contract-test suite.'
|
|
142
|
+
email:
|
|
143
|
+
- mc@cs3b.com
|
|
144
|
+
executables:
|
|
145
|
+
- ace-runtime
|
|
146
|
+
extensions: []
|
|
147
|
+
extra_rdoc_files: []
|
|
148
|
+
files:
|
|
149
|
+
- ".ace-defaults/runtime/config.yml"
|
|
150
|
+
- CHANGELOG.md
|
|
151
|
+
- LICENSE
|
|
152
|
+
- README.md
|
|
153
|
+
- Rakefile
|
|
154
|
+
- docs/usage.md
|
|
155
|
+
- exe/ace-runtime
|
|
156
|
+
- lib/ace/runtime.rb
|
|
157
|
+
- lib/ace/runtime/atoms/detector.rb
|
|
158
|
+
- lib/ace/runtime/atoms/name_sanitizer.rb
|
|
159
|
+
- lib/ace/runtime/atoms/send_contract.rb
|
|
160
|
+
- lib/ace/runtime/cli.rb
|
|
161
|
+
- lib/ace/runtime/cli/commands/send.rb
|
|
162
|
+
- lib/ace/runtime/errors.rb
|
|
163
|
+
- lib/ace/runtime/molecules/runtime_selector.rb
|
|
164
|
+
- lib/ace/runtime/registry.rb
|
|
165
|
+
- lib/ace/runtime/testing.rb
|
|
166
|
+
- lib/ace/runtime/testing/adapter_contract.rb
|
|
167
|
+
- lib/ace/runtime/testing/scripted_runtime.rb
|
|
168
|
+
- lib/ace/runtime/version.rb
|
|
169
|
+
homepage: https://github.com/cs3b/ace
|
|
170
|
+
licenses:
|
|
171
|
+
- MIT
|
|
172
|
+
metadata:
|
|
173
|
+
allowed_push_host: https://rubygems.org
|
|
174
|
+
homepage_uri: https://github.com/cs3b/ace
|
|
175
|
+
source_code_uri: https://github.com/cs3b/ace/tree/main/ace-runtime/
|
|
176
|
+
changelog_uri: https://github.com/cs3b/ace/blob/main/ace-runtime/CHANGELOG.md
|
|
177
|
+
rdoc_options: []
|
|
178
|
+
require_paths:
|
|
179
|
+
- lib
|
|
180
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
181
|
+
requirements:
|
|
182
|
+
- - ">="
|
|
183
|
+
- !ruby/object:Gem::Version
|
|
184
|
+
version: 3.2.0
|
|
185
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
186
|
+
requirements:
|
|
187
|
+
- - ">="
|
|
188
|
+
- !ruby/object:Gem::Version
|
|
189
|
+
version: '0'
|
|
190
|
+
requirements: []
|
|
191
|
+
rubygems_version: 3.6.9
|
|
192
|
+
specification_version: 4
|
|
193
|
+
summary: Runtime-neutral terminal intent contract for ACE
|
|
194
|
+
test_files: []
|