regolith 0.1.33 → 0.3.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/README.md +19 -0
- data/bin/regolith +2 -0
- data/examples/incident-triage-rails/.gitignore +7 -0
- data/examples/incident-triage-rails/.mcp.json +8 -0
- data/examples/incident-triage-rails/AGENTS.md +8 -0
- data/examples/incident-triage-rails/Gemfile +4 -0
- data/examples/incident-triage-rails/README.md +37 -0
- data/examples/incident-triage-rails/Rakefile +2 -0
- data/examples/incident-triage-rails/app/controllers/incidents_controller.rb +29 -0
- data/examples/incident-triage-rails/app/services/incident_selector.rb +12 -0
- data/examples/incident-triage-rails/bin/rails +4 -0
- data/examples/incident-triage-rails/config/application.rb +12 -0
- data/examples/incident-triage-rails/config/boot.rb +2 -0
- data/examples/incident-triage-rails/config/environment.rb +2 -0
- data/examples/incident-triage-rails/config/initializers/arbiter.rb +5 -0
- data/examples/incident-triage-rails/config/initializers/incident_triage.rb +10 -0
- data/examples/incident-triage-rails/config/puma.rb +2 -0
- data/examples/incident-triage-rails/config/routes.rb +4 -0
- data/examples/incident-triage-rails/test/incident_selector_test.rb +25 -0
- data/lib/regolith/arbiter_option.rb +101 -0
- data/lib/regolith/cli.rb +40 -0
- data/lib/regolith/version.rb +1 -1
- data/regolith.gemspec +30 -36
- metadata +21 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5ca5fd012fc314627e7966165ec9aba5fc8f1223ce6bf307e5814b7ba28aa62d
|
|
4
|
+
data.tar.gz: 46fa4df36646b204ea2f69e12869e57856bdeb760ae06f5c8e294156e4a176ea
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 18d41ae3be387964bf9415f835422bd0ca061c37c47327e143edabb62c4b13ceeda11bb0c63b1d7adaf850cf6dab1c0c7b9c13ca04577d1ed8e7b16682447557
|
|
7
|
+
data.tar.gz: fc929df648d3f51d12a623482c6c0e519a01f9d4866a92b7d10b9efe768c85369d1ee5a237740047222077cb10e2164d4c598fb8968fbd55525ac64f5f8e1e20
|
data/README.md
CHANGED
|
@@ -208,3 +208,22 @@ Designed to make distributed systems feel human
|
|
|
208
208
|
|
|
209
209
|
Regolith: Because microservices shouldn't be micro-management.
|
|
210
210
|
Built with ❤️ for developers who want to focus on features, not infrastructure.
|
|
211
|
+
|
|
212
|
+
## ARBITER control flow (0.3.0)
|
|
213
|
+
|
|
214
|
+
The optional ARBITER integration ranks a finite set of actions with remote, deterministic measurement. The Regolith generator and existing services work without it.
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
gem install regolith
|
|
218
|
+
regolith new incident_platform --with arbiter
|
|
219
|
+
cd incident_platform
|
|
220
|
+
regolith generate service incidents
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
The option creates `.mcp.json` (GRIP remote endpoint), `AGENTS.md` (authority and control-flow rules), `config/arbiter.yml`, and adds `arbiter-gem` plus an initializer to newly generated Rails services. It never installs a native ARBITER binary.
|
|
224
|
+
|
|
225
|
+
Rails demo: [Incident triage — ranked next actions](examples/incident-triage-rails/README.md).
|
|
226
|
+
|
|
227
|
+
`config/initializers/incident_triage.rb` establishes the field; comparison is performed per request, not on boot. Authorization remains external to measurement. API credentials are supplied by `ARBITER_API_KEY` or `GRIP_API_KEY` and are never written to the project.
|
|
228
|
+
|
|
229
|
+
The `.mcp.json` GRIP remote endpoint must be checked against the MCP host and currently deployed service before production use. ARBITER HTTP 402 means payment is required; no wallet authorization is performed automatically.
|
data/bin/regolith
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Incident triage / ARBITER policy
|
|
2
|
+
|
|
3
|
+
Use ARBITER to rank only actions that the application has permitted.
|
|
4
|
+
Do not pass an action to measurement if execution of that action is prohibited.
|
|
5
|
+
Do not execute actions in this demo. Any production execution needs a separate commit/authorization check.
|
|
6
|
+
Never trust browser-supplied boolean flags as authorization in production.
|
|
7
|
+
No paid ARBITER calls during initializer evaluation or application boot.
|
|
8
|
+
Do not fabricate a winning action if the API returns HTTP 402 or an invalid response.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Incident triage — Regolith + ARBITER
|
|
2
|
+
|
|
3
|
+
A standalone Rails 7.2 API example of *The Last Conditional*: rank a fixed set of explicitly permitted incident actions using the remote ARBITER service. No local ARBITER binary.
|
|
4
|
+
|
|
5
|
+
The initializer (`config/initializers/incident_triage.rb`) defines a finite field of action descriptions, and the ARBITER initializer configures the client. **Neither calls the network on boot.** `IncidentSelector.decide` performs measurement only when a request arrives.
|
|
6
|
+
|
|
7
|
+
## Run
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
bundle install
|
|
11
|
+
export ARBITER_API_KEY='your-funded-GRIP-credit-key'
|
|
12
|
+
bundle exec rails server
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Call the endpoint:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
curl -sS http://localhost:3000/health
|
|
19
|
+
curl -sS http://localhost:3000/triage \
|
|
20
|
+
-H 'content-type: application/json' \
|
|
21
|
+
-d '{"incident":"Checkout API returning 502 after deployment"}'
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Expected: JSON with `selected`, `ranking`, `permitted`, and `executed: false` on a successful authenticated ARBITER comparison. No result values are invented or hardcoded. The live API key header and ranking response shape must be verified against the deployed GRIP gateway before production use.
|
|
25
|
+
|
|
26
|
+
For demonstration purposes, two low-impact actions are always eligible; two high-impact actions are added only by request flags. **Those flags are not production authorization.** Replace the demonstration policy with an authenticated service policy and revalidate it at commitment. No action is ever executed by this example.
|
|
27
|
+
|
|
28
|
+
`config/initializers/incident_triage.rb` defines candidate strings, `app/services/incident_selector.rb` invokes `Arbiter::Flow.decide`, and `app/controllers/incidents_controller.rb` exposes a read-only decision endpoint. The example can run as a standalone Rails API service or be adapted into a Regolith-generated service.
|
|
29
|
+
|
|
30
|
+
MCP client config is in `.mcp.json` and points to GRIP's advertised MCP endpoint. Endpoint connectivity still needs verification in the target MCP host.
|
|
31
|
+
|
|
32
|
+
## Security
|
|
33
|
+
|
|
34
|
+
- Never commit ARBITER credentials.
|
|
35
|
+
- Do not treat ARBITER scores as authorization.
|
|
36
|
+
- Treat 402 as a payment requirement, not permission to spend.
|
|
37
|
+
- This example never auto-executes selected actions.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
class IncidentsController < ActionController::API
|
|
3
|
+
def health
|
|
4
|
+
render json: { status: "ok", measurement: "not_run" }
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def triage
|
|
8
|
+
description = params.require(:incident).to_s
|
|
9
|
+
if description.strip.empty?
|
|
10
|
+
return render json: { error: "incident cannot be empty" }, status: :unprocessable_entity
|
|
11
|
+
end
|
|
12
|
+
# Application policy sets permissible candidates independently of measurement.
|
|
13
|
+
# This is a sample policy, NOT production authorization logic.
|
|
14
|
+
allowed = %i[investigate_logs open_incident]
|
|
15
|
+
allowed << :page_oncall if params[:oncall_authorized] == true
|
|
16
|
+
allowed << :isolate_instance if params[:isolation_authorized] == true
|
|
17
|
+
result = IncidentSelector.decide(description: description, allowed: allowed)
|
|
18
|
+
render json: { selected: result.fetch(:action), ranking: result.fetch(:ranking),
|
|
19
|
+
permitted: result.fetch(:permitted_actions), executed: false }
|
|
20
|
+
rescue Arbiter::PaymentRequired
|
|
21
|
+
render json: { error: "ARBITER credits or x402 authorization required" }, status: :payment_required
|
|
22
|
+
rescue Arbiter::Unauthorized
|
|
23
|
+
render json: { error: "ARBITER authentication failed" }, status: :bad_gateway
|
|
24
|
+
rescue Arbiter::Error => e
|
|
25
|
+
render json: { error: "ARBITER measurement failed", detail: e.class.name }, status: :bad_gateway
|
|
26
|
+
rescue ActionController::ParameterMissing, ArgumentError
|
|
27
|
+
render json: { error: "incident and at least two permitted actions are required" }, status: :unprocessable_entity
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
class IncidentSelector
|
|
3
|
+
def self.decide(description:, allowed:, client: Arbiter.client)
|
|
4
|
+
approved = IncidentTriage::ACTION_FIELD.select { |key, _| allowed.include?(key) }
|
|
5
|
+
raise ArgumentError, "At least two permitted actions required" if approved.length < 2
|
|
6
|
+
# :run is required by the gem, but no action is executed by decide().
|
|
7
|
+
actions = approved.transform_values do |text|
|
|
8
|
+
{ description: text, run: -> { raise "Execution is disabled in this demo" } }
|
|
9
|
+
end
|
|
10
|
+
Arbiter::Flow.decide(intent: description, actions: actions, client: client)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require_relative "boot"
|
|
2
|
+
require "rails"
|
|
3
|
+
require "action_controller/railtie"
|
|
4
|
+
Bundler.require(*Rails.groups)
|
|
5
|
+
module IncidentTriage
|
|
6
|
+
class Application < Rails::Application
|
|
7
|
+
config.load_defaults 7.2
|
|
8
|
+
config.api_only = true
|
|
9
|
+
config.eager_load = false
|
|
10
|
+
config.secret_key_base = ENV.fetch("SECRET_KEY_BASE", "demo-only-do-not-deploy-with-this-value")
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# The finite action field is defined at boot; ranking occurs only on request.
|
|
3
|
+
module IncidentTriage
|
|
4
|
+
ACTION_FIELD = {
|
|
5
|
+
investigate_logs: "Inspect service logs and recent deployment changes",
|
|
6
|
+
open_incident: "Open an incident ticket and assign an investigation owner",
|
|
7
|
+
page_oncall: "Page the authorized on-call engineer for active service disruption",
|
|
8
|
+
isolate_instance: "Isolate a verified unhealthy instance after authorization"
|
|
9
|
+
}.freeze
|
|
10
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "minitest/autorun"
|
|
3
|
+
require "arbiter"
|
|
4
|
+
require_relative "../config/initializers/incident_triage"
|
|
5
|
+
require_relative "../app/services/incident_selector"
|
|
6
|
+
class IncidentSelectorTest < Minitest::Test
|
|
7
|
+
FakeClient = Struct.new(:calls) do
|
|
8
|
+
def compare(query:, candidates:, top_k: nil)
|
|
9
|
+
calls << { query: query, candidates: candidates, top_k: top_k }
|
|
10
|
+
{ "results" => [{ "index" => 1, "score" => 0.8 }, { "index" => 0, "score" => 0.2 }] }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
def test_only_allowed_actions_enter_comparison
|
|
14
|
+
fake = FakeClient.new([])
|
|
15
|
+
outcome = IncidentSelector.decide(description: "5xx", allowed: %i[investigate_logs open_incident], client: fake)
|
|
16
|
+
assert_equal :open_incident, outcome.fetch(:action)
|
|
17
|
+
assert_equal 2, fake.calls[0][:candidates].length
|
|
18
|
+
refute_includes fake.calls[0][:candidates], IncidentTriage::ACTION_FIELD.fetch(:isolate_instance)
|
|
19
|
+
end
|
|
20
|
+
def test_requires_two_allowed_actions
|
|
21
|
+
assert_raises(ArgumentError) do
|
|
22
|
+
IncidentSelector.decide(description: "5xx", allowed: [:open_incident], client: FakeClient.new([]))
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "json"
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "yaml"
|
|
5
|
+
|
|
6
|
+
module Regolith
|
|
7
|
+
# Additive CLI support, preserving Regolith 0.2's existing generator and arguments.
|
|
8
|
+
module ArbiterOption
|
|
9
|
+
module_function
|
|
10
|
+
|
|
11
|
+
def prepare!(argv, cwd: Dir.pwd)
|
|
12
|
+
if argv[0] == "new" && (index = argv.index("--with"))
|
|
13
|
+
raise ArgumentError, "--with requires 'arbiter'" unless argv[index + 1] == "arbiter"
|
|
14
|
+
argv.slice!(index, 2)
|
|
15
|
+
name = argv[1]
|
|
16
|
+
raise ArgumentError, "usage: regolith new APP_NAME --with arbiter" unless name && !name.start_with?("-")
|
|
17
|
+
destination = File.expand_path(name, cwd)
|
|
18
|
+
at_exit do
|
|
19
|
+
next unless success?
|
|
20
|
+
if File.directory?(destination) && File.file?(File.join(destination, "config/regolith.yml"))
|
|
21
|
+
install_project!(destination)
|
|
22
|
+
warn "REGOLITH ARBITER: installed in #{destination}"
|
|
23
|
+
else
|
|
24
|
+
warn "REGOLITH ARBITER: original generator did not produce expected config/regolith.yml; no overlay applied"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
elsif argv[0..1] == ["generate", "service"]
|
|
28
|
+
root = File.expand_path(cwd)
|
|
29
|
+
at_exit do
|
|
30
|
+
next unless success?
|
|
31
|
+
install_services!(root) if File.file?(File.join(root, "config/arbiter.yml"))
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
argv
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def success?
|
|
38
|
+
exc = $!
|
|
39
|
+
exc.nil? || (exc.is_a?(SystemExit) && exc.success?)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def install_project!(root)
|
|
43
|
+
config = File.join(root, "config")
|
|
44
|
+
FileUtils.mkdir_p(config)
|
|
45
|
+
write_unless_exists(File.join(config, "arbiter.yml"), <<~YAML)
|
|
46
|
+
# ARBITER is optional; remote engine only. No local binary or field.
|
|
47
|
+
enabled: true
|
|
48
|
+
gem: arbiter-gem
|
|
49
|
+
endpoint: https://api.grip.fyi
|
|
50
|
+
YAML
|
|
51
|
+
write_unless_exists(File.join(root, ".mcp.json"), JSON.pretty_generate({
|
|
52
|
+
"mcpServers" => { "grip" => { "type" => "http", "url" => "https://grip.fyi/mcp" } }
|
|
53
|
+
}) + "\n")
|
|
54
|
+
write_unless_exists(File.join(root, "AGENTS.md"), <<~POLICY)
|
|
55
|
+
# ARBITER — control-flow policy
|
|
56
|
+
|
|
57
|
+
- Use `arbiter-gem` for deterministic ordering of explicitly permitted action descriptions.
|
|
58
|
+
- Do not use ARBITER to establish authorization, eligibility, policy, or transaction validity.
|
|
59
|
+
- Construct the candidate set from actions already permitted by the application.
|
|
60
|
+
- Revalidate authorization and mutable constraints at the execution or commitment boundary.
|
|
61
|
+
- Use `Arbiter.decide` for ranking only. Use `Arbiter.dispatch` only for intentional execution.
|
|
62
|
+
- Never add model-generated actions to the permitted candidate set.
|
|
63
|
+
- Never call a paid endpoint during Rails boot or from an initializer.
|
|
64
|
+
- Treat HTTP 402 and connectivity failures as errors; do not invent a winning action.
|
|
65
|
+
- Keep API credentials in environment variables, not in source or MCP config.
|
|
66
|
+
- The remote GRIP MCP URL is optional and needs client-side connectivity verification.
|
|
67
|
+
POLICY
|
|
68
|
+
install_services!(root)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def install_services!(root)
|
|
72
|
+
Dir.glob(File.join(root, "services", "*", "Gemfile")).each do |gemfile|
|
|
73
|
+
service_root = File.dirname(gemfile)
|
|
74
|
+
next unless File.directory?(File.join(service_root, "config"))
|
|
75
|
+
add_gem(gemfile)
|
|
76
|
+
init = File.join(service_root, "config/initializers/arbiter.rb")
|
|
77
|
+
write_unless_exists(init, <<~RUBY)
|
|
78
|
+
# frozen_string_literal: true
|
|
79
|
+
# No network calls during initialization. Configuration only.
|
|
80
|
+
require "arbiter"
|
|
81
|
+
Arbiter.configure(
|
|
82
|
+
api_key: ENV["ARBITER_API_KEY"] || ENV["GRIP_API_KEY"],
|
|
83
|
+
base_url: ENV.fetch("ARBITER_BASE_URL", "https://api.grip.fyi")
|
|
84
|
+
)
|
|
85
|
+
RUBY
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def add_gem(path)
|
|
90
|
+
gemfile = File.read(path)
|
|
91
|
+
return if gemfile.match?(/^\s*gem\s+["']arbiter-gem["']/)
|
|
92
|
+
File.open(path, "a") { |f| f.write("\n# ARBITER remote measurement (Regolith optional integration)\ngem \"arbiter-gem\", \"~> 0.1\"\n") }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def write_unless_exists(path, content)
|
|
96
|
+
return if File.exist?(path)
|
|
97
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
98
|
+
File.write(path, content)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
data/lib/regolith/cli.rb
CHANGED
|
@@ -315,6 +315,46 @@ module Regolith
|
|
|
315
315
|
File.write(app_rb_path, app_rb_content)
|
|
316
316
|
end
|
|
317
317
|
|
|
318
|
+
def patch_database_yml(service_dir, service_name)
|
|
319
|
+
database_yml_path = "#{service_dir}/config/database.yml"
|
|
320
|
+
|
|
321
|
+
database_config = <<~YAML
|
|
322
|
+
default: &default
|
|
323
|
+
adapter: postgresql
|
|
324
|
+
encoding: unicode
|
|
325
|
+
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
|
|
326
|
+
host: <%= ENV.fetch('POSTGRES_HOST', 'localhost') %>
|
|
327
|
+
port: <%= ENV.fetch('POSTGRES_PORT', 5432) %>
|
|
328
|
+
database: <%= ENV.fetch('POSTGRES_DB', '#{service_name}_development') %>
|
|
329
|
+
username: <%= ENV.fetch('POSTGRES_USER', 'postgres') %>
|
|
330
|
+
password: <%= ENV.fetch('POSTGRES_PASSWORD', 'password') %>
|
|
331
|
+
|
|
332
|
+
development:
|
|
333
|
+
<<: *default
|
|
334
|
+
|
|
335
|
+
test:
|
|
336
|
+
<<: *default
|
|
337
|
+
database: <%= ENV.fetch('POSTGRES_DB', '#{service_name}_development') %>_test
|
|
338
|
+
|
|
339
|
+
production:
|
|
340
|
+
<<: *default
|
|
341
|
+
url: <%= ENV['DATABASE_URL'] %>
|
|
342
|
+
YAML
|
|
343
|
+
|
|
344
|
+
File.write(database_yml_path, database_config)
|
|
345
|
+
puts "🔧 Updated database.yml for PostgreSQL"
|
|
346
|
+
|
|
347
|
+
# Also check if there are any environment-specific configs that might override this
|
|
348
|
+
dev_config_path = "#{service_dir}/config/environments/development.rb"
|
|
349
|
+
if File.exist?(dev_config_path)
|
|
350
|
+
dev_config = File.read(dev_config_path)
|
|
351
|
+
# Remove any SQLite references
|
|
352
|
+
dev_config.gsub!(/config\.active_record\.database_selector.*?\n/, '')
|
|
353
|
+
dev_config.gsub!(/config\.active_record\.database_resolver.*?\n/, '')
|
|
354
|
+
File.write(dev_config_path, dev_config)
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
|
|
318
358
|
def start_server
|
|
319
359
|
unless File.exist?('docker-compose.yml')
|
|
320
360
|
puts "❌ Error: Not in a Regolith app directory"
|
data/lib/regolith/version.rb
CHANGED
data/regolith.gemspec
CHANGED
|
@@ -1,37 +1,31 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
Gem::Specification.new do |
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
spec.add_dependency "activesupport", ">= 6.0"
|
|
32
|
-
spec.add_dependency "activemodel", ">= 6.0"
|
|
33
|
-
|
|
34
|
-
# Development dependencies
|
|
35
|
-
spec.add_development_dependency "rspec", "~> 3.0"
|
|
36
|
-
spec.add_development_dependency "rake", "~> 13.0"
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
# stub: regolith 0.2.0 ruby lib
|
|
3
|
+
|
|
4
|
+
Gem::Specification.new do |s|
|
|
5
|
+
s.name = "regolith".freeze
|
|
6
|
+
s.version = "0.3.0".freeze
|
|
7
|
+
|
|
8
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
|
9
|
+
s.metadata = { "changelog_uri" => "https://github.com/ziolndr/regolith/blob/main/CHANGELOG.md", "homepage_uri" => "https://regolith.bio", "source_code_uri" => "https://github.com/ziolndr/regolith" } if s.respond_to? :metadata=
|
|
10
|
+
s.require_paths = ["lib".freeze]
|
|
11
|
+
s.authors = ["Regolith Team".freeze]
|
|
12
|
+
s.date = "2025-08-11"
|
|
13
|
+
s.description = "Generate and orchestrate Rails microservices with zero setup using Docker + PostgreSQL.".freeze
|
|
14
|
+
s.email = ["info@regolith.bio".freeze]
|
|
15
|
+
s.executables = ["regolith".freeze]
|
|
16
|
+
s.files = ["CHANGELOG.md".freeze, "LICENSE".freeze, "README.md".freeze, "bin/regolith".freeze, "lib/regolith.rb".freeze, "lib/regolith/cli.rb".freeze, "lib/regolith/regolith_association.rb".freeze, "lib/regolith/regolith_record.rb".freeze, "lib/regolith/service_client.rb".freeze, "lib/regolith/version.rb".freeze, "regolith.gemspec".freeze]
|
|
17
|
+
s.homepage = "https://regolith.bio".freeze
|
|
18
|
+
s.licenses = ["MIT".freeze]
|
|
19
|
+
s.required_ruby_version = Gem::Requirement.new(">= 2.7.0".freeze)
|
|
20
|
+
s.rubygems_version = "3.3.15".freeze
|
|
21
|
+
s.summary = "Rails microservices. Zero setup. Docker + PostgreSQL".freeze
|
|
22
|
+
|
|
23
|
+
s.specification_version = 4
|
|
24
|
+
|
|
25
|
+
s.add_runtime_dependency(%q<activesupport>.freeze, [">= 6.0".freeze])
|
|
26
|
+
s.add_runtime_dependency(%q<activemodel>.freeze, [">= 6.0".freeze])
|
|
27
|
+
s.add_development_dependency(%q<rspec>.freeze, ["~> 3.0".freeze])
|
|
28
|
+
s.add_development_dependency(%q<rake>.freeze, ["~> 13.0".freeze])
|
|
29
|
+
# Regolith 0.3 ARBITER optional integration and example.
|
|
30
|
+
s.files = (Array(s.files) + (Dir["lib/regolith/arbiter_option.rb", "README.md"] + Dir.glob("examples/incident-triage-rails/**/*", File::FNM_DOTMATCH))).uniq.select { |path| File.file?(path) }
|
|
37
31
|
end
|
metadata
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: regolith
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Regolith Team
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
10
|
date: 2025-08-11 00:00:00.000000000 Z
|
|
@@ -79,7 +78,25 @@ files:
|
|
|
79
78
|
- LICENSE
|
|
80
79
|
- README.md
|
|
81
80
|
- bin/regolith
|
|
81
|
+
- examples/incident-triage-rails/.gitignore
|
|
82
|
+
- examples/incident-triage-rails/.mcp.json
|
|
83
|
+
- examples/incident-triage-rails/AGENTS.md
|
|
84
|
+
- examples/incident-triage-rails/Gemfile
|
|
85
|
+
- examples/incident-triage-rails/README.md
|
|
86
|
+
- examples/incident-triage-rails/Rakefile
|
|
87
|
+
- examples/incident-triage-rails/app/controllers/incidents_controller.rb
|
|
88
|
+
- examples/incident-triage-rails/app/services/incident_selector.rb
|
|
89
|
+
- examples/incident-triage-rails/bin/rails
|
|
90
|
+
- examples/incident-triage-rails/config/application.rb
|
|
91
|
+
- examples/incident-triage-rails/config/boot.rb
|
|
92
|
+
- examples/incident-triage-rails/config/environment.rb
|
|
93
|
+
- examples/incident-triage-rails/config/initializers/arbiter.rb
|
|
94
|
+
- examples/incident-triage-rails/config/initializers/incident_triage.rb
|
|
95
|
+
- examples/incident-triage-rails/config/puma.rb
|
|
96
|
+
- examples/incident-triage-rails/config/routes.rb
|
|
97
|
+
- examples/incident-triage-rails/test/incident_selector_test.rb
|
|
82
98
|
- lib/regolith.rb
|
|
99
|
+
- lib/regolith/arbiter_option.rb
|
|
83
100
|
- lib/regolith/cli.rb
|
|
84
101
|
- lib/regolith/regolith_association.rb
|
|
85
102
|
- lib/regolith/regolith_record.rb
|
|
@@ -90,10 +107,9 @@ homepage: https://regolith.bio
|
|
|
90
107
|
licenses:
|
|
91
108
|
- MIT
|
|
92
109
|
metadata:
|
|
110
|
+
changelog_uri: https://github.com/ziolndr/regolith/blob/main/CHANGELOG.md
|
|
93
111
|
homepage_uri: https://regolith.bio
|
|
94
112
|
source_code_uri: https://github.com/ziolndr/regolith
|
|
95
|
-
changelog_uri: https://github.com/ziolndr/regolith/blob/main/CHANGELOG.md
|
|
96
|
-
post_install_message:
|
|
97
113
|
rdoc_options: []
|
|
98
114
|
require_paths:
|
|
99
115
|
- lib
|
|
@@ -108,8 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
108
124
|
- !ruby/object:Gem::Version
|
|
109
125
|
version: '0'
|
|
110
126
|
requirements: []
|
|
111
|
-
rubygems_version:
|
|
112
|
-
signing_key:
|
|
127
|
+
rubygems_version: 4.0.3
|
|
113
128
|
specification_version: 4
|
|
114
129
|
summary: Rails microservices. Zero setup. Docker + PostgreSQL
|
|
115
130
|
test_files: []
|