decision_agent 0.1.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.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +1060 -0
  4. data/bin/decision_agent +104 -0
  5. data/lib/decision_agent/agent.rb +147 -0
  6. data/lib/decision_agent/audit/adapter.rb +9 -0
  7. data/lib/decision_agent/audit/logger_adapter.rb +27 -0
  8. data/lib/decision_agent/audit/null_adapter.rb +8 -0
  9. data/lib/decision_agent/context.rb +42 -0
  10. data/lib/decision_agent/decision.rb +51 -0
  11. data/lib/decision_agent/dsl/condition_evaluator.rb +133 -0
  12. data/lib/decision_agent/dsl/rule_parser.rb +36 -0
  13. data/lib/decision_agent/dsl/schema_validator.rb +275 -0
  14. data/lib/decision_agent/errors.rb +62 -0
  15. data/lib/decision_agent/evaluation.rb +52 -0
  16. data/lib/decision_agent/evaluators/base.rb +15 -0
  17. data/lib/decision_agent/evaluators/json_rule_evaluator.rb +51 -0
  18. data/lib/decision_agent/evaluators/static_evaluator.rb +31 -0
  19. data/lib/decision_agent/replay/replay.rb +147 -0
  20. data/lib/decision_agent/scoring/base.rb +19 -0
  21. data/lib/decision_agent/scoring/consensus.rb +40 -0
  22. data/lib/decision_agent/scoring/max_weight.rb +16 -0
  23. data/lib/decision_agent/scoring/threshold.rb +40 -0
  24. data/lib/decision_agent/scoring/weighted_average.rb +26 -0
  25. data/lib/decision_agent/version.rb +3 -0
  26. data/lib/decision_agent/web/public/app.js +580 -0
  27. data/lib/decision_agent/web/public/index.html +190 -0
  28. data/lib/decision_agent/web/public/styles.css +558 -0
  29. data/lib/decision_agent/web/server.rb +255 -0
  30. data/lib/decision_agent.rb +29 -0
  31. data/spec/agent_spec.rb +249 -0
  32. data/spec/api_contract_spec.rb +430 -0
  33. data/spec/audit_adapters_spec.rb +74 -0
  34. data/spec/comprehensive_edge_cases_spec.rb +1777 -0
  35. data/spec/context_spec.rb +84 -0
  36. data/spec/dsl_validation_spec.rb +648 -0
  37. data/spec/edge_cases_spec.rb +353 -0
  38. data/spec/examples/feedback_aware_evaluator_spec.rb +460 -0
  39. data/spec/json_rule_evaluator_spec.rb +587 -0
  40. data/spec/replay_edge_cases_spec.rb +699 -0
  41. data/spec/replay_spec.rb +210 -0
  42. data/spec/scoring_spec.rb +225 -0
  43. data/spec/spec_helper.rb +28 -0
  44. metadata +133 -0
@@ -0,0 +1,84 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe DecisionAgent::Context do
4
+ describe "#initialize" do
5
+ it "accepts a hash and freezes it" do
6
+ context = DecisionAgent::Context.new({ user: "alice" })
7
+
8
+ expect(context.to_h).to eq({ user: "alice" })
9
+ expect(context.to_h).to be_frozen
10
+ end
11
+
12
+ it "converts non-hash to empty hash" do
13
+ context = DecisionAgent::Context.new("not a hash")
14
+
15
+ expect(context.to_h).to eq({})
16
+ end
17
+
18
+ it "deep freezes nested hashes" do
19
+ data = { user: { name: "alice", roles: ["admin"] } }
20
+ context = DecisionAgent::Context.new(data)
21
+
22
+ expect(context.to_h[:user]).to be_frozen
23
+ expect(context.to_h[:user][:roles]).to be_frozen
24
+ end
25
+ end
26
+
27
+ describe "#[]" do
28
+ it "retrieves values by key" do
29
+ context = DecisionAgent::Context.new({ status: "active" })
30
+
31
+ expect(context[:status]).to eq("active")
32
+ end
33
+
34
+ it "returns nil for missing keys" do
35
+ context = DecisionAgent::Context.new({})
36
+
37
+ expect(context[:missing]).to be_nil
38
+ end
39
+ end
40
+
41
+ describe "#fetch" do
42
+ it "retrieves values by key" do
43
+ context = DecisionAgent::Context.new({ priority: "high" })
44
+
45
+ expect(context.fetch(:priority)).to eq("high")
46
+ end
47
+
48
+ it "returns default for missing keys" do
49
+ context = DecisionAgent::Context.new({})
50
+
51
+ expect(context.fetch(:missing, "default")).to eq("default")
52
+ end
53
+ end
54
+
55
+ describe "#key?" do
56
+ it "returns true when key exists" do
57
+ context = DecisionAgent::Context.new({ user: "alice" })
58
+
59
+ expect(context.key?(:user)).to be true
60
+ end
61
+
62
+ it "returns false when key does not exist" do
63
+ context = DecisionAgent::Context.new({})
64
+
65
+ expect(context.key?(:user)).to be false
66
+ end
67
+ end
68
+
69
+ describe "#==" do
70
+ it "compares contexts by data equality" do
71
+ context1 = DecisionAgent::Context.new({ user: "alice" })
72
+ context2 = DecisionAgent::Context.new({ user: "alice" })
73
+
74
+ expect(context1).to eq(context2)
75
+ end
76
+
77
+ it "returns false for different data" do
78
+ context1 = DecisionAgent::Context.new({ user: "alice" })
79
+ context2 = DecisionAgent::Context.new({ user: "bob" })
80
+
81
+ expect(context1).not_to eq(context2)
82
+ end
83
+ end
84
+ end