decision_agent 0.1.1 → 0.1.3

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +234 -919
  3. data/bin/decision_agent +5 -5
  4. data/lib/decision_agent/agent.rb +19 -26
  5. data/lib/decision_agent/audit/null_adapter.rb +1 -2
  6. data/lib/decision_agent/decision.rb +3 -1
  7. data/lib/decision_agent/dsl/condition_evaluator.rb +4 -3
  8. data/lib/decision_agent/dsl/rule_parser.rb +4 -6
  9. data/lib/decision_agent/dsl/schema_validator.rb +27 -31
  10. data/lib/decision_agent/errors.rb +21 -6
  11. data/lib/decision_agent/evaluation.rb +3 -1
  12. data/lib/decision_agent/evaluation_validator.rb +78 -0
  13. data/lib/decision_agent/evaluators/json_rule_evaluator.rb +26 -0
  14. data/lib/decision_agent/evaluators/static_evaluator.rb +2 -6
  15. data/lib/decision_agent/monitoring/alert_manager.rb +282 -0
  16. data/lib/decision_agent/monitoring/dashboard/public/dashboard.css +381 -0
  17. data/lib/decision_agent/monitoring/dashboard/public/dashboard.js +471 -0
  18. data/lib/decision_agent/monitoring/dashboard/public/index.html +161 -0
  19. data/lib/decision_agent/monitoring/dashboard_server.rb +340 -0
  20. data/lib/decision_agent/monitoring/metrics_collector.rb +278 -0
  21. data/lib/decision_agent/monitoring/monitored_agent.rb +71 -0
  22. data/lib/decision_agent/monitoring/prometheus_exporter.rb +247 -0
  23. data/lib/decision_agent/replay/replay.rb +12 -22
  24. data/lib/decision_agent/scoring/base.rb +1 -1
  25. data/lib/decision_agent/scoring/consensus.rb +5 -5
  26. data/lib/decision_agent/scoring/weighted_average.rb +1 -1
  27. data/lib/decision_agent/version.rb +1 -1
  28. data/lib/decision_agent/versioning/activerecord_adapter.rb +141 -0
  29. data/lib/decision_agent/versioning/adapter.rb +100 -0
  30. data/lib/decision_agent/versioning/file_storage_adapter.rb +290 -0
  31. data/lib/decision_agent/versioning/version_manager.rb +127 -0
  32. data/lib/decision_agent/web/public/app.js +318 -0
  33. data/lib/decision_agent/web/public/index.html +56 -1
  34. data/lib/decision_agent/web/public/styles.css +219 -0
  35. data/lib/decision_agent/web/server.rb +169 -9
  36. data/lib/decision_agent.rb +11 -0
  37. data/lib/generators/decision_agent/install/install_generator.rb +40 -0
  38. data/lib/generators/decision_agent/install/templates/README +47 -0
  39. data/lib/generators/decision_agent/install/templates/migration.rb +37 -0
  40. data/lib/generators/decision_agent/install/templates/rule.rb +30 -0
  41. data/lib/generators/decision_agent/install/templates/rule_version.rb +66 -0
  42. data/spec/activerecord_thread_safety_spec.rb +553 -0
  43. data/spec/agent_spec.rb +13 -13
  44. data/spec/api_contract_spec.rb +16 -16
  45. data/spec/audit_adapters_spec.rb +3 -3
  46. data/spec/comprehensive_edge_cases_spec.rb +86 -86
  47. data/spec/dsl_validation_spec.rb +83 -83
  48. data/spec/edge_cases_spec.rb +23 -23
  49. data/spec/examples/feedback_aware_evaluator_spec.rb +7 -7
  50. data/spec/examples.txt +548 -0
  51. data/spec/issue_verification_spec.rb +685 -0
  52. data/spec/json_rule_evaluator_spec.rb +15 -15
  53. data/spec/monitoring/alert_manager_spec.rb +378 -0
  54. data/spec/monitoring/metrics_collector_spec.rb +281 -0
  55. data/spec/monitoring/monitored_agent_spec.rb +222 -0
  56. data/spec/monitoring/prometheus_exporter_spec.rb +242 -0
  57. data/spec/replay_edge_cases_spec.rb +58 -58
  58. data/spec/replay_spec.rb +11 -11
  59. data/spec/rfc8785_canonicalization_spec.rb +215 -0
  60. data/spec/scoring_spec.rb +1 -1
  61. data/spec/spec_helper.rb +9 -0
  62. data/spec/thread_safety_spec.rb +482 -0
  63. data/spec/thread_safety_spec.rb.broken +878 -0
  64. data/spec/versioning_spec.rb +777 -0
  65. data/spec/web_ui_rack_spec.rb +135 -0
  66. metadata +84 -11
@@ -0,0 +1,135 @@
1
+ require "spec_helper"
2
+ require "rack/test"
3
+ require_relative "../lib/decision_agent/web/server"
4
+
5
+ RSpec.describe "DecisionAgent Web UI Rack Integration" do
6
+ include Rack::Test::Methods
7
+
8
+ def app
9
+ DecisionAgent::Web::Server
10
+ end
11
+
12
+ describe "Rack interface" do
13
+ it "responds to .call for Rack compatibility" do
14
+ expect(DecisionAgent::Web::Server).to respond_to(:call)
15
+ end
16
+
17
+ it "serves the main page" do
18
+ get "/"
19
+ expect(last_response).to be_ok
20
+ expect(last_response.body).to include("DecisionAgent")
21
+ end
22
+
23
+ it "serves the health endpoint" do
24
+ get "/health"
25
+ expect(last_response).to be_ok
26
+ expect(last_response.content_type).to include("application/json")
27
+
28
+ json = JSON.parse(last_response.body)
29
+ expect(json["status"]).to eq("ok")
30
+ expect(json["version"]).to eq(DecisionAgent::VERSION)
31
+ end
32
+
33
+ it "validates rules via POST /api/validate" do
34
+ valid_rules = {
35
+ version: "1.0",
36
+ ruleset: "test_rules",
37
+ rules: [{
38
+ id: "test_rule",
39
+ if: { field: "amount", op: "gt", value: 100 },
40
+ then: { decision: "approve", weight: 0.9, reason: "Test" }
41
+ }]
42
+ }
43
+
44
+ post "/api/validate", valid_rules.to_json, { "CONTENT_TYPE" => "application/json" }
45
+
46
+ expect(last_response).to be_ok
47
+ json = JSON.parse(last_response.body)
48
+ expect(json["valid"]).to be true
49
+ end
50
+
51
+ it "returns error for invalid rules" do
52
+ invalid_rules = {
53
+ version: "1.0",
54
+ ruleset: "test_rules",
55
+ rules: [{
56
+ id: "bad_rule"
57
+ # Missing required fields
58
+ }]
59
+ }
60
+
61
+ post "/api/validate", invalid_rules.to_json, { "CONTENT_TYPE" => "application/json" }
62
+
63
+ expect(last_response.status).to eq(422)
64
+ json = JSON.parse(last_response.body)
65
+ expect(json["valid"]).to be false
66
+ expect(json["errors"]).to be_an(Array)
67
+ end
68
+
69
+ it "evaluates rules via POST /api/evaluate" do
70
+ rules = {
71
+ version: "1.0",
72
+ ruleset: "test_rules",
73
+ rules: [{
74
+ id: "high_value",
75
+ if: { field: "amount", op: "gt", value: 1000 },
76
+ then: { decision: "approve", weight: 0.9, reason: "High value" }
77
+ }]
78
+ }
79
+
80
+ payload = {
81
+ rules: rules,
82
+ context: { amount: 1500 }
83
+ }
84
+
85
+ post "/api/evaluate", payload.to_json, { "CONTENT_TYPE" => "application/json" }
86
+
87
+ expect(last_response).to be_ok
88
+ json = JSON.parse(last_response.body)
89
+ expect(json["success"]).to be true
90
+ expect(json["decision"]).to eq("approve")
91
+ expect(json["weight"]).to eq(0.9)
92
+ expect(json["reason"]).to eq("High value")
93
+ end
94
+
95
+ it "serves example rules" do
96
+ get "/api/examples"
97
+
98
+ expect(last_response).to be_ok
99
+ json = JSON.parse(last_response.body)
100
+ expect(json).to be_an(Array)
101
+ expect(json.length).to be > 0
102
+ expect(json.first).to have_key("name")
103
+ expect(json.first).to have_key("rules")
104
+ end
105
+
106
+ it "handles CORS preflight requests" do
107
+ options "/api/validate"
108
+
109
+ expect(last_response.status).to eq(200)
110
+ expect(last_response.headers["Access-Control-Allow-Origin"]).to eq("*")
111
+ expect(last_response.headers["Access-Control-Allow-Methods"]).to include("POST")
112
+ end
113
+ end
114
+
115
+ describe "Rails mounting compatibility" do
116
+ it "can be mounted in a Rack app" do
117
+ # Simulate a Rails-style mount
118
+ rack_app = Rack::Builder.new do
119
+ map "/decision_agent" do
120
+ run DecisionAgent::Web::Server
121
+ end
122
+ end
123
+
124
+ # Create a test session for the mounted app
125
+ test_session = Rack::Test::Session.new(Rack::MockSession.new(rack_app))
126
+
127
+ # Test that the health endpoint works when mounted
128
+ test_session.get "/decision_agent/health"
129
+ expect(test_session.last_response).to be_ok
130
+
131
+ json = JSON.parse(test_session.last_response.body)
132
+ expect(json["status"]).to eq("ok")
133
+ end
134
+ end
135
+ end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: decision_agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Aswin
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-12-19 00:00:00.000000000 Z
11
+ date: 2025-12-24 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json-canonicalization
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: sinatra
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -25,19 +39,19 @@ dependencies:
25
39
  - !ruby/object:Gem::Version
26
40
  version: '3.0'
27
41
  - !ruby/object:Gem::Dependency
28
- name: rspec
42
+ name: rack-test
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: '3.12'
47
+ version: '2.0'
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: '3.12'
54
+ version: '2.0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rake
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -52,11 +66,39 @@ dependencies:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
68
  version: '13.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.12'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.12'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.60'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.60'
55
97
  description: A production-grade decision agent that provides deterministic rule evaluation,
56
98
  conflict resolution, and full audit replay capabilities. Framework-agnostic and
57
99
  AI-optional.
58
100
  email:
59
- - samaswin87@gmail.com
101
+ - samaswin@gmail.com
60
102
  executables:
61
103
  - decision_agent
62
104
  extensions: []
@@ -77,9 +119,18 @@ files:
77
119
  - lib/decision_agent/dsl/schema_validator.rb
78
120
  - lib/decision_agent/errors.rb
79
121
  - lib/decision_agent/evaluation.rb
122
+ - lib/decision_agent/evaluation_validator.rb
80
123
  - lib/decision_agent/evaluators/base.rb
81
124
  - lib/decision_agent/evaluators/json_rule_evaluator.rb
82
125
  - lib/decision_agent/evaluators/static_evaluator.rb
126
+ - lib/decision_agent/monitoring/alert_manager.rb
127
+ - lib/decision_agent/monitoring/dashboard/public/dashboard.css
128
+ - lib/decision_agent/monitoring/dashboard/public/dashboard.js
129
+ - lib/decision_agent/monitoring/dashboard/public/index.html
130
+ - lib/decision_agent/monitoring/dashboard_server.rb
131
+ - lib/decision_agent/monitoring/metrics_collector.rb
132
+ - lib/decision_agent/monitoring/monitored_agent.rb
133
+ - lib/decision_agent/monitoring/prometheus_exporter.rb
83
134
  - lib/decision_agent/replay/replay.rb
84
135
  - lib/decision_agent/scoring/base.rb
85
136
  - lib/decision_agent/scoring/consensus.rb
@@ -87,10 +138,20 @@ files:
87
138
  - lib/decision_agent/scoring/threshold.rb
88
139
  - lib/decision_agent/scoring/weighted_average.rb
89
140
  - lib/decision_agent/version.rb
141
+ - lib/decision_agent/versioning/activerecord_adapter.rb
142
+ - lib/decision_agent/versioning/adapter.rb
143
+ - lib/decision_agent/versioning/file_storage_adapter.rb
144
+ - lib/decision_agent/versioning/version_manager.rb
90
145
  - lib/decision_agent/web/public/app.js
91
146
  - lib/decision_agent/web/public/index.html
92
147
  - lib/decision_agent/web/public/styles.css
93
148
  - lib/decision_agent/web/server.rb
149
+ - lib/generators/decision_agent/install/install_generator.rb
150
+ - lib/generators/decision_agent/install/templates/README
151
+ - lib/generators/decision_agent/install/templates/migration.rb
152
+ - lib/generators/decision_agent/install/templates/rule.rb
153
+ - lib/generators/decision_agent/install/templates/rule_version.rb
154
+ - spec/activerecord_thread_safety_spec.rb
94
155
  - spec/agent_spec.rb
95
156
  - spec/api_contract_spec.rb
96
157
  - spec/audit_adapters_spec.rb
@@ -98,12 +159,23 @@ files:
98
159
  - spec/context_spec.rb
99
160
  - spec/dsl_validation_spec.rb
100
161
  - spec/edge_cases_spec.rb
162
+ - spec/examples.txt
101
163
  - spec/examples/feedback_aware_evaluator_spec.rb
164
+ - spec/issue_verification_spec.rb
102
165
  - spec/json_rule_evaluator_spec.rb
166
+ - spec/monitoring/alert_manager_spec.rb
167
+ - spec/monitoring/metrics_collector_spec.rb
168
+ - spec/monitoring/monitored_agent_spec.rb
169
+ - spec/monitoring/prometheus_exporter_spec.rb
103
170
  - spec/replay_edge_cases_spec.rb
104
171
  - spec/replay_spec.rb
172
+ - spec/rfc8785_canonicalization_spec.rb
105
173
  - spec/scoring_spec.rb
106
174
  - spec/spec_helper.rb
175
+ - spec/thread_safety_spec.rb
176
+ - spec/thread_safety_spec.rb.broken
177
+ - spec/versioning_spec.rb
178
+ - spec/web_ui_rack_spec.rb
107
179
  homepage: https://github.com/samaswin87/decision_agent
108
180
  licenses:
109
181
  - MIT
@@ -111,7 +183,8 @@ metadata:
111
183
  homepage_uri: https://github.com/samaswin87/decision_agent
112
184
  source_code_uri: https://github.com/samaswin87/decision_agent
113
185
  changelog_uri: https://github.com/samaswin87/decision_agent/blob/main/CHANGELOG.md
114
- post_install_message:
186
+ rubygems_mfa_required: 'true'
187
+ post_install_message:
115
188
  rdoc_options: []
116
189
  require_paths:
117
190
  - lib
@@ -119,15 +192,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
119
192
  requirements:
120
193
  - - ">="
121
194
  - !ruby/object:Gem::Version
122
- version: 2.7.0
195
+ version: 3.0.0
123
196
  required_rubygems_version: !ruby/object:Gem::Requirement
124
197
  requirements:
125
198
  - - ">="
126
199
  - !ruby/object:Gem::Version
127
200
  version: '0'
128
201
  requirements: []
129
- rubygems_version: 3.0.3.1
130
- signing_key:
202
+ rubygems_version: 3.5.22
203
+ signing_key:
131
204
  specification_version: 4
132
205
  summary: Deterministic, explainable, auditable decision engine for Ruby
133
206
  test_files: []